diff --git a/APPSTORE.md b/APPSTORE.md index 46f8585..3390ece 100644 --- a/APPSTORE.md +++ b/APPSTORE.md @@ -27,7 +27,6 @@ For Homey to be able to communicate with devices over the miIO protocol a unique Xiaomi has recently released an update for its v1 vacuum that enabled it for the zoned cleaning and goto function that was previously only available to the v2 vacuum. Using the action cards that utilize these functions are a bit challenging. If you want to use these cards please read the instructions [here](https://github.com/jghaanstra/com.xiaomi-miio/blob/master/docs/mirobot_zonecleanup.md). ## Changelog -### v2.11.2 - 2019-02-25 -* NEW: settings Yeelights to 0% dim will turn them off, also within the change dim over time card (except for the JIAOYUE ceilight which will toggle night mode when set to 0% twice in 5 seconds) -* IMPROVEMENT: changed callbacks to promises for Yeelight driver -* IMPROVEMENT: moved Yeelight settings from data to settings object to prevent issues when re-pairing without restarting the app +### v2.11.3 - 2019-02-28 +* FIX: fixed a bug in the pairing of Yeelights which was introduced in the previous release +* NEW: added functionality for automatically updating a Yeelight IP address when a change has been detected (when using DHCP instead of statip IP for instance) diff --git a/app.json b/app.json index 2d41da2..096043e 100644 --- a/app.json +++ b/app.json @@ -10,7 +10,7 @@ "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.11.2", + "version": "2.11.3", "compatibility": ">=2.0.0", "author": { "name": "Jelger Haanstra", diff --git a/drivers/yeelights/device.js b/drivers/yeelights/device.js index 2883909..6a80ed8 100644 --- a/drivers/yeelights/device.js +++ b/drivers/yeelights/device.js @@ -18,12 +18,8 @@ class YeelightDevice extends Homey.Device { yeelights[id].connecting = false; yeelights[id].connected = false; - // MOVE SETTINGS TO SETTINGS OBJECT FROM 2.11.2 - if (!this.getSetting('address')) { - var address = this.getData().address; - var port = this.getData().port; - this.setSettings({address: address, port: port}); - } + // FILL TEMP DEVICES FOR PAIRING + yeelight.fillAddedDevices(); this.createDeviceSocket(id); diff --git a/drivers/yeelights/driver.js b/drivers/yeelights/driver.js index 7efc5fb..930b95f 100644 --- a/drivers/yeelights/driver.js +++ b/drivers/yeelights/driver.js @@ -54,7 +54,7 @@ class YeelightDriver extends Homey.Driver { for (let i in result) { if(result[i].model.startsWith('color')) { var name = Homey.__('yeelight_bulb_color')+ ' (' + result[i].address + ')'; - } else if (result[i].startsWith('mono')) { + } else if (result[i].model.startsWith('mono')) { var name = Homey.__('yeelight_bulb_white')+ ' (' + result[i].address + ')'; } else if (result[i].model == 'ct') { var name = Homey.__('yeelight_bulb_white_v2')+ ' (' + result[i].address + ')'; diff --git a/lib/yeelight.js b/lib/yeelight.js index 5226a08..6cfdef6 100644 --- a/lib/yeelight.js +++ b/lib/yeelight.js @@ -2,19 +2,33 @@ const Homey = require('homey'); const dgram = require('dgram'); const advertisements = dgram.createSocket('udp4'); -var temp_devices = {}; +var new_devices = {}; +var added_devices = {}; + + +/* send discovery message during pair wizard */ +exports.fillAddedDevices = function () { + var yeelights = Homey.ManagerDrivers.getDriver('yeelights').getDevices(); + Object.keys(yeelights).forEach(function(key) { + added_devices[yeelights[key].getData().id] = { + id: yeelights[key].getData().id, + address: yeelights[key].getSetting('address'), + port: yeelights[key].getSetting('port') + }; + }); +} /* send discovery message during pair wizard */ exports.discover = function () { return new Promise(resolve => { var message = 'M-SEARCH * HTTP/1.1\r\nMAN: \"ssdp:discover\"\r\nST: wifi_bulb\r\n'; var broadcast = () => advertisements.send(message, 0, message.length, 1982, "239.255.255.250"); - var broadcastInterval = setInterval(broadcast, 4000); + var broadcastInterval = setInterval(broadcast, 3000); broadcast(); setTimeout(() => { clearInterval(broadcastInterval); - resolve(temp_devices); + resolve(new_devices); }, 4000); }); } @@ -31,14 +45,23 @@ exports.listenUpdates = function () { process.nextTick(function() { parseMessage(message) .then(result => { - if (!temp_devices.hasOwnProperty(result.device.id)) { - temp_devices[result.device.id] = result.device; - } - if (result.message_type != 'discover') { + if (result !== 'no devices') { var yeelights = Homey.ManagerDrivers.getDriver('yeelights').getDevices(); Object.keys(yeelights).forEach(function(key) { - if(yeelights[key].getData().id == result.device.id && !yeelights[key].isConnected(result.device.id)) { - yeelights[key].createDeviceSocket(result.device.id); + + // new devices for pairing + if (!new_devices.hasOwnProperty(result.device.id) && added_devices.hasOwnProperty(yeelights[key].getData().id)) { + new_devices[result.device.id] = result.device; + } + + // update ip for changed ip's + if (result.message_type != 'discover' && yeelights[key].getData().id == result.device.id && (yeelights[key].getSetting('address') != result.device.address || yeelights[key].getSetting('port') != result.device.port) ) { + yeelights[key].setSettings({address: result.device.address, port: result.device.port}); + } + + // new sockets for broken devices + if (result.message_type != 'discover' && yeelights[key].getData().id == result.device.id && !yeelights[key].isConnected(result.device.id)) { + yeelights[key].createDeviceSocket(result.device.id); } }); } @@ -68,44 +91,48 @@ function parseMessage(message) { var message_type = 'discover'; } - headers = headers.split("\r\nLocation:").pop(); - headers = headers.substring(0, headers.indexOf("\r\nname:")); - headers = 'Location:'+ headers+''; - headers = headers.replace(re, '": "'); - headers = headers.replace(re2, '",\r\n"'); - headers = '{ "'+ headers +'" }'; - - var result = JSON.parse(headers); - - var location = result.Location.split(':'); - var address = location[1].replace('//', ''); - var port = parseInt(location[2], 10); - - if (result.power == 'on') { - var onoff = true; + if (!headers.includes('ssdp:discover')) { + headers = headers.split("\r\nLocation:").pop(); + headers = headers.substring(0, headers.indexOf("\r\nname:")); + headers = 'Location:'+ headers+''; + headers = headers.replace(re, '": "'); + headers = headers.replace(re2, '",\r\n"'); + headers = '{ "'+ headers +'" }'; + + var result = JSON.parse(headers); + + var location = result.Location.split(':'); + var address = location[1].replace('//', ''); + var port = parseInt(location[2], 10); + + if (result.power == 'on') { + var onoff = true; + } else { + var onoff = false; + } + + var device = { + id: result.id, + address: address, + port: port, + model: result.model, + onoff: onoff, + dim: parseInt(result.bright), + mode: parseInt(result.color_mode), + temperature: parseInt(result.ct), + rgb: parseInt(result.rgb), + hue: parseInt(result.hue), + saturation: parseInt(result.sat), + connected: false + } + + return resolve({ + message_type: message_type, + device: device + }); } else { - var onoff = false; - } - - var device = { - id: result.id, - address: address, - port: port, - model: result.model, - onoff: onoff, - dim: parseInt(result.bright), - mode: parseInt(result.color_mode), - temperature: parseInt(result.ct), - rgb: parseInt(result.rgb), - hue: parseInt(result.hue), - saturation: parseInt(result.sat), - connected: false + return resolve('no devices'); } - - return resolve({ - message_type: message_type, - device: device - }); } catch (error) { return reject(error); } diff --git a/package.json b/package.json index 5e8da00..9f27021 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.xiaomi-miio", - "version": "2.11.2", + "version": "2.11.3", "description": "Xiaomi Mi Home", "main": "app.js", "dependencies": {