diff --git a/APPSTORE.md b/APPSTORE.md
index 09a27d8..a663427 100644
--- a/APPSTORE.md
+++ b/APPSTORE.md
@@ -12,6 +12,7 @@ Below is a list of supported devices and devices. Post a comment in the [support
* Xiamomi Humidifier (tested)
* Xiaomi Single Power Plug and Power Strip WiFi version (tested)
* Xiaomi PM2.5 Air Monitor (tested)
+* Xiaomi Gateway Light - alarm not supported yet and subdevices are supported directly with the Xiaomi ZigBee app (tested)
## Support topic
For support please use the official support topic on the forum [here](https://forum.athom.com/discussion/3295/).
@@ -46,6 +47,11 @@ For Homey to be able to communicate with devices over the miIO protocol a unique
* Default flow cards for on/off, measure power and meter power capabilities class
## Changelog
+### 2018-03-15 -- v2.6.2
+* NEW: add support for the Xiaomi Gateway Light - alarm not supported yet and subdevices are supported directly with the Xiaomi ZigBee app
+* FIX: fix for pairing wizard Philips Light Bulbs
+* FIX: small fix in Yeelights driver
+
### 2018-03-04 -- v2.6.1
* CHANGE: updated device class of Mi Power Plug and Mi Power Strip to "socket" (this require re-pairing of these devices)
* FIX: solved small device naming issue in pair wizard
diff --git a/app.json b/app.json
index 89f9a0d..dab47f3 100644
--- a/app.json
+++ b/app.json
@@ -6,10 +6,10 @@
"nl": "Xiaomi Mi Home"
},
"tags": {
- "en": [ "Xiaomi", "Mi", "Mi Home", "miio", "vacuumcleaner", "robot", "yeelight", "yeelights", "purifier", "humidifier", "philips", "eyecare", "powerplug" ],
- "nl": [ "Xiaomi", "Mi", "Mi home", "miio", "stofzuiger", "robot", "yeelight", "yeelights", "luchtreiniger", "luchtbevochtiger", "philips", "eyecare", "powerplug" ]
+ "en": [ "Xiaomi", "Mi", "Mi Home", "miio", "vacuumcleaner", "robot", "yeelight", "yeelights", "purifier", "humidifier", "philips", "eyecare", "powerplug", "gateway" ],
+ "nl": [ "Xiaomi", "Mi", "Mi home", "miio", "stofzuiger", "robot", "yeelight", "yeelights", "luchtreiniger", "luchtbevochtiger", "philips", "eyecare", "powerplug", "gateway" ]
},
- "version": "2.6.1",
+ "version": "2.6.2",
"compatibility": "1.x >=1.5.0",
"author": {
"name": "Jelger Haanstra",
@@ -663,6 +663,92 @@
]
}
]
+ },
+ {
+ "id": "gateway",
+ "name": {
+ "en": "Gateway",
+ "nl": "Gateway"
+ },
+ "images": {
+ "large": "drivers/gateway/assets/images/large.jpg",
+ "small": "drivers/gateway/assets/images/small.jpg"
+ },
+ "class": "other",
+ "capabilities": [
+ "onoff",
+ "dim",
+ "light_hue",
+ "light_saturation",
+ "measure_luminance"
+ ],
+ "mobile": {
+ "components": [
+ {
+ "id": "icon",
+ "capabilities": [ "onoff" ]
+ },
+ {
+ "id": "sensor",
+ "capabilities": [ "measure_luminance" ]
+ },
+ {
+ "id": "slider",
+ "capabilities": [ "dim" ]
+ },
+ {
+ "id": "color",
+ "capabilities": [ "light_hue", "light_saturation" ]
+ }
+ ]
+ },
+ "pair": [
+ {
+ "id": "start"
+ }
+ ],
+ "settings": [
+ {
+ "type": "group",
+ "label": {
+ "en": "Gateway Settings",
+ "nl": "Gateway Instellingen"
+ },
+ "children": [
+ {
+ "id": "address",
+ "type": "text",
+ "value": "0.0.0.0",
+ "label": {
+ "en": "IP Address",
+ "nl": "IP Adres"
+ }
+ },
+ {
+ "id": "token",
+ "type": "text",
+ "value": "",
+ "label": {
+ "en": "Gateway Token",
+ "nl": "Gateway Token"
+ }
+ },
+ {
+ "id": "polling",
+ "type": "number",
+ "value": 60,
+ "attr": {
+ "min": 5,
+ "max": 3600
+ },
+ "label": {
+ "en": "Gateway Polling",
+ "nl": "Gateway Polling"
+ }
+ }
+ ]
+ }
+ ]
}
],
"flow": {
diff --git a/drivers/air-monitor/pair/start.html b/drivers/air-monitor/pair/start.html
index b9a98c7..9146770 100644
--- a/drivers/air-monitor/pair/start.html
+++ b/drivers/air-monitor/pair/start.html
@@ -11,7 +11,7 @@
var inputaddress = $('#address').val();
var inputtoken = $('#token').val();
- if( inputaddress != '' && inputtoken != '') {
+ if (inputaddress != '' && inputtoken != '') {
var device_data = {
address: inputaddress,
token: inputtoken
@@ -132,7 +132,7 @@
-
+
diff --git a/drivers/gateway/assets/icon.svg b/drivers/gateway/assets/icon.svg
new file mode 100644
index 0000000..75b8176
--- /dev/null
+++ b/drivers/gateway/assets/icon.svg
@@ -0,0 +1,1618 @@
+
+
+
diff --git a/drivers/gateway/assets/images/large.jpg b/drivers/gateway/assets/images/large.jpg
new file mode 100644
index 0000000..abe26bc
Binary files /dev/null and b/drivers/gateway/assets/images/large.jpg differ
diff --git a/drivers/gateway/assets/images/small.jpg b/drivers/gateway/assets/images/small.jpg
new file mode 100644
index 0000000..93fe9d2
Binary files /dev/null and b/drivers/gateway/assets/images/small.jpg differ
diff --git a/drivers/gateway/device.js b/drivers/gateway/device.js
new file mode 100644
index 0000000..ca6b810
--- /dev/null
+++ b/drivers/gateway/device.js
@@ -0,0 +1,125 @@
+'use strict';
+
+const Homey = require('homey');
+const util = require('/lib/util.js');
+const miio = require('miio');
+const tinycolor = require("tinycolor2");
+
+class GatewayDevice extends Homey.Device {
+
+ onInit() {
+ this.createDevice();
+
+ this.registerCapabilityListener('onoff', this.onCapabilityOnoff.bind(this));
+ this.registerCapabilityListener('dim', this.onCapabilityDim.bind(this));
+ this.registerMultipleCapabilityListener(['light_hue', 'light_saturation'], this.onCapabilityHueSaturation.bind(this), 500);
+ }
+
+ onDeleted() {
+ clearInterval(this.pollingInterval);
+ this.miio.destroy();
+ }
+
+ // LISTENERS FOR UPDATING CAPABILITIES
+ onCapabilityOnoff(value, opts, callback) {
+ this.miio.light.setPower(value)
+ .then(result => { callback(null, value) })
+ .catch(error => { callback(error, false) });
+ }
+
+ onCapabilityDim(value, opts, callback) {
+ var brightness = value * 100;
+ this.miio.light.setBrightness(brightness)
+ .then(result => { callback(null, value) })
+ .catch(error => { callback(error, false) });
+ }
+
+ onCapabilityHueSaturation(valueObj, optsObj) {
+ if (typeof valueObj.light_hue !== 'undefined') {
+ var hue_value = valueObj.light_hue;
+ } else {
+ var hue_value = this.getCapabilityValue('light_hue');
+ }
+
+ if (typeof valueObj.light_saturation !== 'undefined') {
+ var saturation_value = valueObj.light_saturation;
+ } else {
+ var saturation_value = this.getCapabilityValue('light_saturation');
+ }
+
+ var hue = hue_value * 359;
+ var saturation = saturation_value * 100;
+ var dim = this.getCapabilityValue('dim') * 100
+ var colorUpdate = tinycolor({ h: Math.round(hue), s: Math.round(saturation), v: dim });
+ this.miio.light.color(colorUpdate.toRgbString())
+
+ return Promise.resolve();
+ }
+
+ // HELPER FUNCTIONS
+ createDevice() {
+ miio.device({
+ address: this.getSetting('address'),
+ token: this.getSetting('token')
+ }).then(miiodevice => {
+ this.miio = miiodevice;
+ this.miio.light = miiodevice.child('light');
+
+ miiodevice.on('illuminanceChanged', illuminance => {
+ if (this.getCapabilityValue('measure_luminance') != illuminance.value) {
+ this.setCapabilityValue('measure_luminance', illuminance.value);
+ }
+ });
+
+ this.miio.light.on('colorChanged', c => {
+ var colorChanged = tinycolor({r: c.rgb.red, g: c.rgb.green, b: c.rgb.blue});
+ var hsv = colorChanged.toHsv();
+ var hue = Math.round(hsv.h) / 359;
+ var saturation = Math.round(hsv.s);
+
+ if (this.getCapabilityValue('light_hue') != hue) {
+ this.setCapabilityValue('light_hue', hue);
+ }
+
+ if (this.getCapabilityValue('light_saturation') != saturation) {
+ this.setCapabilityValue('light_saturation', saturation);
+ }
+ });
+
+ var interval = this.getSetting('polling') || 60;
+ this.pollDevice(interval);
+ }).catch(function (error) {
+ return reject(error);
+ });
+ }
+
+ pollDevice(interval) {
+ clearInterval(this.pollingInterval);
+
+ this.pollingInterval = setInterval(() => {
+ const getData = async () => {
+ try {
+ const power = await this.miio.light.power();
+ const brightness = await this.miio.light.brightness()
+
+ if (this.getCapabilityValue('onoff') != power) {
+ this.setCapabilityValue('onoff', power);
+ }
+ var dim = brightness / 100;
+ if (this.getCapabilityValue('dim') != dim) {
+ this.setCapabilityValue('dim', dim);
+ }
+ if (!this.getAvailable()) {
+ this.setAvailable();
+ }
+ } catch (error) {
+ this.setUnavailable(Homey.__('unreachable'));
+ this.log(error);
+ }
+ }
+ getData();
+ }, 1000 * interval);
+ }
+}
+
+module.exports = GatewayDevice;
diff --git a/drivers/gateway/driver.js b/drivers/gateway/driver.js
new file mode 100644
index 0000000..14af5df
--- /dev/null
+++ b/drivers/gateway/driver.js
@@ -0,0 +1,36 @@
+"use strict";
+
+const Homey = require('homey');
+const miio = require('miio');
+
+class GatewayDriver extends Homey.Driver {
+
+ onPair(socket) {
+ socket.on('testConnection', function(data, callback) {
+ miio.device({
+ address: data.address,
+ token: data.token
+ }).then(device => {
+ const getData = async () => {
+ try {
+ const lightLevel = await device.illuminance();
+
+ let result = {
+ lux: lightLevel.lux
+ }
+
+ callback(null, result);
+ } catch (error) {
+ callback(error, null);
+ }
+ }
+ getData();
+ }).catch(function (error) {
+ callback(error, null);
+ });
+ });
+ }
+
+}
+
+module.exports = GatewayDriver;
diff --git a/drivers/gateway/pair/start.html b/drivers/gateway/pair/start.html
new file mode 100644
index 0000000..bbcad7a
--- /dev/null
+++ b/drivers/gateway/pair/start.html
@@ -0,0 +1,146 @@
+
+
+
+
+
Enter the details of your Mi Home device.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Connection test successfull, you can now connect the device.
+
Mi Home device added succesfully.
+
+
diff --git a/drivers/philips-bulb/pair/start.html b/drivers/philips-bulb/pair/start.html
index 3195e1f..ef2f8d7 100644
--- a/drivers/philips-bulb/pair/start.html
+++ b/drivers/philips-bulb/pair/start.html
@@ -11,7 +11,7 @@
var inputaddress = $('#address').val();
var inputtoken = $('#token').val();
- if( inputaddress != '' && inputtoken != '') {
+ if (inputaddress != '' && inputtoken != '') {
var device_data = {
address: inputaddress,
token: inputtoken
@@ -33,7 +33,6 @@
$('.mi-device-error-msg').html( __('pair.unknownerror') );
}
});
- });
} else {
$('.mi-device-error').show();
diff --git a/drivers/philips-eyecare/pair/start.html b/drivers/philips-eyecare/pair/start.html
index caa081b..eeb5c6c 100644
--- a/drivers/philips-eyecare/pair/start.html
+++ b/drivers/philips-eyecare/pair/start.html
@@ -11,7 +11,7 @@
var inputaddress = $('#address').val();
var inputtoken = $('#token').val();
- if( inputaddress != '' && inputtoken != '') {
+ if (inputaddress != '' && inputtoken != '') {
var device_data = {
address: inputaddress,
token: inputtoken
@@ -35,7 +35,6 @@
$('.mi-device-error-msg').html( __('pair.unknownerror') );
}
});
- });
} else {
$('.mi-device-error').show();
diff --git a/drivers/yeelights/device.js b/drivers/yeelights/device.js
index 24b7826..76720ed 100644
--- a/drivers/yeelights/device.js
+++ b/drivers/yeelights/device.js
@@ -257,14 +257,16 @@ class YeelightDevice extends Homey.Device {
/* send commands to devices using their socket connection */
sendCommand(id, command) {
- if (yeelights[id].connected === false) {
+ if (yeelights[id].connected === false && yeelights[id].socket !== null) {
yeelights[id].socket.emit('error', new Error('Connection to device broken'));
} else {
yeelights[id].socket.write(command + '\r\n');
if (yeelights[id].timeout === null) {
yeelights[id].timeout = setTimeout(() => {
- yeelights[id].socket.emit('error', new Error('Error sending command'));
+ if (yeelights[id].connected === true && yeelights[id].socket !== null) {
+ yeelights[id].socket.emit('error', new Error('Error sending command'));
+ }
}, 3000);
}
}
diff --git a/locales/en.json b/locales/en.json
index 80d7af7..11aa6c0 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -7,12 +7,14 @@
"humidifier": "Humidifier",
"philipsbulb": "Philips Light Bulb",
"philipseyecare": "Philips Eyecare Lamp",
+ "gateway": "Xiaomi Gateway",
"airmonitor": "PM2.5 Air Monitor",
"powerplug": "Mi Power Plug",
"powerstrip": "Mi Power Strip",
"powered": "Powered:",
"mode": "Mode:",
"dim": "Dim Level:",
+ "lux": "Lux:",
"temperature": "Temperature:",
"colortemperature": "Color Temperature:",
"load": "Current Load In Watt:",
diff --git a/locales/nl.json b/locales/nl.json
index 3ad9986..82871e9 100644
--- a/locales/nl.json
+++ b/locales/nl.json
@@ -7,12 +7,14 @@
"humidifier": "Luchtbevochtiger",
"philipsbulb": "Philips Light Bulb",
"philipseyecare": "Philips Eyecare Lamp",
+ "gateway": "Xiaomi Gateway",
"airmonitor": "PM2.5 Air Monitor",
"powerplug": "Mi Power Plug",
"powerstrip": "Mi Power Strip",
"powered": "Aangezet:",
"mode": "Modus:",
"dim": "Dim niveau:",
+ "lux": "Lux:",
"temperature": "Temperatuur:",
"colortemperature": "Kleurtemperatuur:",
"load": "Huidige gebruik in Watt:",
diff --git a/package.json b/package.json
index 49dda2b..99311c5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "com.xiaomi-miio",
- "version": "2.6.1",
+ "version": "2.6.2",
"description": "Xiaomi Mi Home",
"main": "app.js",
"dependencies": {