text:
Handling multiple connections fails

I have a setup using Node Red. How do I handle multiple requests? This code seems to work ok for 2 requests but has problems with more than 2.
if(msg.topic.indexOf('zigbee_light') !== -1)
{
    var lightify = global.get('lightify');
    var connection = new lightify.lightify('192.168.0.41');
    connection.connect().then(function()
    {
        return connection.discover();
    })
    .then(function(data)
    {
        var devices = data.result;

        if(msg.topic.endsWith('/set'))
        {
            var device_no = (msg.topic.substring(
                    msg.topic.indexOf('zigbee_light') + 12,
                    msg.topic.indexOf('zigbee_light') + 13));

            var state = parseInt(msg.payload, 10);

            devices.forEach(
                device =>
                {
                    var check = 'A19 W 60 0' + device_no;
                    if(device.name === check)
                    {
                        new Promise(function(resolve, reject) {
                            resolve(connection.nodeSoftOnOff(device.mac,
                            state, 0))
                            reject(function()
                            {
                                node.warn('Rejected');
                                connection.dispose();
                                flow.set('connection', undefined);
                            });
                        }).then(function(data)
                        {
                            return connection.nodeOnOff(device.mac, state,
                            0);
                        })
                        .then(function(data)
                        {
                            connection.dispose();
                            flow.set('connection', undefined);
                        })
                        .catch(function(error)
                        {
                        	node.warn(error);
                        	flow.set('connection', undefined)
                        });
                    }
                }
            );
        }
}

You should have a buffer to handle incoming requests as well as some watchdog timers to handle a non-responsive gateway - which happens quite often. Here is my flow for using Lightify. It works nicely. The input node can accept commands from HomeKit if you're into that. There are some inject timers that initialize it in the case of a node-red restart. I don't have time at the moment to explain it in detail but if you run into issues let me know.
[{"id":"4006453f.1d432c","type":"subflow","name":"FIFO","info":"# FIFO\n## First in First Out subflow\nThis flow receives a series of msg.payloads and builds a queue using FIFO (First in First out) method. The LIFO size is configurabe through subflow enviroment variables.\n\n### Input\nmsg.topic == put\nWill add the msg.payload to the end of the array. Everytime a new item is received the second output sends the complete queue.\n\nmsg.topic == get\nWill remove the first item of the stack and will send it in the first output\n\nmsg.topic == list\nSends the complete list on the second output.\n\n### Output 1\nThe first item on the top of the stack. It is sent only when msg.topic == get.\n\n### Output 2\nThe complete queue in Array format. It is sent everytime a new item is added, removed or when msg.topic == list\n\n### Status\nAlways show the queue size.\n\n### Enviroment Variables\nBuffer_Size defines the size of the queue. If a new item arrives and the queue is full, the oldest item will be removed.","category":"","in":[{"x":60,"y":180,"wires":[{"id":"81bd46c3.2c5048"}]}],"out":[{"x":640,"y":120,"wires":[{"id":"ac2f383.195b9c8","port":0}]},{"x":640,"y":180,"wires":[{"id":"bb92ce78.e93eb","port":0}]}],"env":[{"name":"Buffer_Size","type":"num","value":"6"}],"icon":"font-awesome/fa-ellipsis-v","status":{"x":800,"y":200,"wires":[{"id":"23d5f18b.05c706","port":0}]}},{"id":"81bd46c3.2c5048","type":"switch","z":"4006453f.1d432c","name":"Topic","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"get","vt":"str"},{"t":"eq","v":"put","vt":"str"},{"t":"eq","v":"list","vt":"str"},{"t":"eq","v":"flush","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":5,"x":190,"y":180,"wires":[["ac2f383.195b9c8"],["7b2aff73.43371"],["bb92ce78.e93eb"],["2eb96832.d1682"],["bb92ce78.e93eb"]]},{"id":"ac2f383.195b9c8","type":"function","z":"4006453f.1d432c","name":"get","func":"var queue = flow.get("queue")\nvar item;\n\nif (!Array.isArray(queue)){\n    queue = [];\n}else{\n    item = queue.pop(1);\n}\n\n\nflow.set("queue", queue)\nmsg.payload = item;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":120,"wires":[["bb92ce78.e93eb"]]},{"id":"bb92ce78.e93eb","type":"change","z":"4006453f.1d432c","name":"list","rules":[{"t":"set","p":"payload","pt":"msg","to":"queue","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":260,"wires":[["23d5f18b.05c706"]]},{"id":"23d5f18b.05c706","type":"change","z":"4006453f.1d432c","name":"Count","rules":[{"t":"set","p":"payload","pt":"msg","to":"$count(msg.payload)\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":260,"wires":[[]]},{"id":"7b2aff73.43371","type":"function","z":"4006453f.1d432c","name":"put","func":"var queue = flow.get("queue")\n\n\nif (!Array.isArray(queue)){\n    queue = [];\n}else if ( queue.length >= env.get("Buffer_Size") ){\n    queue.pop(1);\n}\n\nqueue.unshift(msg.payload);\n\nflow.set("queue", queue);\nmsg.payload = queue;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":160,"wires":[["bb92ce78.e93eb"]]},{"id":"80f36e5b.2e44c","type":"debug","z":"4006453f.1d432c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":530,"y":40,"wires":[]},{"id":"3a25842a.9042dc","type":"debug","z":"4006453f.1d432c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":730,"y":60,"wires":[]},{"id":"2eb96832.d1682","type":"function","z":"4006453f.1d432c","name":"flush","func":"var queue = flow.get("queue")\n\n\nif (!Array.isArray(queue)){\n    queue = [];\n}else{\n    while (queue.length > 0){\n        queue.pop();\n    }\n}\n\nflow.set("queue", queue);\nmsg.payload = queue;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":200,"wires":[["bb92ce78.e93eb"]]},{"id":"d60169b2.b83b","type":"function","z":"4ad1e2f.135b39c","name":"Lightify In","func":"//            "platform": "Lightify",\n//            "bridge_ip": "192.168.0.16",\n//            "name": "Lightify",\n//            "showGroups": true,\n//            "hideNodes": false,\n//\t\t\t  "pollFreqSecs" : "2"\n                \n//var bridge_ip = "192.168.0.16"; // bridge 2\nvar bridge_ip = "192.168.0.28"; // bridge 1\nvar showGroups = true;\nvar hideNodes = false;\n\nvar moment = global.get('moment');\nvar util = global.get('util');\nvar lightify = global.get("lightify");\nvar Service, Characteristic;\nvar Lightbulb;  \nvar log = node;\nvar BusyTimerTimeMs = 20000;\n\n// how long node-lightify should wait before timing out the connection to the bridge.\n// this should ideally be shorter than your poll rate. note that this depends on a modified copy\n// of node-lightify as the master branch does not have this feature.\nvar cfgLightifyBridgeConnectTimeout = 10000; // ms\n// how many counts to pass before retrying a connection to the unresponsive gateway.\n// set this to a value greater than cfgLightifyBridgeConnectTimeout above.\nvar cfgLightifyRetryCount = 10; \n\nvar LightifyRetryCount = flow.get("LightifyRetryCount", 'memoryOnly') || 0;\nvar LightifyIsResponding = flow.get("LightifyIsResponding", 'memoryOnly') || 0;\nvar LightifyIsBusy = flow.get("LightifyIsBusy", 'memoryOnly') || 0;\nvar LightifyGettingGroups = flow.get("LightifyGettingGroups", 'memoryOnly') || false;\n\nif (LightifyIsBusy === 0) {\n    SetBusyTimer(BusyTimerTimeMs);\n    if (LightifyIsResponding > 0 || LightifyRetryCount >= cfgLightifyRetryCount) { \n        if (LightifyIsResponding === 0 && LightifyRetryCount >= cfgLightifyRetryCount) {\n            node.warn('Lightify is responding again!')\n            flow.set("LightifyIsResponding",1, 'memoryOnly');\n        }\n        if (LightifyRetryCount > cfgLightifyRetryCount) {\n            node.warn('Retrying Lightify connection.')\n        }\n        flow.set("LightifyRetryCount",0, 'memoryOnly');\n        findAccessories();\n    } else {\n        node.warn('Lightify is not responding. Incrementing retry counter ' + (cfgLightifyRetryCount - LightifyRetryCount) + ' times.')\n        flow.set("LightifyRetryCount",LightifyRetryCount + 1, 'memoryOnly');\n        ClearBusyTimer();\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire){\n    \n    // show lightify as busy\n    flow.set("LightifyIsBusy",1, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function(){\n                                        // do some stuff here if timeout\n                                        node.warn('Lightify Busy Timer Expired');\n                                        flow.set("LightifyIsBusy",0, 'memoryOnly');\n                                    }, TimeTillExpire || 5000);\n                                    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly')\n    \n}\n\nfunction ClearBusyTimer(){\n    \n    // show lightify as not busy\n    flow.set("LightifyIsBusy",0, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly');\n    \n}\n\nfunction findAccessories() {\n    var self = this;\n    var connection = new lightify.lightify(bridge_ip);\n    discover(connection).then(function(data) {\n        //var foundAccessories = [];\n        data.result.forEach(function(light) {\n            var msg_out_light = Object.assign({},msg); // create new message\n            msg_out_light.topic = light.name;\n            //msg_out_light.payload = '';\n            light.isBrightnessSupported = lightify.isBrightnessSupported(light.type);\n            light.isColorSupported = lightify.isColorSupported(light.type);\n            light.isTemperatureSupported = lightify.isTemperatureSupported(light.type);\n            light.isLight = lightify.isLight(light.type);\n            light.isSwitch = lightify.isSwitch(light.type);\n            light.isPlug = lightify.isPlug(light.type);\n            light.isSensor = lightify.isSensor(light.type);\n            msg_out_light.light = light;\n            node.send(msg_out_light);\n            /\n            if(!hideNodes && light.type && lightify.isLight(light.type)) {\n                //node.warn('Lightify Light [%s]', light.name);\n                foundAccessories.push(new LightifyAccessory(self, light));\n                //msg.light.name = light.name;\n                //msg.light.type = light.type;\n                //msg.light.status = light.status;\n                //node.send(msg);\n            } else if (!hideNodes && light.type && lightify.isPlug(light.type)) {\n                //node.warn('Lightify Plug [%s]', light.name);\n                foundAccessories.push(new LightifyOutlet(self, light));\n            } else if (!hideNodes && light.type && lightify.isSensor(light.type)) {\n                //node.warn('Lightify Sensor [%s]', light.name);\n                foundAccessories.push(new LightifySensor(self, light));\n            } else if(!light.type) {\n                foundAccessories.push(new LightifyAccessory(self, light));\n            }\n            /\n        });\n        connection.dispose();\n        \n        flow.set("LightifyIsResponding",1, 'memoryOnly');\n        ClearBusyTimer();\n        flow.set("LightifyGettingGroups",!LightifyGettingGroups, 'memoryOnly'); // get groups every other message\n        \n        //var elapsedTime = Date.now() - msg.payload;\n        //node.warn('Elasped Time: ' + elapsedTime.toString() + ' ms');\n    }).catch(function(error) {\n        flow.set("LightifyIsResponding",0, 'memoryOnly');\n        ClearBusyTimer();\n        node.warn('Discovered failed', error);\n    });\n}\n    \nfunction discover(connection) {\n    var self = this;\n    return connection.connect(cfgLightifyBridgeConnectTimeout).then(function() {\n        //have to discover nodes for light status of group\n        //var elapsedTime = Date.now() - msg.payload;\n        //node.warn('Discovered light nodes: ' + elapsedTime.toString() + ' ms');\n        return connection.discover();\n    }).then(function(data) {\n        //return !showGroups ? Promise.resolve(data) :\n        return !LightifyGettingGroups ? Promise.resolve(data) :\n        new Promise(function(resolve, reject) {\n            //node.warn('discover zones');\n            connection.discoverZone()\n            .then(function(zones) {\n                //var elapsedTime = Date.now() - msg.payload;\n                //node.warn('Discovered zones: ' + elapsedTime.toString() + ' ms');\n                //get zone info. if one of them is off, then this group is off\n                zones.result.reduce(function(av, zone){\n                    return av.then(function() {\n                        return connection\n                        .getZoneInfo(zone.id)\n                        .then(function(zoneInfo){\n                            //var elapsedTime = Date.now() - msg.payload;\n                            //node.warn('Got zone info: ' + elapsedTime.toString() + ' ms');\n                            zone.online = 2; // group always online\n                            zone.status = 0; // default to off\n                            zone.isBrightnessSupported = false;\n                            zone.isColorSupported = false;\n                            zone.isTemperatureSupported = false;\n                            if(!zoneInfo.result || zoneInfo.result.length === 0) {\n                                return Promise.reject('no result for zone');\n                            }\n                            //node.warn(zoneInfo.result);\n                            for (var mac of zoneInfo.result[0].devices) {\n                                //var elapsedTime = Date.now() - msg.payload;\n                                //node.warn('Got zone device info: ' + elapsedTime.toString() + ' ms');\n                                //node.warn('getting mac');\n                                var device = data.result.find(function(d) {\n                                    return d.mac === mac;\n                                });\n                                //node.warn(device);\n                                if (device && device.online && device.status === 1) {\n                                    zone.status = 1;\n                                    //node.warn('Lightify Zone is on');\n                                }\n                                if(device && lightify.isBrightnessSupported(device.type)) {\n                                    zone.isBrightnessSupported = true;\n                                    zone.brightness = device.brightness;\n                                    //node.warn('Lightify Zone support brightness, current brightness=[%d]', device.brightness);\n                                }\n                                if(device && lightify.isColorSupported(device.type)) {\n                                    zone.isColorSupported = true;\n                                    zone.red = device.red;\n                                    zone.green = device.green;\n                                    zone.blue = device.blue;\n                                    //c = device.blue; // why was this here??\n                                    //node.warn('Lightify Zone support color, current red=[%d], green=[%d], blue=[%d]', device.red, zone.green, zone.blue);\n                                }\n                                if(device && lightify.isTemperatureSupported(device.type)) {\n                                    zone.isTemperatureSupported = true;\n                                    zone.temperature = device.temperature;\n                                    //node.warn('Lightify Zone support temperature, current temperature=[%d]', device.temperature);\n                                }\n                            }\n                            return Promise.resolve();\n                        });\n                    });\n                }, Promise.resolve())\n                .then(function() {\n                    Array.prototype.push.apply(data.result, zones.result);\n                    resolve(data);\n                })\n                .catch(function(error) {\n                    node.warn('error 2');\n                    reject(error);\n                });\n            })\n            .catch(function(error) {\n                node.warn('error 1');\n                reject(error);\n            });\n        });\n    });\n}\n\nfunction LightifyAccessory(platform, device) {\n    //node.warn('LightifyAccessory');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Lightbulb(device.name || 'Unknown');\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n\n    var self = this;\n    if(device.isColorSupported || lightify.isColorSupported(device.type)) {\n        this.colorBulb(platform);\n    } else if (device.isTemperatureSupported || lightify.isTemperatureSupported(device.type)) {\n        this.temperatureBulb(platform);\n    }\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n        this.service.addOptionalCharacteristic(Characteristic.Brightness);\n        this.service.getCharacteristic(Characteristic.Brightness).value = self.device.brightness;\n        this.service.getCharacteristic(Characteristic.Brightness)\n        .on('get', function(callback) {\n            callback(null, self.device.brightness);\n        })\n        .on('set', function(brightness, callback) {\n            if(self.setBrightnessTimer) {\n                clearTimeout(self.setBrightnessTimer);\n            }\n            self.setBrightnessTimer = setTimeout(function() {\n                var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n                connection.connect().then(function() {\n                    return connection.nodeBrightness(self.device.mac, brightness, 0, self.device.type ? false : true);\n                }).then(function() {\n                    self.device.brightness = brightness;\n                    return connection.dispose();\n                });\n            }, 80);\n            callback(null);\n        });\n    }\n\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false, self.device.type ? false : true);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyAccessory.prototype.setHSV = function(hsv) {\n    var rgb = HSVtoRGB(hsv.h, hsv.s, hsv.v);\n\n    this.device.red = rgb.r;\n    this.device.green = rgb.g;\n    this.device.blue = rgb.b;\n\n    var self = this;\n    if(this.setHSVTimer) {\n        clearTimeout(this.setHSVTimer);\n    }\n    this.setHSVTimer = setTimeout(function() {\n        var connection = new lightify.lightify(self.platform.config.bridge_ip, self.log);\n\n        connection.connect().then(function() {\n            return connection.nodeColor(self.device.mac,\n                self.device.red, self.device.green, self.device.blue, self.device.alpha, 0, self.device.type ? false : true);\n        }).then(function() {\n            return connection.dispose();\n        });\n    }, 100);\n\n}\nLightifyAccessory.prototype.colorBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.Hue);\n    this.service.addOptionalCharacteristic(Characteristic.Saturation);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n\n    var hsv = RGBtoHSV(this.device.red, this.device.green, this.device.blue);\n\n    this.service.getCharacteristic(Characteristic.Hue).value = hsv.h * 360;\n    this.service.getCharacteristic(Characteristic.Saturation).value = hsv.h * 100;\n    this.service.getCharacteristic(Characteristic.Brightness).value = hsv.v * 100;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.Hue)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.h * 360);\n    })\n    .on('set', function(h, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.h = h / 360.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n\n    this.service.getCharacteristic(Characteristic.Saturation)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.s * 100);\n    })\n    .on('set', function(s, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.s = s / 100.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n}\nLightifyAccessory.prototype.temperatureBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.ColorTemperature);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n    var mired = 1000000 / this.device.temperature;\n\n    this.log.debug('temperatureBulb', mired);\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.ColorTemperature)\n    .on('get', function(callback) {\n        self.log.error('get temperature:', self.device.temperature, 'mired:', mired);\n        callback(null, mired);\n    })\n    .on('set', function(mired, callback) {\n        var temperature = 1000000 / mired;\n        self.log.error('sent temperature to set: ', temperature, 'mired:', mired);\n        \n        var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n        connection.connect().then(function() {\n            return connection.nodeTemperature(self.device.mac, temperature, 0, self.device.type ? false : true).then(function(data) {\n                self.log.error('set temperature (via mired): ', temperature); \n                self.device.temperature = temperature;\n                callback(null, mired);\n                return connection.dispose();\n            });\n        });\n    });\n}\nLightifyAccessory.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/* send updated status to HomeKit /\n    self.service.getCharacteristic(Characteristic.On).updateValue(device.status);\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n\t\tself.service.getCharacteristic(Characteristic.Brightness).updateValue(self.device.brightness);\n\t}\n}\nLightifyAccessory.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifyOutlet(platform, device) {\n    //node.warn('LightifyOutlet');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Service.Outlet(device.name);\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n    this.service.getCharacteristic(Characteristic.OutletInUse).value = true;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.OutletInUse)\n    .on('get', function(callback) {\n        callback(null, true);\n    });\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyOutlet.prototype.updateDevice = function(device) {\n    this.device = device;\n}\nLightifyOutlet.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Outlet')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifySensor(platform, device) {\n    //node.warn('LightifySensor');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\t\n    var self = this;\n\n\t// contact status\n    this.service = new Service.ContactSensor(device.name);\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.ContactSensorState).value = true;\n    this.service.getCharacteristic(Characteristic.ContactSensorState)\n    .on('get', function(callback) {\n        callback(null, self.device.online == 2 && self.device.green == 1)\n    });/\n\t/\n\t// battery service\n\tthis.batteryService = new Service.BatteryService(device.name);\n    this.batteryService.getCharacteristic(Characteristic.Name).value = device.name;\n    this.batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t*/\n}\nLightifySensor.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/* send updated status to HomeKit /\n\tself.service.getCharacteristic(Characteristic.ContactSensorState).updateValue(self.device.green);\n}\nLightifySensor.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Sensor')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n\t\n    var self = this;\n\t\n\t// battery service\n\tvar batteryService = new Service.BatteryService();\n    batteryService.getCharacteristic(Characteristic.Name).value = this.name;\n    batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tbatteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tbatteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness < 15 ? true : false)\n    });\n    services.push(batteryService);\n\t\n    if(this.batteryService) {\n        services.push(this.batteryService);\n    }\n\t\n    return services;\n}\n        ","outputs":1,"noerr":0,"x":580,"y":180,"wires":[["eec298a.b88e268","228ec816.c78588","3c5bcefd.65bd7a","6bbc5501.00db5c"]]},{"id":"4c2a6d85.f1f824","type":"inject","z":"4ad1e2f.135b39c","name":"Get accessories (2000ms)","topic":"","payload":"","payloadType":"date","repeat":"2","crontab":"","once":true,"onceDelay":"5","x":380,"y":180,"wires":[["d60169b2.b83b"]]},{"id":"eec298a.b88e268","type":"link out","z":"4ad1e2f.135b39c","name":"Homebridge Out","links":["2ff95594.9f519a"],"x":755,"y":240,"wires":[]},{"id":"c1f3726b.c0cd18","type":"link in","z":"4ad1e2f.135b39c","name":"Homebridge In","links":["a3113f68.88c998"],"x":75,"y":240,"wires":[["aab2d393.1eccb8"]]},{"id":"228ec816.c78588","type":"function","z":"4ad1e2f.135b39c","name":"Save Lightify Accessories","func":"// save the light so we can look up its data\n// when homekit sends a command.\nglobal.set("LightifyAccessory["+msg.light.id+"]",msg.light, 'memoryOnly')","outputs":1,"noerr":0,"x":810,"y":280,"wires":[[]]},{"id":"aab2d393.1eccb8","type":"function","z":"4ad1e2f.135b39c","name":"Look up Accessory","func":"try {\n    var accessoryObjects=global.get("LightifyAccessory", 'memoryOnly') || 0;\n    if (accessoryObjects !== 0) {\n        msg.light = getByValue3(accessoryObjects, msg.name);\n        node.send(msg);\n    }\n}\ncatch(error) {\n    node.warn(error)\n}\n\nfunction getByValue(arr, value) {\n  for (var i=0, iLen=arr.length; i<iLen; i++) {\n    if (arr[i] !== null){\n        if (arr[i].hasOwnProperty('name')){\n            if (arr[i].name !== null){\n                if (arr[i].name == value) return arr[i];\n            }\n        }\n    }\n  }\n}\n\nfunction getByValue2(arr, value) {\n\n  var result  = arr.filter(function(o){return o.name == value;} );\n\n  return result? result[0] : null; // or undefined\n\n}\n\nfunction getByValue3(arr, value) {\n\n  var result = [];\n\n  arr.forEach(function(o){if (o.name == value) result.push(o);} );\n\n  return result? result[0] : null; // or undefined\n\n}\n\nfunction getByValue4(arr, value) {\n  var o;\n\n  for (var i=0, iLen=arr.length; i<iLen; i++) {\n    o = arr[i];\n\n    for (var name in o) {\n      if (o.hasOwnProperty(name) && o[name] == value) {\n        return o;\n      }\n    }\n  }\n}\n","outputs":1,"noerr":0,"x":230,"y":240,"wires":[["a76dc8ad.49c5d"]]},{"id":"ddcab773.74ff08","type":"function","z":"4ad1e2f.135b39c","name":"Lightify Out","func":"var bridge_ip = "192.168.0.28";\n//var bridge_ip = "192.168.0.16";\n\nvar moment = global.get('moment');\nvar util = global.get('util');\nvar lightify = global.get('lightify');\nvar BusyTimerTimeMs = 20000;\n\n// how long node-lightify should wait before timing out the connection to the bridge.\n// this should ideally be shorter than your poll rate. note that this depends on a modified copy\n// of node-lightify as the master branch does not have this feature.\nvar cfgLightifyBridgeConnectTimeout = 1000; // ms\n\nvar LightifyIsResponding = flow.get("LightifyIsResponding", 'memoryOnly');\nif (LightifyIsResponding > 0) {\n    var device_in = msg.light\n    var connection = new lightify.lightify(bridge_ip);\n    \n    if(msg.payload.hasOwnProperty('Brightness')){\n        //node.warn('Brightness');\n        //node.warn(device);\n        //if(setBrightnessTimer) {\n        //    clearTimeout(setBrightnessTimer);\n        //}\n        //setBrightnessTimer = setTimeout(function() {\n            var brightness = msg.payload.Brightness;\n            connection.connect(cfgLightifyBridgeConnectTimeout).then(function() {\n                return connection.nodeBrightness(device_in.mac, brightness, 0, device_in.type ? false : true);\n            }).then(function() {\n                msg.light.brightness = brightness;\n                node.send(msg);\n                ClearBusyTimer();\n                return connection.dispose();\n            }).catch(function() {\n                ClearBusyTimer();\n                return connection.dispose();\n            });\n        //}, 80);\n    } else if (msg.payload.hasOwnProperty('On')){\n        //node.warn('On');\n        //node.warn(device);\n        var state = msg.payload.On;\n        connection.connect(cfgLightifyBridgeConnectTimeout).then(function() {\n            return connection.nodeOnOff(device_in.mac, state ? true : false, device_in.type ? false : true);\n            }).then(function() {\n                msg.light.status = state ? 1 : 0;\n                node.send(msg);\n                ClearBusyTimer();\n                return connection.dispose();\n            }).catch(function() {\n                ClearBusyTimer();\n                return connection.dispose();\n            });\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire){\n    \n    // show lightify as busy\n    flow.set("LightifyIsBusy",1, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function(){\n                                        // do some stuff here if timeout\n                                        node.warn('Lightify Busy Timer Expired');\n                                        flow.set("LightifyIsBusy",0, 'memoryOnly');\n                                    }, TimeTillExpire || 5000);\n                                    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly')\n    \n}\n\nfunction ClearBusyTimer(){\n    \n    // show lightify as not busy\n    flow.set("LightifyIsBusy",0, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly');\n    \n}        \n\nfunction discover(connection) {\n    //node.warn('discover')\n    var self = this;\n    return connection.connect().then(function() {\n        //node.warn('Connected to Lightify Bridge');\n        //have to discover nodes for light status of group\n        return connection.discover();\n    }).then(function(data) {\n        return !showGroups ? Promise.resolve(data) :\n        new Promise(function(resolve, reject) {\n            //node.warn('discover zones');\n            connection.discoverZone()\n            .then(function(zones) {\n                //get zone info. if one of them is off, then this group is off\n                zones.result.reduce(function(av, zone){\n                    return av.then(function() {\n                        return connection\n                        .getZoneInfo(zone.id)\n                        .then(function(zoneInfo){\n                            zone.online = 2; // group always online\n                            zone.status = 0; // default to off\n                            zone.isBrightnessSupported = false;\n                            zone.isColorSupported = false;\n                            zone.isTemperatureSupported = false;\n                            if(!zoneInfo.result || zoneInfo.result.length === 0) {\n                                return Promise.reject('no result for zone');\n                            }\n                            for (var mac of zoneInfo.result[0].devices) {\n                                var device = data.result.find(function(d) {\n                                    return d.mac === mac;\n                                });\n                                if (device && device.online && device.status === 1) {\n                                    zone.status = 1;\n                                    node.warn('Lightify Zone is on');\n                                }\n                                if(device && lightify.isBrightnessSupported(device.type)) {\n                                    zone.isBrightnessSupported = true;\n                                    zone.brightness = device.brightness;\n                                    node.warn('Lightify Zone support brightness, current brightness=[%d]', device.brightness);\n                                }\n                                if(device && lightify.isColorSupported(device.type)) {\n                                    zone.isColorSupported = true;\n                                    zone.red = device.red;\n                                    zone.green = device.green;\n                                    c = device.blue;\n                                    node.warn('Lightify Zone support color, current red=[%d], green=[%d], blue=[%d]', device.red, zone.green, zone.blue);\n                                }\n                                if(device && lightify.isTemperatureSupported(device.type)) {\n                                    zone.isTemperatureSupported = true;\n                                    zone.temperature = device.temperature;\n                                    node.warn('Lightify Zone support temperature, current temperature=[%d]', device.temperature);\n                                }\n                            }\n                            return Promise.resolve();\n                        });\n                    });\n                }, Promise.resolve())\n                .then(function() {\n                    Array.prototype.push.apply(data.result, zones.result);\n                    resolve(data);\n                })\n                .catch(function(error) {\n                    node.warn('error 2');\n                    reject(error);\n                });\n            })\n            .catch(function(error) {\n                node.warn('error 1');\n                reject(error);\n            });\n        });\n    });\n}\n\nfunction accessories() {\n    //node.warn('accessories')\n    var self = this;\n    //var connection = new lightify.lightify(bridge_ip, self.log);\n    var connection = new lightify.lightify(bridge_ip);\n    discover(connection).then(function(data) {\n        var foundAccessories = [];\n        data.result.forEach(function(light) {\n            //node.warn(light);\n            msg.topic = light.name;\n            light.isBrightnessSupported = lightify.isBrightnessSupported(light.type);\n            light.isColorSupported = lightify.isColorSupported(light.type);\n            light.isTemperatureSupported = lightify.isTemperatureSupported(light.type);\n            msg.light = light;\n            node.send(msg);\n            if(!hideNodes && light.type && lightify.isLight(light.type)) {\n                //node.warn('Lightify Light [%s]', light.name);\n                foundAccessories.push(new LightifyAccessory(self, light));\n                //msg.light.name = light.name;\n                //msg.light.type = light.type;\n                //msg.light.status = light.status;\n                //node.send(msg);\n            } else if (!hideNodes && light.type && lightify.isPlug(light.type)) {\n                //node.warn('Lightify Plug [%s]', light.name);\n                foundAccessories.push(new LightifyOutlet(self, light));\n            } else if (!hideNodes && light.type && lightify.isSensor(light.type)) {\n                //node.warn('Lightify Sensor [%s]', light.name);\n                foundAccessories.push(new LightifySensor(self, light));\n            } else if(!light.type) {\n                foundAccessories.push(new LightifyAccessory(self, light));\n            }\n        });\n        //node.warn(foundAccessories);\n        connection.dispose();\n        //callback(self.foundAccessories);\n        //node.warn('Lightify accessories');\n        //self.refreshTimer();\n    }).catch(function(error) {\n        node.warn('Discovered failed', error);\n        throw 'can not connect to lightify bridge.';\n    });\n}\n\nfunction LightifyAccessory(platform, device) {\n    //node.warn('LightifyAccessory');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Lightbulb(device.name || 'Unknown');\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n\n    var self = this;\n    if(device.isColorSupported || lightify.isColorSupported(device.type)) {\n        this.colorBulb(platform);\n    } else if (device.isTemperatureSupported || lightify.isTemperatureSupported(device.type)) {\n        this.temperatureBulb(platform);\n    }\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n        this.service.addOptionalCharacteristic(Characteristic.Brightness);\n        this.service.getCharacteristic(Characteristic.Brightness).value = self.device.brightness;\n        this.service.getCharacteristic(Characteristic.Brightness)\n        .on('get', function(callback) {\n            callback(null, self.device.brightness);\n        })\n        .on('set', function(brightness, callback) {\n            if(self.setBrightnessTimer) {\n                clearTimeout(self.setBrightnessTimer);\n            }\n            self.setBrightnessTimer = setTimeout(function() {\n                var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n                connection.connect().then(function() {\n                    return connection.nodeBrightness(self.device.mac, brightness, 0, self.device.type ? false : true);\n                }).then(function() {\n                    self.device.brightness = brightness;\n                    return connection.dispose();\n                });\n            }, 80);\n            callback(null);\n        });\n    }\n\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false, self.device.type ? false : true);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyAccessory.prototype.setHSV = function(hsv) {\n    var rgb = HSVtoRGB(hsv.h, hsv.s, hsv.v);\n\n    this.device.red = rgb.r;\n    this.device.green = rgb.g;\n    this.device.blue = rgb.b;\n\n    var self = this;\n    if(this.setHSVTimer) {\n        clearTimeout(this.setHSVTimer);\n    }\n    this.setHSVTimer = setTimeout(function() {\n        var connection = new lightify.lightify(self.platform.config.bridge_ip, self.log);\n\n        connection.connect().then(function() {\n            return connection.nodeColor(self.device.mac,\n                self.device.red, self.device.green, self.device.blue, self.device.alpha, 0, self.device.type ? false : true);\n        }).then(function() {\n            return connection.dispose();\n        });\n    }, 100);\n\n}\nLightifyAccessory.prototype.colorBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.Hue);\n    this.service.addOptionalCharacteristic(Characteristic.Saturation);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n\n    var hsv = RGBtoHSV(this.device.red, this.device.green, this.device.blue);\n\n    this.service.getCharacteristic(Characteristic.Hue).value = hsv.h * 360;\n    this.service.getCharacteristic(Characteristic.Saturation).value = hsv.h * 100;\n    this.service.getCharacteristic(Characteristic.Brightness).value = hsv.v * 100;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.Hue)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.h * 360);\n    })\n    .on('set', function(h, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.h = h / 360.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n\n    this.service.getCharacteristic(Characteristic.Saturation)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.s * 100);\n    })\n    .on('set', function(s, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.s = s / 100.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n}\nLightifyAccessory.prototype.temperatureBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.ColorTemperature);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n    var mired = 1000000 / this.device.temperature;\n\n    this.log.debug('temperatureBulb', mired);\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.ColorTemperature)\n    .on('get', function(callback) {\n        self.log.error('get temperature:', self.device.temperature, 'mired:', mired);\n        callback(null, mired);\n    })\n    .on('set', function(mired, callback) {\n        var temperature = 1000000 / mired;\n        self.log.error('sent temperature to set: ', temperature, 'mired:', mired);\n        \n        var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n        connection.connect().then(function() {\n            return connection.nodeTemperature(self.device.mac, temperature, 0, self.device.type ? false : true).then(function(data) {\n                self.log.error('set temperature (via mired): ', temperature); \n                self.device.temperature = temperature;\n                callback(null, mired);\n                return connection.dispose();\n            });\n        });\n    });\n}\nLightifyAccessory.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/ send updated status to HomeKit /\n    self.service.getCharacteristic(Characteristic.On).updateValue(device.status);\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n\t\tself.service.getCharacteristic(Characteristic.Brightness).updateValue(self.device.brightness);\n\t}\n}\nLightifyAccessory.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifyOutlet(platform, device) {\n    //node.warn('LightifyOutlet');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Service.Outlet(device.name);\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n    this.service.getCharacteristic(Characteristic.OutletInUse).value = true;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.OutletInUse)\n    .on('get', function(callback) {\n        callback(null, true);\n    });\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyOutlet.prototype.updateDevice = function(device) {\n    this.device = device;\n}\nLightifyOutlet.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Outlet')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifySensor(platform, device) {\n    //node.warn('LightifySensor');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\t\n    var self = this;\n\n\t// contact status\n    this.service = new Service.ContactSensor(device.name);\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.ContactSensorState).value = true;\n    this.service.getCharacteristic(Characteristic.ContactSensorState)\n    .on('get', function(callback) {\n        callback(null, self.device.online == 2 && self.device.green == 1)\n    });/\n\t/\n\t// battery service\n\tthis.batteryService = new Service.BatteryService(device.name);\n    this.batteryService.getCharacteristic(Characteristic.Name).value = device.name;\n    this.batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t*/\n}\nLightifySensor.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/* send updated status to HomeKit */\n\tself.service.getCharacteristic(Characteristic.ContactSensorState).updateValue(self.device.green);\n}\nLightifySensor.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Sensor')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n\t\n    var self = this;\n\t\n\t// battery service\n\tvar batteryService = new Service.BatteryService();\n    batteryService.getCharacteristic(Characteristic.Name).value = this.name;\n    batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tbatteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tbatteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness < 15 ? true : false)\n    });\n    services.push(batteryService);\n\t\n    if(this.batteryService) {\n        services.push(this.batteryService);\n    }\n\t\n    return services;\n}","outputs":1,"noerr":0,"x":770,"y":340,"wires":[["228ec816.c78588"]]},{"id":"69066150.2c3c7","type":"catch","z":"4ad1e2f.135b39c","name":"","scope":null,"uncaught":false,"x":60,"y":20,"wires":[["81f30f8c.83c8c8"]]},{"id":"81f30f8c.83c8c8","type":"debug","z":"4ad1e2f.135b39c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":190,"y":20,"wires":[]},{"id":"66751ef8.c56bc8","type":"subflow:4006453f.1d432c","z":"4ad1e2f.135b39c","name":"","env":[{"name":"Buffer_Size","type":"num","value":"20"}],"x":390,"y":300,"wires":[["730b03d7.40a86c","223c5bbc.9180fc"],[]]},{"id":"a76dc8ad.49c5d","type":"change","z":"4ad1e2f.135b39c","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"put","tot":"str"},{"t":"move","p":"light","pt":"msg","to":"payload.light","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":240,"wires":[["66751ef8.c56bc8","faf2a73d.6a8e88"]]},{"id":"39effee8.066602","type":"inject","z":"4ad1e2f.135b39c","name":"Unload FIFO (500ms)","topic":"get","payload":"","payloadType":"date","repeat":"0.5","crontab":"","once":true,"onceDelay":0.1,"x":140,"y":280,"wires":[["66751ef8.c56bc8"]]},{"id":"bf4fd563.f9fc6","type":"change","z":"4ad1e2f.135b39c","name":"","rules":[{"t":"move","p":"payload.light","pt":"msg","to":"light","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":400,"wires":[["ddcab773.74ff08"]]},{"id":"730b03d7.40a86c","type":"function","z":"4ad1e2f.135b39c","name":"Filter valid messages","func":"// when topic == put a new message is being put\n// into the buffer. likewise, when the payload is null\n// a trigger is being fired from the inject.\n\n// other nodes may be interacting with the gateway so\n// check if it is busy first. "LightifyIsBusy" is just a \n// variable used for handshaking between the nodes.\n\nvar BusyTimerTimeMs = 20000;\n\nvar LightifyIsBusy = flow.get("LightifyIsBusy", 'memoryOnly') || 0;\n\nif (msg.topic != 'put' && msg.payload){\n    if (!LightifyIsBusy){\n        SetBusyTimer(BusyTimerTimeMs);\n        return [null, msg]; // null to first output, msg to second\n    } else {\n        msg.topic = "put";\n        return [msg, null]; // to first output, null to second\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire){\n    \n    // show lightify as busy\n    flow.set("LightifyIsBusy",1, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function(){\n                                        // do some stuff here if timeout\n                                        node.warn('Lightify Busy Timer Expired');\n                                        flow.set("LightifyIsBusy",0, 'memoryOnly');\n                                    }, TimeTillExpire || 5000);\n                                    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly')\n    \n}\n\nfunction ClearBusyTimer(){\n    \n    // show lightify as not busy\n    flow.set("LightifyIsBusy",0, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly');\n    \n}","outputs":2,"noerr":0,"x":420,"y":380,"wires":[["420de8ec.1dbae8"],["bf4fd563.f9fc6"]]},{"id":"3c5bcefd.65bd7a","type":"debug","z":"4ad1e2f.135b39c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":770,"y":180,"wires":[]},{"id":"6bbc5501.00db5c","type":"switch","z":"4ad1e2f.135b39c","name":"Devices","property":"topic","propertyType":"msg","rules":[{"t":"cont","v":"Contact","vt":"str"},{"t":"cont","v":"Light","vt":"str"},{"t":"cont","v":"Switch","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":640,"y":80,"wires":[["4b7c38a9.346b28"],["db8deb1f.d732c8"],["13956656.7043f2"]]},{"id":"4b7c38a9.346b28","type":"debug","z":"4ad1e2f.135b39c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"light","targetType":"msg","x":780,"y":60,"wires":[]},{"id":"e14a201b.157648","type":"catch","z":"4ad1e2f.135b39c","name":"","scope":["730b03d7.40a86c","d60169b2.b83b","ddcab773.74ff08"],"uncaught":false,"x":50,"y":60,"wires":[["3ac697f1.8e63c8"]]},{"id":"3ac697f1.8e63c8","type":"function","z":"4ad1e2f.135b39c","name":"Reset Variables","func":"flow.set("LightifyIsBusy",0, 'memoryOnly');\nreturn msg;","outputs":1,"noerr":0,"x":220,"y":60,"wires":[["37722444.0b63b4"]]},{"id":"37722444.0b63b4","type":"debug","z":"4ad1e2f.135b39c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":370,"y":60,"wires":[]},{"id":"b302fba1.40ac48","type":"link in","z":"4ad1e2f.135b39c","name":"","links":["420de8ec.1dbae8"],"x":135,"y":400,"wires":[["66751ef8.c56bc8"]]},{"id":"420de8ec.1dbae8","type":"link out","z":"4ad1e2f.135b39c","name":"","links":["b302fba1.40ac48"],"x":575,"y":360,"wires":[]},{"id":"db8deb1f.d732c8","type":"debug","z":"4ad1e2f.135b39c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"light","targetType":"msg","x":780,"y":80,"wires":[]},{"id":"13956656.7043f2","type":"debug","z":"4ad1e2f.135b39c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"light","targetType":"msg","x":780,"y":100,"wires":[]},{"id":"59dd9ec1.d93eb","type":"inject","z":"4ad1e2f.135b39c","name":"Single Shot","topic":"flush","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":110,"y":440,"wires":[["69a2ce86.4563c","66751ef8.c56bc8"]]},{"id":"69a2ce86.4563c","type":"function","z":"4ad1e2f.135b39c","name":"Initialize Lightify","func":"var LightifyRetryCount = flow.set("LightifyRetryCount",0, 'memoryOnly');\nvar LightifyIsResponding = flow.set("LightifyIsResponding",1, 'memoryOnly');\nvar LightifyIsBusy = flow.set("LightifyIsBusy",0, 'memoryOnly');\nvar LightifyGettingGroups = flow.set("LightifyGettingGroups",false, 'memoryOnly');\n\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":500,"wires":[[]]},{"id":"ab04325c.53c6f","type":"inject","z":"4ad1e2f.135b39c","name":"Manual Unload FIFO","topic":"get","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":320,"wires":[["66751ef8.c56bc8"]]},{"id":"963a432.3020e4","type":"inject","z":"4ad1e2f.135b39c","name":"Flush FIFO","topic":"flush","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":360,"wires":[["66751ef8.c56bc8"]]},{"id":"faf2a73d.6a8e88","type":"debug","z":"4ad1e2f.135b39c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":580,"y":240,"wires":[]},{"id":"223c5bbc.9180fc","type":"debug","z":"4ad1e2f.135b39c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":570,"y":300,"wires":[]}]

Greatly appreciated! I will do as much as I can without you. Thank you for taking the time and providing the code!

No problem, I hope it works out for you! If you can improve it let me know.
Sent from my iPhone

Greatly appreciated! I will do as much as I can without you. Thank you for taking the time and providing the code!
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

Github doesn't seem to like the cut/paste. I'm getting json formatting errors. Zip?

Copy the text and import it into node-red using the “import from clipboard” menu.
Sent from my iPhone

On Mar 20, 2020, at 8:12 PM, nospam2k notifications@github.com wrote:

Github doesn't seem to like the cut/paste. I'm getting json formatting errors. Zip?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

Yes, that's what is complaining. Apparently there are extra characters it doesn't like. I've tried putting it in a json pretty and all the functions seem to have the same problem. Seems to be specific to .get and .set and some comments.

Try this:
[
{
"id": "4006453f.1d432c",
"type": "subflow",
"name": "FIFO",
"info": "# FIFO\n## First in First Out subflow\nThis flow receives a series of msg.payloads and builds a queue using FIFO (First in First out) method. The LIFO size is configurabe through subflow enviroment variables.\n\n### Input\nmsg.topic == put\nWill add the msg.payload to the end of the array. Everytime a new item is received the second output sends the complete queue.\n\nmsg.topic == get\nWill remove the first item of the stack and will send it in the first output\n\nmsg.topic == list\nSends the complete list on the second output.\n\n### Output 1\nThe first item on the top of the stack. It is sent only when msg.topic == get.\n\n### Output 2\nThe complete queue in Array format. It is sent everytime a new item is added, removed or when msg.topic == list\n\n### Status\nAlways show the queue size.\n\n### Enviroment Variables\nBuffer_Size defines the size of the queue. If a new item arrives and the queue is full, the oldest item will be removed.",
"category": "",
"in": [
{
"x": 60,
"y": 180,
"wires": [
{
"id": "81bd46c3.2c5048"
}
]
}
],
"out": [
{
"x": 640,
"y": 120,
"wires": [
{
"id": "ac2f383.195b9c8",
"port": 0
}
]
},
{
"x": 640,
"y": 180,
"wires": [
{
"id": "bb92ce78.e93eb",
"port": 0
}
]
}
],
"env": [
{
"name": "Buffer_Size",
"type": "num",
"value": "6"
}
],
"icon": "font-awesome/fa-ellipsis-v",
"status": {
"x": 800,
"y": 200,
"wires": [
{
"id": "23d5f18b.05c706",
"port": 0
}
]
}
},
{
"id": "81bd46c3.2c5048",
"type": "switch",
"z": "4006453f.1d432c",
"name": "Topic",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "get",
"vt": "str"
},
{
"t": "eq",
"v": "put",
"vt": "str"
},
{
"t": "eq",
"v": "list",
"vt": "str"
},
{
"t": "eq",
"v": "flush",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 5,
"x": 190,
"y": 180,
"wires": [
[
"ac2f383.195b9c8"
],
[
"7b2aff73.43371"
],
[
"bb92ce78.e93eb"
],
[
"2eb96832.d1682"
],
[
"bb92ce78.e93eb"
]
]
},
{
"id": "ac2f383.195b9c8",
"type": "function",
"z": "4006453f.1d432c",
"name": "get",
"func": "var queue = flow.get("queue")\nvar item;\n\nif (!Array.isArray(queue)){\n    queue = [];\n}else{\n    item = queue.pop(1);\n}\n\n\nflow.set("queue", queue)\nmsg.payload = item;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 470,
"y": 120,
"wires": [
[
"bb92ce78.e93eb"
]
]
},
{
"id": "bb92ce78.e93eb",
"type": "change",
"z": "4006453f.1d432c",
"name": "list",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "queue",
"tot": "flow"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 630,
"y": 260,
"wires": [
[
"23d5f18b.05c706"
]
]
},
{
"id": "23d5f18b.05c706",
"type": "change",
"z": "4006453f.1d432c",
"name": "Count",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "$count(msg.payload)\t",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 790,
"y": 260,
"wires": [
[]
]
},
{
"id": "7b2aff73.43371",
"type": "function",
"z": "4006453f.1d432c",
"name": "put",
"func": "var queue = flow.get("queue")\n\n\nif (!Array.isArray(queue)){\n    queue = [];\n}else if ( queue.length >= env.get("Buffer_Size") ){\n    queue.pop(1);\n}\n\nqueue.unshift(msg.payload);\n\nflow.set("queue", queue);\nmsg.payload = queue;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 470,
"y": 160,
"wires": [
[
"bb92ce78.e93eb"
]
]
},
{
"id": "80f36e5b.2e44c",
"type": "debug",
"z": "4006453f.1d432c",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 530,
"y": 40,
"wires": []
},
{
"id": "3a25842a.9042dc",
"type": "debug",
"z": "4006453f.1d432c",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 730,
"y": 60,
"wires": []
},
{
"id": "2eb96832.d1682",
"type": "function",
"z": "4006453f.1d432c",
"name": "flush",
"func": "var queue = flow.get("queue")\n\n\nif (!Array.isArray(queue)){\n    queue = [];\n}else{\n    while (queue.length > 0){\n        queue.pop();\n    }\n}\n\nflow.set("queue", queue);\nmsg.payload = queue;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 470,
"y": 200,
"wires": [
[
"bb92ce78.e93eb"
]
]
},
{
"id": "d60169b2.b83b",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Lightify In",
"func": "//            "platform": "Lightify",\n//            "bridge_ip": "192.168.0.16",\n//            "name": "Lightify",\n//            "showGroups": true,\n//            "hideNodes": false,\n//\t\t\t  "pollFreqSecs" : "2"\n                \n//var bridge_ip = "192.168.0.16"; // bridge 2\nvar bridge_ip = "192.168.0.28"; // bridge 1\nvar showGroups = true;\nvar hideNodes = false;\n\nvar moment = global.get('moment');\nvar util = global.get('util');\nvar lightify = global.get("lightify");\nvar Service, Characteristic;\nvar Lightbulb;  \nvar log = node;\nvar BusyTimerTimeMs = 20000;\n\n// how long node-lightify should wait before timing out the connection to the bridge.\n// this should ideally be shorter than your poll rate. note that this depends on a modified copy\n// of node-lightify as the master branch does not have this feature.\nvar cfgLightifyBridgeConnectTimeout = 10000; // ms\n// how many counts to pass before retrying a connection to the unresponsive gateway.\n// set this to a value greater than cfgLightifyBridgeConnectTimeout above.\nvar cfgLightifyRetryCount = 10; \n\nvar LightifyRetryCount = flow.get("LightifyRetryCount", 'memoryOnly') || 0;\nvar LightifyIsResponding = flow.get("LightifyIsResponding", 'memoryOnly') || 0;\nvar LightifyIsBusy = flow.get("LightifyIsBusy", 'memoryOnly') || 0;\nvar LightifyGettingGroups = flow.get("LightifyGettingGroups", 'memoryOnly') || false;\n\nif (LightifyIsBusy === 0) {\n    SetBusyTimer(BusyTimerTimeMs);\n    if (LightifyIsResponding > 0 || LightifyRetryCount >= cfgLightifyRetryCount) { \n        if (LightifyIsResponding === 0 && LightifyRetryCount >= cfgLightifyRetryCount) {\n            node.warn('Lightify is responding again!')\n            flow.set("LightifyIsResponding",1, 'memoryOnly');\n        }\n        if (LightifyRetryCount > cfgLightifyRetryCount) {\n            node.warn('Retrying Lightify connection.')\n        }\n        flow.set("LightifyRetryCount",0, 'memoryOnly');\n        findAccessories();\n    } else {\n        node.warn('Lightify is not responding. Incrementing retry counter ' + (cfgLightifyRetryCount - LightifyRetryCount) + ' times.')\n        flow.set("LightifyRetryCount",LightifyRetryCount + 1, 'memoryOnly');\n        ClearBusyTimer();\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire){\n    \n    // show lightify as busy\n    flow.set("LightifyIsBusy",1, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function(){\n                                        // do some stuff here if timeout\n                                        node.warn('Lightify Busy Timer Expired');\n                                        flow.set("LightifyIsBusy",0, 'memoryOnly');\n                                    }, TimeTillExpire || 5000);\n                                    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly')\n    \n}\n\nfunction ClearBusyTimer(){\n    \n    // show lightify as not busy\n    flow.set("LightifyIsBusy",0, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly');\n    \n}\n\nfunction findAccessories() {\n    var self = this;\n    var connection = new lightify.lightify(bridge_ip);\n    discover(connection).then(function(data) {\n        //var foundAccessories = [];\n        data.result.forEach(function(light) {\n            var msg_out_light = Object.assign({},msg); // create new message\n            msg_out_light.topic = light.name;\n            //msg_out_light.payload = '';\n            light.isBrightnessSupported = lightify.isBrightnessSupported(light.type);\n            light.isColorSupported = lightify.isColorSupported(light.type);\n            light.isTemperatureSupported = lightify.isTemperatureSupported(light.type);\n            light.isLight = lightify.isLight(light.type);\n            light.isSwitch = lightify.isSwitch(light.type);\n            light.isPlug = lightify.isPlug(light.type);\n            light.isSensor = lightify.isSensor(light.type);\n            msg_out_light.light = light;\n            node.send(msg_out_light);\n            /\n            if(!hideNodes && light.type && lightify.isLight(light.type)) {\n                //node.warn('Lightify Light [%s]', light.name);\n                foundAccessories.push(new LightifyAccessory(self, light));\n                //msg.light.name = light.name;\n                //msg.light.type = light.type;\n                //msg.light.status = light.status;\n                //node.send(msg);\n            } else if (!hideNodes && light.type && lightify.isPlug(light.type)) {\n                //node.warn('Lightify Plug [%s]', light.name);\n                foundAccessories.push(new LightifyOutlet(self, light));\n            } else if (!hideNodes && light.type && lightify.isSensor(light.type)) {\n                //node.warn('Lightify Sensor [%s]', light.name);\n                foundAccessories.push(new LightifySensor(self, light));\n            } else if(!light.type) {\n                foundAccessories.push(new LightifyAccessory(self, light));\n            }\n            /\n        });\n        connection.dispose();\n        \n        flow.set("LightifyIsResponding",1, 'memoryOnly');\n        ClearBusyTimer();\n        flow.set("LightifyGettingGroups",!LightifyGettingGroups, 'memoryOnly'); // get groups every other message\n        \n        //var elapsedTime = Date.now() - msg.payload;\n        //node.warn('Elasped Time: ' + elapsedTime.toString() + ' ms');\n    }).catch(function(error) {\n        flow.set("LightifyIsResponding",0, 'memoryOnly');\n        ClearBusyTimer();\n        node.warn('Discovered failed', error);\n    });\n}\n    \nfunction discover(connection) {\n    var self = this;\n    return connection.connect(cfgLightifyBridgeConnectTimeout).then(function() {\n        //have to discover nodes for light status of group\n        //var elapsedTime = Date.now() - msg.payload;\n        //node.warn('Discovered light nodes: ' + elapsedTime.toString() + ' ms');\n        return connection.discover();\n    }).then(function(data) {\n        //return !showGroups ? Promise.resolve(data) :\n        return !LightifyGettingGroups ? Promise.resolve(data) :\n        new Promise(function(resolve, reject) {\n            //node.warn('discover zones');\n            connection.discoverZone()\n            .then(function(zones) {\n                //var elapsedTime = Date.now() - msg.payload;\n                //node.warn('Discovered zones: ' + elapsedTime.toString() + ' ms');\n                //get zone info. if one of them is off, then this group is off\n                zones.result.reduce(function(av, zone){\n                    return av.then(function() {\n                        return connection\n                        .getZoneInfo(zone.id)\n                        .then(function(zoneInfo){\n                            //var elapsedTime = Date.now() - msg.payload;\n                            //node.warn('Got zone info: ' + elapsedTime.toString() + ' ms');\n                            zone.online = 2; // group always online\n                            zone.status = 0; // default to off\n                            zone.isBrightnessSupported = false;\n                            zone.isColorSupported = false;\n                            zone.isTemperatureSupported = false;\n                            if(!zoneInfo.result || zoneInfo.result.length === 0) {\n                                return Promise.reject('no result for zone');\n                            }\n                            //node.warn(zoneInfo.result);\n                            for (var mac of zoneInfo.result[0].devices) {\n                                //var elapsedTime = Date.now() - msg.payload;\n                                //node.warn('Got zone device info: ' + elapsedTime.toString() + ' ms');\n                                //node.warn('getting mac');\n                                var device = data.result.find(function(d) {\n                                    return d.mac === mac;\n                                });\n                                //node.warn(device);\n                                if (device && device.online && device.status === 1) {\n                                    zone.status = 1;\n                                    //node.warn('Lightify Zone is on');\n                                }\n                                if(device && lightify.isBrightnessSupported(device.type)) {\n                                    zone.isBrightnessSupported = true;\n                                    zone.brightness = device.brightness;\n                                    //node.warn('Lightify Zone support brightness, current brightness=[%d]', device.brightness);\n                                }\n                                if(device && lightify.isColorSupported(device.type)) {\n                                    zone.isColorSupported = true;\n                                    zone.red = device.red;\n                                    zone.green = device.green;\n                                    zone.blue = device.blue;\n                                    //c = device.blue; // why was this here??\n                                    //node.warn('Lightify Zone support color, current red=[%d], green=[%d], blue=[%d]', device.red, zone.green, zone.blue);\n                                }\n                                if(device && lightify.isTemperatureSupported(device.type)) {\n                                    zone.isTemperatureSupported = true;\n                                    zone.temperature = device.temperature;\n                                    //node.warn('Lightify Zone support temperature, current temperature=[%d]', device.temperature);\n                                }\n                            }\n                            return Promise.resolve();\n                        });\n                    });\n                }, Promise.resolve())\n                .then(function() {\n                    Array.prototype.push.apply(data.result, zones.result);\n                    resolve(data);\n                })\n                .catch(function(error) {\n                    node.warn('error 2');\n                    reject(error);\n                });\n            })\n            .catch(function(error) {\n                node.warn('error 1');\n                reject(error);\n            });\n        });\n    });\n}\n\nfunction LightifyAccessory(platform, device) {\n    //node.warn('LightifyAccessory');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Lightbulb(device.name || 'Unknown');\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n\n    var self = this;\n    if(device.isColorSupported || lightify.isColorSupported(device.type)) {\n        this.colorBulb(platform);\n    } else if (device.isTemperatureSupported || lightify.isTemperatureSupported(device.type)) {\n        this.temperatureBulb(platform);\n    }\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n        this.service.addOptionalCharacteristic(Characteristic.Brightness);\n        this.service.getCharacteristic(Characteristic.Brightness).value = self.device.brightness;\n        this.service.getCharacteristic(Characteristic.Brightness)\n        .on('get', function(callback) {\n            callback(null, self.device.brightness);\n        })\n        .on('set', function(brightness, callback) {\n            if(self.setBrightnessTimer) {\n                clearTimeout(self.setBrightnessTimer);\n            }\n            self.setBrightnessTimer = setTimeout(function() {\n                var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n                connection.connect().then(function() {\n                    return connection.nodeBrightness(self.device.mac, brightness, 0, self.device.type ? false : true);\n                }).then(function() {\n                    self.device.brightness = brightness;\n                    return connection.dispose();\n                });\n            }, 80);\n            callback(null);\n        });\n    }\n\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false, self.device.type ? false : true);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyAccessory.prototype.setHSV = function(hsv) {\n    var rgb = HSVtoRGB(hsv.h, hsv.s, hsv.v);\n\n    this.device.red = rgb.r;\n    this.device.green = rgb.g;\n    this.device.blue = rgb.b;\n\n    var self = this;\n    if(this.setHSVTimer) {\n        clearTimeout(this.setHSVTimer);\n    }\n    this.setHSVTimer = setTimeout(function() {\n        var connection = new lightify.lightify(self.platform.config.bridge_ip, self.log);\n\n        connection.connect().then(function() {\n            return connection.nodeColor(self.device.mac,\n                self.device.red, self.device.green, self.device.blue, self.device.alpha, 0, self.device.type ? false : true);\n        }).then(function() {\n            return connection.dispose();\n        });\n    }, 100);\n\n}\nLightifyAccessory.prototype.colorBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.Hue);\n    this.service.addOptionalCharacteristic(Characteristic.Saturation);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n\n    var hsv = RGBtoHSV(this.device.red, this.device.green, this.device.blue);\n\n    this.service.getCharacteristic(Characteristic.Hue).value = hsv.h * 360;\n    this.service.getCharacteristic(Characteristic.Saturation).value = hsv.h * 100;\n    this.service.getCharacteristic(Characteristic.Brightness).value = hsv.v * 100;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.Hue)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.h * 360);\n    })\n    .on('set', function(h, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.h = h / 360.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n\n    this.service.getCharacteristic(Characteristic.Saturation)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.s * 100);\n    })\n    .on('set', function(s, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.s = s / 100.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n}\nLightifyAccessory.prototype.temperatureBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.ColorTemperature);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n    var mired = 1000000 / this.device.temperature;\n\n    this.log.debug('temperatureBulb', mired);\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.ColorTemperature)\n    .on('get', function(callback) {\n        self.log.error('get temperature:', self.device.temperature, 'mired:', mired);\n        callback(null, mired);\n    })\n    .on('set', function(mired, callback) {\n        var temperature = 1000000 / mired;\n        self.log.error('sent temperature to set: ', temperature, 'mired:', mired);\n        \n        var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n        connection.connect().then(function() {\n            return connection.nodeTemperature(self.device.mac, temperature, 0, self.device.type ? false : true).then(function(data) {\n                self.log.error('set temperature (via mired): ', temperature); \n                self.device.temperature = temperature;\n                callback(null, mired);\n                return connection.dispose();\n            });\n        });\n    });\n}\nLightifyAccessory.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/* send updated status to HomeKit /\n    self.service.getCharacteristic(Characteristic.On).updateValue(device.status);\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n\t\tself.service.getCharacteristic(Characteristic.Brightness).updateValue(self.device.brightness);\n\t}\n}\nLightifyAccessory.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifyOutlet(platform, device) {\n    //node.warn('LightifyOutlet');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Service.Outlet(device.name);\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n    this.service.getCharacteristic(Characteristic.OutletInUse).value = true;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.OutletInUse)\n    .on('get', function(callback) {\n        callback(null, true);\n    });\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyOutlet.prototype.updateDevice = function(device) {\n    this.device = device;\n}\nLightifyOutlet.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Outlet')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifySensor(platform, device) {\n    //node.warn('LightifySensor');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\t\n    var self = this;\n\n\t// contact status\n    this.service = new Service.ContactSensor(device.name);\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.ContactSensorState).value = true;\n    this.service.getCharacteristic(Characteristic.ContactSensorState)\n    .on('get', function(callback) {\n        callback(null, self.device.online == 2 && self.device.green == 1)\n    });/\n\t/\n\t// battery service\n\tthis.batteryService = new Service.BatteryService(device.name);\n    this.batteryService.getCharacteristic(Characteristic.Name).value = device.name;\n    this.batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t*/\n}\nLightifySensor.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/* send updated status to HomeKit /\n\tself.service.getCharacteristic(Characteristic.ContactSensorState).updateValue(self.device.green);\n}\nLightifySensor.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Sensor')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n\t\n    var self = this;\n\t\n\t// battery service\n\tvar batteryService = new Service.BatteryService();\n    batteryService.getCharacteristic(Characteristic.Name).value = this.name;\n    batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tbatteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tbatteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness < 15 ? true : false)\n    });\n    services.push(batteryService);\n\t\n    if(this.batteryService) {\n        services.push(this.batteryService);\n    }\n\t\n    return services;\n}\n        ",
"outputs": 1,
"noerr": 0,
"x": 580,
"y": 180,
"wires": [
[
"eec298a.b88e268",
"228ec816.c78588",
"3c5bcefd.65bd7a",
"6bbc5501.00db5c"
]
]
},
{
"id": "4c2a6d85.f1f824",
"type": "inject",
"z": "4ad1e2f.135b39c",
"name": "Get accessories (2000ms)",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "2",
"crontab": "",
"once": true,
"onceDelay": "5",
"x": 380,
"y": 180,
"wires": [
[
"d60169b2.b83b"
]
]
},
{
"id": "eec298a.b88e268",
"type": "link out",
"z": "4ad1e2f.135b39c",
"name": "Homebridge Out",
"links": [
"2ff95594.9f519a"
],
"x": 755,
"y": 240,
"wires": []
},
{
"id": "c1f3726b.c0cd18",
"type": "link in",
"z": "4ad1e2f.135b39c",
"name": "Homebridge In",
"links": [
"a3113f68.88c998"
],
"x": 75,
"y": 240,
"wires": [
[
"aab2d393.1eccb8"
]
]
},
{
"id": "228ec816.c78588",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Save Lightify Accessories",
"func": "// save the light so we can look up its data\n// when homekit sends a command.\n// this is also used in the garage flow so it needs to be global\nglobal.set("LightifyAccessory["+msg.light.id+"]",msg.light, 'memoryOnly')",
"outputs": 1,
"noerr": 0,
"x": 810,
"y": 280,
"wires": [
[]
]
},
{
"id": "aab2d393.1eccb8",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Look up Accessory",
"func": "try {\n    var accessoryObjects=global.get("LightifyAccessory", 'memoryOnly') || 0;\n    if (accessoryObjects !== 0) {\n        msg.light = getByValue3(accessoryObjects, msg.name);\n        node.send(msg);\n    }\n}\ncatch(error) {\n    node.warn(error)\n}\n\nfunction getByValue(arr, value) {\n  for (var i=0, iLen=arr.length; i<iLen; i++) {\n    if (arr[i] !== null){\n        if (arr[i].hasOwnProperty('name')){\n            if (arr[i].name !== null){\n                if (arr[i].name == value) return arr[i];\n            }\n        }\n    }\n  }\n}\n\nfunction getByValue2(arr, value) {\n\n  var result  = arr.filter(function(o){return o.name == value;} );\n\n  return result? result[0] : null; // or undefined\n\n}\n\nfunction getByValue3(arr, value) {\n\n  var result = [];\n\n  arr.forEach(function(o){if (o.name == value) result.push(o);} );\n\n  return result? result[0] : null; // or undefined\n\n}\n\nfunction getByValue4(arr, value) {\n  var o;\n\n  for (var i=0, iLen=arr.length; i<iLen; i++) {\n    o = arr[i];\n\n    for (var name in o) {\n      if (o.hasOwnProperty(name) && o[name] == value) {\n        return o;\n      }\n    }\n  }\n}\n",
"outputs": 1,
"noerr": 0,
"x": 230,
"y": 240,
"wires": [
[
"a76dc8ad.49c5d"
]
]
},
{
"id": "ddcab773.74ff08",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Lightify Out",
"func": "var bridge_ip = "192.168.0.28";\n//var bridge_ip = "192.168.0.16";\n\nvar moment = global.get('moment');\nvar util = global.get('util');\nvar lightify = global.get('lightify');\nvar BusyTimerTimeMs = 20000;\n\n// how long node-lightify should wait before timing out the connection to the bridge.\n// this should ideally be shorter than your poll rate. note that this depends on a modified copy\n// of node-lightify as the master branch does not have this feature.\nvar cfgLightifyBridgeConnectTimeout = 1000; // ms\n\nvar LightifyIsResponding = flow.get("LightifyIsResponding", 'memoryOnly');\nif (LightifyIsResponding > 0) {\n    var device_in = msg.light\n    var connection = new lightify.lightify(bridge_ip);\n    \n    if(msg.payload.hasOwnProperty('Brightness')){\n        //node.warn('Brightness');\n        //node.warn(device);\n        //if(setBrightnessTimer) {\n        //    clearTimeout(setBrightnessTimer);\n        //}\n        //setBrightnessTimer = setTimeout(function() {\n            var brightness = msg.payload.Brightness;\n            connection.connect(cfgLightifyBridgeConnectTimeout).then(function() {\n                return connection.nodeBrightness(device_in.mac, brightness, 0, device_in.type ? false : true);\n            }).then(function() {\n                msg.light.brightness = brightness;\n                node.send(msg);\n                ClearBusyTimer();\n                return connection.dispose();\n            }).catch(function() {\n                ClearBusyTimer();\n                return connection.dispose();\n            });\n        //}, 80);\n    } else if (msg.payload.hasOwnProperty('On')){\n        //node.warn('On');\n        //node.warn(device);\n        var state = msg.payload.On;\n        connection.connect(cfgLightifyBridgeConnectTimeout).then(function() {\n            return connection.nodeOnOff(device_in.mac, state ? true : false, device_in.type ? false : true);\n            }).then(function() {\n                msg.light.status = state ? 1 : 0;\n                node.send(msg);\n                ClearBusyTimer();\n                return connection.dispose();\n            }).catch(function() {\n                ClearBusyTimer();\n                return connection.dispose();\n            });\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire){\n    \n    // show lightify as busy\n    flow.set("LightifyIsBusy",1, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function(){\n                                        // do some stuff here if timeout\n                                        node.warn('Lightify Busy Timer Expired');\n                                        flow.set("LightifyIsBusy",0, 'memoryOnly');\n                                    }, TimeTillExpire || 5000);\n                                    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly')\n    \n}\n\nfunction ClearBusyTimer(){\n    \n    // show lightify as not busy\n    flow.set("LightifyIsBusy",0, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly');\n    \n}        \n\nfunction discover(connection) {\n    //node.warn('discover')\n    var self = this;\n    return connection.connect().then(function() {\n        //node.warn('Connected to Lightify Bridge');\n        //have to discover nodes for light status of group\n        return connection.discover();\n    }).then(function(data) {\n        return !showGroups ? Promise.resolve(data) :\n        new Promise(function(resolve, reject) {\n            //node.warn('discover zones');\n            connection.discoverZone()\n            .then(function(zones) {\n                //get zone info. if one of them is off, then this group is off\n                zones.result.reduce(function(av, zone){\n                    return av.then(function() {\n                        return connection\n                        .getZoneInfo(zone.id)\n                        .then(function(zoneInfo){\n                            zone.online = 2; // group always online\n                            zone.status = 0; // default to off\n                            zone.isBrightnessSupported = false;\n                            zone.isColorSupported = false;\n                            zone.isTemperatureSupported = false;\n                            if(!zoneInfo.result || zoneInfo.result.length === 0) {\n                                return Promise.reject('no result for zone');\n                            }\n                            for (var mac of zoneInfo.result[0].devices) {\n                                var device = data.result.find(function(d) {\n                                    return d.mac === mac;\n                                });\n                                if (device && device.online && device.status === 1) {\n                                    zone.status = 1;\n                                    node.warn('Lightify Zone is on');\n                                }\n                                if(device && lightify.isBrightnessSupported(device.type)) {\n                                    zone.isBrightnessSupported = true;\n                                    zone.brightness = device.brightness;\n                                    node.warn('Lightify Zone support brightness, current brightness=[%d]', device.brightness);\n                                }\n                                if(device && lightify.isColorSupported(device.type)) {\n                                    zone.isColorSupported = true;\n                                    zone.red = device.red;\n                                    zone.green = device.green;\n                                    c = device.blue;\n                                    node.warn('Lightify Zone support color, current red=[%d], green=[%d], blue=[%d]', device.red, zone.green, zone.blue);\n                                }\n                                if(device && lightify.isTemperatureSupported(device.type)) {\n                                    zone.isTemperatureSupported = true;\n                                    zone.temperature = device.temperature;\n                                    node.warn('Lightify Zone support temperature, current temperature=[%d]', device.temperature);\n                                }\n                            }\n                            return Promise.resolve();\n                        });\n                    });\n                }, Promise.resolve())\n                .then(function() {\n                    Array.prototype.push.apply(data.result, zones.result);\n                    resolve(data);\n                })\n                .catch(function(error) {\n                    node.warn('error 2');\n                    reject(error);\n                });\n            })\n            .catch(function(error) {\n                node.warn('error 1');\n                reject(error);\n            });\n        });\n    });\n}\n\nfunction accessories() {\n    //node.warn('accessories')\n    var self = this;\n    //var connection = new lightify.lightify(bridge_ip, self.log);\n    var connection = new lightify.lightify(bridge_ip);\n    discover(connection).then(function(data) {\n        var foundAccessories = [];\n        data.result.forEach(function(light) {\n            //node.warn(light);\n            msg.topic = light.name;\n            light.isBrightnessSupported = lightify.isBrightnessSupported(light.type);\n            light.isColorSupported = lightify.isColorSupported(light.type);\n            light.isTemperatureSupported = lightify.isTemperatureSupported(light.type);\n            msg.light = light;\n            node.send(msg);\n            if(!hideNodes && light.type && lightify.isLight(light.type)) {\n                //node.warn('Lightify Light [%s]', light.name);\n                foundAccessories.push(new LightifyAccessory(self, light));\n                //msg.light.name = light.name;\n                //msg.light.type = light.type;\n                //msg.light.status = light.status;\n                //node.send(msg);\n            } else if (!hideNodes && light.type && lightify.isPlug(light.type)) {\n                //node.warn('Lightify Plug [%s]', light.name);\n                foundAccessories.push(new LightifyOutlet(self, light));\n            } else if (!hideNodes && light.type && lightify.isSensor(light.type)) {\n                //node.warn('Lightify Sensor [%s]', light.name);\n                foundAccessories.push(new LightifySensor(self, light));\n            } else if(!light.type) {\n                foundAccessories.push(new LightifyAccessory(self, light));\n            }\n        });\n        //node.warn(foundAccessories);\n        connection.dispose();\n        //callback(self.foundAccessories);\n        //node.warn('Lightify accessories');\n        //self.refreshTimer();\n    }).catch(function(error) {\n        node.warn('Discovered failed', error);\n        throw 'can not connect to lightify bridge.';\n    });\n}\n\nfunction LightifyAccessory(platform, device) {\n    //node.warn('LightifyAccessory');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Lightbulb(device.name || 'Unknown');\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n\n    var self = this;\n    if(device.isColorSupported || lightify.isColorSupported(device.type)) {\n        this.colorBulb(platform);\n    } else if (device.isTemperatureSupported || lightify.isTemperatureSupported(device.type)) {\n        this.temperatureBulb(platform);\n    }\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n        this.service.addOptionalCharacteristic(Characteristic.Brightness);\n        this.service.getCharacteristic(Characteristic.Brightness).value = self.device.brightness;\n        this.service.getCharacteristic(Characteristic.Brightness)\n        .on('get', function(callback) {\n            callback(null, self.device.brightness);\n        })\n        .on('set', function(brightness, callback) {\n            if(self.setBrightnessTimer) {\n                clearTimeout(self.setBrightnessTimer);\n            }\n            self.setBrightnessTimer = setTimeout(function() {\n                var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n                connection.connect().then(function() {\n                    return connection.nodeBrightness(self.device.mac, brightness, 0, self.device.type ? false : true);\n                }).then(function() {\n                    self.device.brightness = brightness;\n                    return connection.dispose();\n                });\n            }, 80);\n            callback(null);\n        });\n    }\n\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false, self.device.type ? false : true);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyAccessory.prototype.setHSV = function(hsv) {\n    var rgb = HSVtoRGB(hsv.h, hsv.s, hsv.v);\n\n    this.device.red = rgb.r;\n    this.device.green = rgb.g;\n    this.device.blue = rgb.b;\n\n    var self = this;\n    if(this.setHSVTimer) {\n        clearTimeout(this.setHSVTimer);\n    }\n    this.setHSVTimer = setTimeout(function() {\n        var connection = new lightify.lightify(self.platform.config.bridge_ip, self.log);\n\n        connection.connect().then(function() {\n            return connection.nodeColor(self.device.mac,\n                self.device.red, self.device.green, self.device.blue, self.device.alpha, 0, self.device.type ? false : true);\n        }).then(function() {\n            return connection.dispose();\n        });\n    }, 100);\n\n}\nLightifyAccessory.prototype.colorBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.Hue);\n    this.service.addOptionalCharacteristic(Characteristic.Saturation);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n\n    var hsv = RGBtoHSV(this.device.red, this.device.green, this.device.blue);\n\n    this.service.getCharacteristic(Characteristic.Hue).value = hsv.h * 360;\n    this.service.getCharacteristic(Characteristic.Saturation).value = hsv.h * 100;\n    this.service.getCharacteristic(Characteristic.Brightness).value = hsv.v * 100;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.Hue)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.h * 360);\n    })\n    .on('set', function(h, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.h = h / 360.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n\n    this.service.getCharacteristic(Characteristic.Saturation)\n    .on('get', function(callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        callback(null, hsv.s * 100);\n    })\n    .on('set', function(s, callback) {\n        hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n        hsv.s = s / 100.0;\n        self.setHSV(hsv);\n        callback(null);\n    });\n}\nLightifyAccessory.prototype.temperatureBulb = function(platform) {\n    this.service.addOptionalCharacteristic(Characteristic.ColorTemperature);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n    var mired = 1000000 / this.device.temperature;\n\n    this.log.debug('temperatureBulb', mired);\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.ColorTemperature)\n    .on('get', function(callback) {\n        self.log.error('get temperature:', self.device.temperature, 'mired:', mired);\n        callback(null, mired);\n    })\n    .on('set', function(mired, callback) {\n        var temperature = 1000000 / mired;\n        self.log.error('sent temperature to set: ', temperature, 'mired:', mired);\n        \n        var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n        connection.connect().then(function() {\n            return connection.nodeTemperature(self.device.mac, temperature, 0, self.device.type ? false : true).then(function(data) {\n                self.log.error('set temperature (via mired): ', temperature); \n                self.device.temperature = temperature;\n                callback(null, mired);\n                return connection.dispose();\n            });\n        });\n    });\n}\nLightifyAccessory.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/ send updated status to HomeKit /\n    self.service.getCharacteristic(Characteristic.On).updateValue(device.status);\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type)) {\n\t\tself.service.getCharacteristic(Characteristic.Brightness).updateValue(self.device.brightness);\n\t}\n}\nLightifyAccessory.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifyOutlet(platform, device) {\n    //node.warn('LightifyOutlet');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Service.Outlet(device.name);\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n    this.service.getCharacteristic(Characteristic.OutletInUse).value = true;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.OutletInUse)\n    .on('get', function(callback) {\n        callback(null, true);\n    });\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback) {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback) {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function() {\n                return connection.nodeOnOff(self.device.mac, state ? true : false);\n            }).then(function() {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function() {\n                callback(null);\n                return connection.dispose();\n            });\n        });/\n}\nLightifyOutlet.prototype.updateDevice = function(device) {\n    this.device = device;\n}\nLightifyOutlet.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Outlet')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifySensor(platform, device) {\n    //node.warn('LightifySensor');\n/    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\t\n    var self = this;\n\n\t// contact status\n    this.service = new Service.ContactSensor(device.name);\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.ContactSensorState).value = true;\n    this.service.getCharacteristic(Characteristic.ContactSensorState)\n    .on('get', function(callback) {\n        callback(null, self.device.online == 2 && self.device.green == 1)\n    });/\n\t/\n\t// battery service\n\tthis.batteryService = new Service.BatteryService(device.name);\n    this.batteryService.getCharacteristic(Characteristic.Name).value = device.name;\n    this.batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tthis.batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t*/\n}\nLightifySensor.prototype.updateDevice = function(device) {\n    this.device = device;\n    var self = this;\n\t/* send updated status to HomeKit */\n\tself.service.getCharacteristic(Characteristic.ContactSensorState).updateValue(self.device.green);\n}\nLightifySensor.prototype.getServices = function() {\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Sensor')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if(this.service) {\n        services.push(this.service);\n    }\n\t\n    var self = this;\n\t\n\t// battery service\n\tvar batteryService = new Service.BatteryService();\n    batteryService.getCharacteristic(Characteristic.Name).value = this.name;\n    batteryService.getCharacteristic(Characteristic.BatteryLevel)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n\tbatteryService.getCharacteristic(Characteristic.ChargingState)\n    .on('get', function(callback) {\n        callback(null, false)\n    });\n\t\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n\tbatteryService.getCharacteristic(Characteristic.StatusLowBattery)\n    .on('get', function(callback) {\n        callback(null, self.device.brightness < 15 ? true : false)\n    });\n    services.push(batteryService);\n\t\n    if(this.batteryService) {\n        services.push(this.batteryService);\n    }\n\t\n    return services;\n}",
"outputs": 1,
"noerr": 0,
"x": 770,
"y": 340,
"wires": [
[
"228ec816.c78588"
]
]
},
{
"id": "69066150.2c3c7",
"type": "catch",
"z": "4ad1e2f.135b39c",
"name": "",
"scope": null,
"uncaught": false,
"x": 60,
"y": 20,
"wires": [
[
"81f30f8c.83c8c8"
]
]
},
{
"id": "81f30f8c.83c8c8",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 190,
"y": 20,
"wires": []
},
{
"id": "66751ef8.c56bc8",
"type": "subflow:4006453f.1d432c",
"z": "4ad1e2f.135b39c",
"name": "",
"env": [
{
"name": "Buffer_Size",
"type": "num",
"value": "20"
}
],
"x": 390,
"y": 300,
"wires": [
[
"730b03d7.40a86c",
"223c5bbc.9180fc"
],
[]
]
},
{
"id": "a76dc8ad.49c5d",
"type": "change",
"z": "4ad1e2f.135b39c",
"name": "",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "put",
"tot": "str"
},
{
"t": "move",
"p": "light",
"pt": "msg",
"to": "payload.light",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 420,
"y": 240,
"wires": [
[
"66751ef8.c56bc8",
"faf2a73d.6a8e88"
]
]
},
{
"id": "39effee8.066602",
"type": "inject",
"z": "4ad1e2f.135b39c",
"name": "Unload FIFO (500ms)",
"topic": "get",
"payload": "",
"payloadType": "date",
"repeat": "0.5",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"x": 140,
"y": 280,
"wires": [
[
"66751ef8.c56bc8"
]
]
},
{
"id": "bf4fd563.f9fc6",
"type": "change",
"z": "4ad1e2f.135b39c",
"name": "",
"rules": [
{
"t": "move",
"p": "payload.light",
"pt": "msg",
"to": "light",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 710,
"y": 400,
"wires": [
[
"ddcab773.74ff08"
]
]
},
{
"id": "730b03d7.40a86c",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Filter valid messages",
"func": "// when topic == put a new message is being put\n// into the buffer. likewise, when the payload is null\n// a trigger is being fired from the inject.\n\n// other nodes may be interacting with the gateway so\n// check if it is busy first. "LightifyIsBusy" is just a \n// variable used for handshaking between the nodes.\n\nvar BusyTimerTimeMs = 20000;\n\nvar LightifyIsBusy = flow.get("LightifyIsBusy", 'memoryOnly') || 0;\n\nif (msg.topic != 'put' && msg.payload){\n    if (!LightifyIsBusy){\n        SetBusyTimer(BusyTimerTimeMs);\n        return [null, msg]; // null to first output, msg to second\n    } else {\n        msg.topic = "put";\n        return [msg, null]; // to first output, null to second\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire){\n    \n    // show lightify as busy\n    flow.set("LightifyIsBusy",1, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function(){\n                                        // do some stuff here if timeout\n                                        node.warn('Lightify Busy Timer Expired');\n                                        flow.set("LightifyIsBusy",0, 'memoryOnly');\n                                    }, TimeTillExpire || 5000);\n                                    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly')\n    \n}\n\nfunction ClearBusyTimer(){\n    \n    // show lightify as not busy\n    flow.set("LightifyIsBusy",0, 'memoryOnly');\n                \n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n    \n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n    \n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer',LightifyIsBusyTimeoutTimer, 'memoryOnly');\n    \n}",
"outputs": 2,
"noerr": 0,
"x": 420,
"y": 380,
"wires": [
[
"420de8ec.1dbae8"
],
[
"bf4fd563.f9fc6"
]
]
},
{
"id": "3c5bcefd.65bd7a",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 770,
"y": 180,
"wires": []
},
{
"id": "6bbc5501.00db5c",
"type": "switch",
"z": "4ad1e2f.135b39c",
"name": "Devices",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "Contact",
"vt": "str"
},
{
"t": "cont",
"v": "Light",
"vt": "str"
},
{
"t": "cont",
"v": "Switch",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 640,
"y": 80,
"wires": [
[
"4b7c38a9.346b28"
],
[
"db8deb1f.d732c8"
],
[
"13956656.7043f2"
]
]
},
{
"id": "4b7c38a9.346b28",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "light",
"targetType": "msg",
"x": 780,
"y": 60,
"wires": []
},
{
"id": "e14a201b.157648",
"type": "catch",
"z": "4ad1e2f.135b39c",
"name": "",
"scope": [
"730b03d7.40a86c",
"d60169b2.b83b",
"ddcab773.74ff08"
],
"uncaught": false,
"x": 50,
"y": 60,
"wires": [
[
"3ac697f1.8e63c8"
]
]
},
{
"id": "3ac697f1.8e63c8",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Reset Variables",
"func": "flow.set("LightifyIsBusy",0, 'memoryOnly');\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 220,
"y": 60,
"wires": [
[
"37722444.0b63b4"
]
]
},
{
"id": "37722444.0b63b4",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 370,
"y": 60,
"wires": []
},
{
"id": "b302fba1.40ac48",
"type": "link in",
"z": "4ad1e2f.135b39c",
"name": "",
"links": [
"420de8ec.1dbae8"
],
"x": 135,
"y": 400,
"wires": [
[
"66751ef8.c56bc8"
]
]
},
{
"id": "420de8ec.1dbae8",
"type": "link out",
"z": "4ad1e2f.135b39c",
"name": "",
"links": [
"b302fba1.40ac48"
],
"x": 575,
"y": 360,
"wires": []
},
{
"id": "db8deb1f.d732c8",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "light",
"targetType": "msg",
"x": 780,
"y": 80,
"wires": []
},
{
"id": "13956656.7043f2",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "light",
"targetType": "msg",
"x": 780,
"y": 100,
"wires": []
},
{
"id": "59dd9ec1.d93eb",
"type": "inject",
"z": "4ad1e2f.135b39c",
"name": "Single Shot",
"topic": "flush",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"x": 110,
"y": 440,
"wires": [
[
"69a2ce86.4563c",
"66751ef8.c56bc8"
]
]
},
{
"id": "69a2ce86.4563c",
"type": "function",
"z": "4ad1e2f.135b39c",
"name": "Initialize Lightify",
"func": "var LightifyRetryCount = flow.set("LightifyRetryCount",0, 'memoryOnly');\nvar LightifyIsResponding = flow.set("LightifyIsResponding",1, 'memoryOnly');\nvar LightifyIsBusy = flow.set("LightifyIsBusy",0, 'memoryOnly');\nvar LightifyGettingGroups = flow.set("LightifyGettingGroups",false, 'memoryOnly');\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 320,
"y": 500,
"wires": [
[]
]
},
{
"id": "ab04325c.53c6f",
"type": "inject",
"z": "4ad1e2f.135b39c",
"name": "Manual Unload FIFO",
"topic": "get",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 130,
"y": 320,
"wires": [
[
"66751ef8.c56bc8"
]
]
},
{
"id": "963a432.3020e4",
"type": "inject",
"z": "4ad1e2f.135b39c",
"name": "Flush FIFO",
"topic": "flush",
"payload": "",
"payloadType": "date",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 100,
"y": 360,
"wires": [
[
"66751ef8.c56bc8"
]
]
},
{
"id": "faf2a73d.6a8e88",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 580,
"y": 240,
"wires": []
},
{
"id": "223c5bbc.9180fc",
"type": "debug",
"z": "4ad1e2f.135b39c",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 570,
"y": 300,
"wires": []
}
]

Ok, I really appreciate your time but it seems that there is something going on with the pasting into github. There seems to be an issue with the import when there are double quotes within functions. I was able to to a search/replace for that but then it looks like there are missing asterisks or double slash comments. Here is an example in Lightify In, function findAccessories(). Notice the single slash above and below. I don't know if this should be /*, */ or //. Again thanks for your help. Maybe try a pastebin?
node.send(msg_out_light);
/
if(!hideNodes && light.type && lightify.isLight(light.type)) {
//node.warn('Lightify Light [%s]', light.name);
foundAccessories.push(new LightifyAccessory(self, light));
//msg.light.name = light.name;
//msg.light.type = light.type;
//msg.light.status = light.status;
//node.send(msg);
} else if (!hideNodes && light.type && lightify.isPlug(light.type)) {
//node.warn('Lightify Plug [%s]', light.name);
foundAccessories.push(new LightifyOutlet(self, light));
} else if (!hideNodes && light.type && lightify.isSensor(light.type)) {
//node.warn('Lightify Sensor [%s]', light.name);
foundAccessories.push(new LightifySensor(self, light));
} else if(!light.type) {
foundAccessories.push(new LightifyAccessory(self, light));
}
/
});

Yes, I was able to verify this is an issue. Characters are being replace in the past into github. They are being interpreted as html. I just looked at the raw html for the page. Let's try pastebin.

Ok, I just did some test of cutting and pasting to github. I "think" it will be ok if it is pasted into a code block with the back ticks.

I'm so sorry for the issues we are having here. I've honestly never exported a flow for someone before. So, there are 2 ways of exporting from Node-RED and I don't know the difference. There is "Compact" and there is "Formatted". I exported both into 2 separate pastebins for you. Hopefully one of them will work. If not, we can try an email next. The links are below.
Also, in regards to getting away from the app, I would love to do that as well especially since they have announced they are turning off their servers in 2021. I will paste a link to a GitHub where the local protocol has been mostly reverse engineered. You can start there. However, I did some experimenting once where I removed internet connectivity from the gateway and tried pairing a new device. It would not work so it seems a connection to the Lightify servers is required.
The good news is that I have been looking at the Hubitat hub and it seems to support Lightify and has a local API.
Compact: https://pastebin.com/ZFLD3u5b
Formatted: https://pastebin.com/WYbcAEtV
Lightify Protocol: https://github.com/noctarius/lightify-binary-protocol

No problem. I have got the bulbs working to my satisfaction using chained promises and it seems to be working. It's far more simple then your flows so I'm sure I'm not covering all the bases but at the moment I only have 4 bulbs controlled by node-red and being via a node implementation of Alexa, so I'm at least working.
I also was able to hack away (as mentioned in my previous posts) at your export and replace the missing elements by converting the raw html on the page to the appropriate characters. As I mentioned, just using the code back ticks seems to be sufficient for fixing that issue. I will grab the pastebins and compare to make sure nothing was lost.
As far as the pairing. I have looked at that reverse of the protocol you mentioned and will be looking further into it in the future. I didn't know about the server shutdowns so I will be looking more urgently into a resolution. I think pairing will be the biggest thing. I'm going to mess with it and see if I can figure out the pairing sequence from reversing the Android App. I was able to do a similar thing with an Epson Wifi Projector so If I get anywhere, I'll be sure to let you know. I would be happy to connect with you at a more personal level to corroborate. I'm not sure how to do that on Github.

Ok, the pastebin worked fine. I will paste it here for others in case pastebin disappears:
[{"id":"8af0616b.5186d8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"56ba7bf.a388d84","type":"subflow","name":"FIFO","info":"# FIFO\n## First in First Out subflow\nThis flow receives a series of msg.payloads and builds a queue using FIFO (First in First out) method. The LIFO size is configurabe through subflow enviroment variables.\n\n### Input\nmsg.topic == put\nWill add the msg.payload to the end of the array. Everytime a new item is received the second output sends the complete queue.\n\nmsg.topic == get\nWill remove the first item of the stack and will send it in the first output\n\nmsg.topic == list\nSends the complete list on the second output.\n\n### Output 1\nThe first item on the top of the stack. It is sent only when msg.topic == get.\n\n### Output 2\nThe complete queue in Array format. It is sent everytime a new item is added, removed or when msg.topic == list\n\n### Status\nAlways show the queue size.\n\n### Enviroment Variables\nBuffer_Size defines the size of the queue. If a new item arrives and the queue is full, the oldest item will be removed.","category":"","in":[{"x":60,"y":180,"wires":[{"id":"822b038a.1e9e78"}]}],"out":[{"x":640,"y":120,"wires":[{"id":"978f3f81.7a0c3","port":0}]},{"x":640,"y":180,"wires":[{"id":"cc162253.786658","port":0}]}],"env":[{"name":"Buffer_Size","type":"num","value":"6"}],"icon":"font-awesome/fa-ellipsis-v","status":{"x":800,"y":200,"wires":[{"id":"a676ac3a.9a9338","port":0}]}},{"id":"8bea8c79.ed4d2","type":"subflow","name":"FIFO (2)","info":"# FIFO\n## First in First Out subflow\nThis flow receives a series of msg.payloads and builds a queue using FIFO (First in First out) method. The LIFO size is configurabe through subflow enviroment variables.\n\n### Input\nmsg.topic == put\nWill add the msg.payload to the end of the array. Everytime a new item is received the second output sends the complete queue.\n\nmsg.topic == get\nWill remove the first item of the stack and will send it in the first output\n\nmsg.topic == list\nSends the complete list on the second output.\n\n### Output 1\nThe first item on the top of the stack. It is sent only when msg.topic == get.\n\n### Output 2\nThe complete queue in Array format. It is sent everytime a new item is added, removed or when msg.topic == list\n\n### Status\nAlways show the queue size.\n\n### Enviroment Variables\nBuffer_Size defines the size of the queue. If a new item arrives and the queue is full, the oldest item will be removed.","category":"","in":[{"x":60,"y":180,"wires":[{"id":"36fe97f7.cc6ba8"}]}],"out":[{"x":640,"y":120,"wires":[{"id":"e8971eb2.450db","port":0}]},{"x":640,"y":180,"wires":[{"id":"8a1ee002.356e7","port":0}]}],"env":[{"name":"Buffer_Size","type":"num","value":"6"}],"icon":"font-awesome/fa-ellipsis-v","status":{"x":800,"y":200,"wires":[{"id":"ba1173a6.a84dc8","port":0}]}},{"id":"68b8642a.42b47c","type":"ui_base","theme":{"name":"theme-light","lightTheme":{"default":"#0094CE","baseColor":"#0094CE","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":true,"reset":false},"darkTheme":{"default":"#097479","baseColor":"#097479","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":false},"customTheme":{"name":"Untitled Theme 1","default":"#4B7930","baseColor":"#4B7930","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"},"themeState":{"base-color":{"default":"#0094CE","value":"#0094CE","edited":false},"page-titlebar-backgroundColor":{"value":"#0094CE","edited":false},"page-backgroundColor":{"value":"#fafafa","edited":false},"page-sidebar-backgroundColor":{"value":"#ffffff","edited":false},"group-textColor":{"value":"#1bbfff","edited":false},"group-borderColor":{"value":"#ffffff","edited":false},"group-backgroundColor":{"value":"#ffffff","edited":false},"widget-textColor":{"value":"#111111","edited":false},"widget-backgroundColor":{"value":"#0094ce","edited":false},"widget-borderColor":{"value":"#ffffff","edited":false},"base-font":{"value":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"}},"angularTheme":{"primary":"indigo","accents":"blue","warn":"red","background":"grey"}},"site":{"name":"Node-RED Dashboard","hideToolbar":"false","allowSwipe":"false","lockMenu":"false","allowTempTheme":"true","dateFormat":"DD/MM/YYYY","sizes":{"sx":48,"sy":48,"gx":6,"gy":6,"cx":6,"cy":6,"px":0,"py":0}}},{"id":"822b038a.1e9e78","type":"switch","z":"56ba7bf.a388d84","name":"Topic","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"get","vt":"str"},{"t":"eq","v":"put","vt":"str"},{"t":"eq","v":"list","vt":"str"},{"t":"eq","v":"flush","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":5,"x":190,"y":180,"wires":[["978f3f81.7a0c3"],["3618067.24089fa"],["cc162253.786658"],["db95af8f.391e18"],["cc162253.786658"]]},{"id":"978f3f81.7a0c3","type":"function","z":"56ba7bf.a388d84","name":"get","func":"var queue = flow.get('queue')\nvar item;\n\nif (!Array.isArray(queue)){\n queue = [];\n}else{\n item = queue.pop(1);\n}\n\n\nflow.set('queue', queue)\nmsg.payload = item;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":120,"wires":[["cc162253.786658"]]},{"id":"cc162253.786658","type":"change","z":"56ba7bf.a388d84","name":"list","rules":[{"t":"set","p":"payload","pt":"msg","to":"queue","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":260,"wires":[["a676ac3a.9a9338"]]},{"id":"a676ac3a.9a9338","type":"change","z":"56ba7bf.a388d84","name":"Count","rules":[{"t":"set","p":"payload","pt":"msg","to":"$count(msg.payload)\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":260,"wires":[[]]},{"id":"3618067.24089fa","type":"function","z":"56ba7bf.a388d84","name":"put","func":"var queue = flow.get('queue'))\n\n\nif (!Array.isArray(queue)){\n queue = [];\n}else if ( queue.length >= env.get('Buffer_Size')) ){\n queue.pop(1);\n}\n\nqueue.unshift(msg.payload);\n\nflow.set('queue'), queue);\nmsg.payload = queue;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":160,"wires":[["cc162253.786658"]]},{"id":"598d5c3d.6c92f4","type":"debug","z":"56ba7bf.a388d84","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":530,"y":40,"wires":[]},{"id":"5b2a5eea.7c5cf","type":"debug","z":"56ba7bf.a388d84","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":730,"y":60,"wires":[]},{"id":"db95af8f.391e18","type":"function","z":"56ba7bf.a388d84","name":"flush","func":"var queue = flow.get('queue'))\n\n\nif (!Array.isArray(queue)){\n queue = [];\n}else{\n while (queue.length > 0){\n queue.pop();\n }\n}\n\nflow.set('queue'), queue);\nmsg.payload = queue;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":200,"wires":[["cc162253.786658"]]},{"id":"36fe97f7.cc6ba8","type":"switch","z":"8bea8c79.ed4d2","name":"Topic","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"get","vt":"str"},{"t":"eq","v":"put","vt":"str"},{"t":"eq","v":"list","vt":"str"},{"t":"eq","v":"flush","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":5,"x":190,"y":180,"wires":[["e8971eb2.450db"],["708fa5c6.e9ef2c"],["8a1ee002.356e7"],["c06a064d.d3d7"],["8a1ee002.356e7"]]},{"id":"e8971eb2.450db","type":"function","z":"8bea8c79.ed4d2","name":"get","func":"var queue = flow.get('queue')\nvar item;\n\nif (!Array.isArray(queue))\n{\n    queue = [];\n}\nelse\n{\n    item = queue.pop(1);\n}\n\nflow.set('queue', queue)\nmsg.payload = item;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":120,"wires":[["8a1ee002.356e7"]]},{"id":"8a1ee002.356e7","type":"change","z":"8bea8c79.ed4d2","name":"list","rules":[{"t":"set","p":"payload","pt":"msg","to":"queue","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":260,"wires":[["ba1173a6.a84dc8"]]},{"id":"ba1173a6.a84dc8","type":"change","z":"8bea8c79.ed4d2","name":"Count","rules":[{"t":"set","p":"payload","pt":"msg","to":"$count(msg.payload)\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":260,"wires":[[]]},{"id":"708fa5c6.e9ef2c","type":"function","z":"8bea8c79.ed4d2","name":"put","func":"var queue = flow.get('queue')\n\nif (!Array.isArray(queue))\n{\n    queue = [];\n}\nelse if (queue.length >= env.get('Buffer_Size'))\n{\n    queue.pop(1);\n}\n\nqueue.unshift(msg.payload);\n\nflow.set('queue', queue);\nmsg.payload = queue;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":160,"wires":[["8a1ee002.356e7"]]},{"id":"57197166.a71f98","type":"debug","z":"8bea8c79.ed4d2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":530,"y":40,"wires":[]},{"id":"77007991.2411d8","type":"debug","z":"8bea8c79.ed4d2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":730,"y":60,"wires":[]},{"id":"c06a064d.d3d7","type":"function","z":"8bea8c79.ed4d2","name":"flush","func":"var queue = flow.get('queue')\n\nif (!Array.isArray(queue))\n{\n    queue = [];\n}\nelse\n{\n    while (queue.length > 0)\n    {\n        queue.pop();\n    }\n}\n\nflow.set('queue', queue);\nmsg.payload = queue;\n\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":200,"wires":[["8a1ee002.356e7"]]},{"id":"fe8cb5c5.df54d","type":"function","z":"8af0616b.5186d8","name":"Lightify In","func":"// 'platform': 'Lightify',\n// 'bridge_ip': '192.168.0.16',\n// 'name': 'Lightify',\n// 'showGroups': true,\n// 'hideNodes': false,\n// 'pollFreqSecs' : '2'\n//var bridge_ip = '192.168.0.16'; // bridge 2\nvar bridge_ip = '192.168.0.79'; // bridge 1\nvar showGroups = true;\nvar hideNodes = false;\n\nvar moment = global.get('moment');\nvar util = global.get('util');\nvar lightify = global.get('lightify');\nvar Service, Characteristic;\nvar Lightbulb;\nvar log = node;\nvar BusyTimerTimeMs = 20000;\n\n// how long node-lightify should wait before timing out the connection to the bridge.\n// this should ideally be shorter than your poll rate. note that this depends on a modified copy\n// of node-lightify as the master branch does not have this feature.\nvar cfgLightifyBridgeConnectTimeout = 10000; // ms\n// how many counts to pass before retrying a connection to the unresponsive gateway.\n// set this to a value greater than cfgLightifyBridgeConnectTimeout above.\nvar cfgLightifyRetryCount = 10;\n\nvar LightifyRetryCount = flow.get('LightifyRetryCount', 'memoryOnly') || 0;\nvar LightifyIsResponding = flow.get('LightifyIsResponding', 'memoryOnly') || 0;\nvar LightifyIsBusy = flow.get('LightifyIsBusy', 'memoryOnly') || 0;\nvar LightifyGettingGroups = flow.get('LightifyGettingGroups', 'memoryOnly') || false;\n\nif (LightifyIsBusy === 0)\n{\n    SetBusyTimer(BusyTimerTimeMs);\n    if (LightifyIsResponding > 0 || LightifyRetryCount >= cfgLightifyRetryCount)\n    {\n        if (LightifyIsResponding === 0 && LightifyRetryCount >= cfgLightifyRetryCount)\n        {\n            node.warn('Lightify is responding again!')\n            flow.set('LightifyIsResponding', 1, 'memoryOnly');\n        }\n        if (LightifyRetryCount > cfgLightifyRetryCount)\n        {\n            node.warn('Retrying Lightify connection.')\n        }\n        flow.set('LightifyRetryCount', 0, 'memoryOnly');\n        findAccessories();\n    }\n    else\n    {\n        node.warn('Lightify is not responding. Incrementing retry counter ' + (cfgLightifyRetryCount - LightifyRetryCount) + ' times.')\n        flow.set('LightifyRetryCount', LightifyRetryCount + 1, 'memoryOnly');\n        ClearBusyTimer();\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire)\n{\n\n    // show lightify as busy\n    flow.set('LightifyIsBusy', 1, 'memoryOnly');\n\n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n\n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function()\n    {\n        // do some stuff here if timeout\n        node.warn('Lightify Busy Timer Expired');\n        flow.set('LightifyIsBusy', 0, 'memoryOnly');\n    }, TimeTillExpire || 5000);\n\n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer', LightifyIsBusyTimeoutTimer, 'memoryOnly')\n\n}\n\nfunction ClearBusyTimer()\n{\n\n    // show lightify as not busy\n    flow.set('LightifyIsBusy', 0, 'memoryOnly');\n\n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n\n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n\n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer', LightifyIsBusyTimeoutTimer, 'memoryOnly');\n\n}\n\nfunction findAccessories()\n{\n    var self = this;\n    var connection = new lightify.lightify(bridge_ip);\n    discover(connection).then(function(data)\n    {\n        //var foundAccessories = [];\n        data.result.forEach(function(light)\n        {\n            var msg_out_light = Object.assign(\n            {}, msg); // create new message\n            msg_out_light.topic = light.name;\n            //msg_out_light.payload = '';\n            light.isBrightnessSupported = lightify.isBrightnessSupported(light.type);\n            light.isColorSupported = lightify.isColorSupported(light.type);\n            light.isTemperatureSupported = lightify.isTemperatureSupported(light.type);\n            light.isLight = lightify.isLight(light.type);\n            light.isSwitch = lightify.isSwitch(light.type);\n            light.isPlug = lightify.isPlug(light.type);\n            light.isSensor = lightify.isSensor(light.type);\n            msg_out_light.light = light;\n            node.send(msg_out_light);\n            /*\n            if (!hideNodes && light.type && lightify.isLight(light.type))\n            {\n                //node.warn('Lightify Light [%s]', light.name);\n                foundAccessories.push(new LightifyAccessory(self, light));\n                //msg.light.name = light.name;\n                //msg.light.type = light.type;\n                //msg.light.status = light.status;\n                //node.send(msg);\n            }\n            else if (!hideNodes && light.type && lightify.isPlug(light.type))\n            {\n                //node.warn('Lightify Plug [%s]', light.name);\n                foundAccessories.push(new LightifyOutlet(self, light));\n            }\n            else if (!hideNodes && light.type && lightify.isSensor(light.type))\n            {\n                //node.warn('Lightify Sensor [%s]', light.name);\n                foundAccessories.push(new LightifySensor(self, light));\n            }\n            else if (!light.type)\n            {\n                foundAccessories.push(new LightifyAccessory(self, light));\n            }\n            */\n        });\n        connection.dispose();\n\n        flow.set('LightifyIsResponding', 1, 'memoryOnly');\n        ClearBusyTimer();\n        flow.set('LightifyGettingGroups', !LightifyGettingGroups, 'memoryOnly'); // get groups every other message\n\n        //var elapsedTime = Date.now() - msg.payload;\n        //node.warn('Elasped Time: ' + elapsedTime.toString() + ' ms');\n    }).catch(function(error)\n    {\n        flow.set('LightifyIsResponding', 0, 'memoryOnly');\n        ClearBusyTimer();\n        node.warn('Discovered failed', error);\n    });\n}\n\nfunction discover(connection)\n{\n    var self = this;\n    return connection.connect(cfgLightifyBridgeConnectTimeout).then(function()\n    {\n        //have to discover nodes for light status of group\n        //var elapsedTime = Date.now() - msg.payload;\n        //node.warn('Discovered light nodes: ' + elapsedTime.toString() + ' ms');\n        return connection.discover();\n    }).then(function(data)\n    {\n        //return !showGroups ? Promise.resolve(data) :\n        return !LightifyGettingGroups ? Promise.resolve(data) :\n            new Promise(function(resolve, reject)\n            {\n                //node.warn('discover zones');\n                connection.discoverZone()\n                    .then(function(zones)\n                    {\n                        //var elapsedTime = Date.now() - msg.payload;\n                        //node.warn('Discovered zones: ' + elapsedTime.toString() + ' ms');\n                        //get zone info. if one of them is off, then this group is off\n                        zones.result.reduce(function(av, zone)\n                            {\n                                return av.then(function()\n                                {\n                                    return connection\n                                        .getZoneInfo(zone.id)\n                                        .then(function(zoneInfo)\n                                        {\n                                            //var elapsedTime = Date.now() - msg.payload;\n                                            //node.warn('Got zone info: ' + elapsedTime.toString() + ' ms');\n                                            zone.online = 2; // group always online\n                                            zone.status = 0; // default to off\n                                            zone.isBrightnessSupported = false;\n                                            zone.isColorSupported = false;\n                                            zone.isTemperatureSupported = false;\n                                            if (!zoneInfo.result || zoneInfo.result.length === 0)\n                                            {\n                                                return Promise.reject('no result for zone');\n                                            }\n                                            //node.warn(zoneInfo.result);\n                                            for (var mac of zoneInfo.result[0].devices)\n                                            {\n                                                //var elapsedTime = Date.now() - msg.payload;\n                                                //node.warn('Got zone device info: ' + elapsedTime.toString() + ' ms');\n                                                //node.warn('getting mac');\n                                                var device = data.result.find(function(d)\n                                                {\n                                                    return d.mac === mac;\n                                                });\n                                                //node.warn(device);\n                                                if (device && device.online && device.status === 1)\n                                                {\n                                                    zone.status = 1;\n                                                    //node.warn('Lightify Zone is on');\n                                                }\n                                                if (device && lightify.isBrightnessSupported(device.type))\n                                                {\n                                                    zone.isBrightnessSupported = true;\n                                                    zone.brightness = device.brightness;\n                                                    //node.warn('Lightify Zone support brightness, current brightness=[%d]', device.brightness);\n                                                }\n                                                if (device && lightify.isColorSupported(device.type))\n                                                {\n                                                    zone.isColorSupported = true;\n                                                    zone.red = device.red;\n                                                    zone.green = device.green;\n                                                    zone.blue = device.blue;\n                                                    //c = device.blue; // why was this here??\n                                                    //node.warn('Lightify Zone support color, current red=[%d], green=[%d], blue=[%d]', device.red, zone.green, zone.blue);\n                                                }\n                                                if (device && lightify.isTemperatureSupported(device.type))\n                                                {\n                                                    zone.isTemperatureSupported = true;\n                                                    zone.temperature = device.temperature;\n                                                    //node.warn('Lightify Zone support temperature, current temperature=[%d]', device.temperature);\n                                                }\n                                            }\n                                            return Promise.resolve();\n                                        });\n                                });\n                            }, Promise.resolve())\n                            .then(function()\n                            {\n                                Array.prototype.push.apply(data.result, zones.result);\n                                resolve(data);\n                            })\n                            .catch(function(error)\n                            {\n                                node.warn('error 2');\n                                reject(error);\n                            });\n                    })\n                    .catch(function(error)\n                    {\n                        node.warn('error 1');\n                        reject(error);\n                    });\n            });\n    });\n}\n\nfunction LightifyAccessory(platform, device)\n{\n    //node.warn('LightifyAccessory');\n    /*\n    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Lightbulb(device.name || 'Unknown');\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n\n    var self = this;\n    if (device.isColorSupported || lightify.isColorSupported(device.type))\n    {\n        this.colorBulb(platform);\n    }\n    else if (device.isTemperatureSupported || lightify.isTemperatureSupported(device.type))\n    {\n        this.temperatureBulb(platform);\n    }\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type))\n    {\n        this.service.addOptionalCharacteristic(Characteristic.Brightness);\n        this.service.getCharacteristic(Characteristic.Brightness).value = self.device.brightness;\n        this.service.getCharacteristic(Characteristic.Brightness)\n            .on('get', function(callback)\n            {\n                callback(null, self.device.brightness);\n            })\n            .on('set', function(brightness, callback)\n            {\n                if (self.setBrightnessTimer)\n                {\n                    clearTimeout(self.setBrightnessTimer);\n                }\n                self.setBrightnessTimer = setTimeout(function()\n                {\n                    var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n                    connection.connect().then(function()\n                    {\n                        return connection.nodeBrightness(self.device.mac, brightness, 0, self.device.type ? false : true);\n                    }).then(function()\n                    {\n                        self.device.brightness = brightness;\n                        return connection.dispose();\n                    });\n                }, 80);\n                callback(null);\n            });\n    }\n\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback)\n        {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function()\n            {\n                return connection.nodeOnOff(self.device.mac, state ? true : false, self.device.type ? false : true);\n            }).then(function()\n            {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function()\n            {\n                callback(null);\n                return connection.dispose();\n            });\n        });\n        */\n}\nLightifyAccessory.prototype.setHSV = function(hsv)\n{\n    var rgb = HSVtoRGB(hsv.h, hsv.s, hsv.v);\n\n    this.device.red = rgb.r;\n    this.device.green = rgb.g;\n    this.device.blue = rgb.b;\n\n    var self = this;\n    if (this.setHSVTimer)\n    {\n        clearTimeout(this.setHSVTimer);\n    }\n    this.setHSVTimer = setTimeout(function()\n    {\n        var connection = new lightify.lightify(self.platform.config.bridge_ip, self.log);\n\n        connection.connect().then(function()\n        {\n            return connection.nodeColor(self.device.mac,\n                self.device.red, self.device.green, self.device.blue, self.device.alpha, 0, self.device.type ? false : true);\n        }).then(function()\n        {\n            return connection.dispose();\n        });\n    }, 100);\n\n}\nLightifyAccessory.prototype.colorBulb = function(platform)\n{\n    this.service.addOptionalCharacteristic(Characteristic.Hue);\n    this.service.addOptionalCharacteristic(Characteristic.Saturation);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n\n    var hsv = RGBtoHSV(this.device.red, this.device.green, this.device.blue);\n\n    this.service.getCharacteristic(Characteristic.Hue).value = hsv.h * 360;\n    this.service.getCharacteristic(Characteristic.Saturation).value = hsv.h * 100;\n    this.service.getCharacteristic(Characteristic.Brightness).value = hsv.v * 100;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.Hue)\n        .on('get', function(callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            callback(null, hsv.h * 360);\n        })\n        .on('set', function(h, callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            hsv.h = h / 360.0;\n            self.setHSV(hsv);\n            callback(null);\n        });\n\n    this.service.getCharacteristic(Characteristic.Saturation)\n        .on('get', function(callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            callback(null, hsv.s * 100);\n        })\n        .on('set', function(s, callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            hsv.s = s / 100.0;\n            self.setHSV(hsv);\n            callback(null);\n        });\n}\nLightifyAccessory.prototype.temperatureBulb = function(platform)\n{\n    this.service.addOptionalCharacteristic(Characteristic.ColorTemperature);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n    var mired = 1000000 / this.device.temperature;\n\n    this.log.debug('temperatureBulb', mired);\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.ColorTemperature)\n        .on('get', function(callback)\n        {\n            self.log.error('get temperature:', self.device.temperature, 'mired:', mired);\n            callback(null, mired);\n        })\n        .on('set', function(mired, callback)\n        {\n            var temperature = 1000000 / mired;\n            self.log.error('sent temperature to set: ', temperature, 'mired:', mired);\n\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function()\n            {\n                return connection.nodeTemperature(self.device.mac, temperature, 0, self.device.type ? false : true).then(function(data)\n                {\n                    self.log.error('set temperature (via mired): ', temperature);\n                    self.device.temperature = temperature;\n                    callback(null, mired);\n                    return connection.dispose();\n                });\n            });\n        });\n}\nLightifyAccessory.prototype.updateDevice = function(device)\n{\n    this.device = device;\n    var self = this;\n    /* send updated status to HomeKit */\n    self.service.getCharacteristic(Characteristic.On).updateValue(device.status);\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type))\n    {\n        self.service.getCharacteristic(Characteristic.Brightness).updateValue(self.device.brightness);\n    }\n}\nLightifyAccessory.prototype.getServices = function()\n{\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if (this.service)\n    {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifyOutlet(platform, device)\n{\n    //node.warn('LightifyOutlet');\n    /*\n    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Service.Outlet(device.name);\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n    this.service.getCharacteristic(Characteristic.OutletInUse).value = true;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.OutletInUse)\n        .on('get', function(callback)\n        {\n            callback(null, true);\n        });\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback)\n        {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function()\n            {\n                return connection.nodeOnOff(self.device.mac, state ? true : false);\n            }).then(function()\n            {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function()\n            {\n                callback(null);\n                return connection.dispose();\n            });\n        });\n        */\n}\nLightifyOutlet.prototype.updateDevice = function(device)\n{\n    this.device = device;\n}\nLightifyOutlet.prototype.getServices = function()\n{\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Outlet')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if (this.service)\n    {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifySensor(platform, device)\n{\n    //node.warn('LightifySensor');\n    /*\n    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    var self = this;\n\n    // contact status\n    this.service = new Service.ContactSensor(device.name);\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.ContactSensorState).value = true;\n    this.service.getCharacteristic(Characteristic.ContactSensorState)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.online == 2 && self.device.green == 1)\n        }); \n\n    // battery service\n    this.batteryService = new Service.BatteryService(device.name);\n    this.batteryService.getCharacteristic(Characteristic.Name).value = device.name;\n    this.batteryService.getCharacteristic(Characteristic.BatteryLevel)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.brightness)\n        });\n\n    this.batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n    this.batteryService.getCharacteristic(Characteristic.ChargingState)\n        .on('get', function(callback)\n        {\n            callback(null, false)\n        });\n\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n        .on('get', function(callback)\n        {\n            callback(null, false)\n        });\n    */\n}\nLightifySensor.prototype.updateDevice = function(device)\n{\n    this.device = device;\n    var self = this;\n    /* send updated status to HomeKit */\n    self.service.getCharacteristic(Characteristic.ContactSensorState).updateValue(self.device.green);\n}\nLightifySensor.prototype.getServices = function()\n{\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Sensor')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if (this.service)\n    {\n        services.push(this.service);\n    }\n\n    var self = this;\n\n    // battery service\n    var batteryService = new Service.BatteryService();\n    batteryService.getCharacteristic(Characteristic.Name).value = this.name;\n    batteryService.getCharacteristic(Characteristic.BatteryLevel)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.brightness)\n        });\n\n    batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n    batteryService.getCharacteristic(Characteristic.ChargingState)\n        .on('get', function(callback)\n        {\n            callback(null, false)\n        });\n\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.brightness < 15 ? true : false)\n        });\n    services.push(batteryService);\n\n    if (this.batteryService)\n    {\n        services.push(this.batteryService);\n    }\n\n    return services;\n}","outputs":1,"noerr":0,"x":620,"y":220,"wires":[["834f34b4.15ead8","33d86e38.a6e3c2","301cd745.3c7a8","fb292f75.edc9a"]]},{"id":"94b7f95c.66e8f8","type":"inject","z":"8af0616b.5186d8","name":"Get accessories (2000ms)","topic":"","payload":"","payloadType":"date","repeat":"20","crontab":"","once":true,"onceDelay":"5","x":420,"y":220,"wires":[["fe8cb5c5.df54d"]]},{"id":"834f34b4.15ead8","type":"link out","z":"8af0616b.5186d8","name":"Homebridge Out","links":["2ff95594.9f519a"],"x":795,"y":280,"wires":[]},{"id":"a2c756f4.1b3848","type":"link in","z":"8af0616b.5186d8","name":"Homebridge In","links":["a3113f68.88c998"],"x":115,"y":280,"wires":[["160861ae.26ef4e"]]},{"id":"33d86e38.a6e3c2","type":"function","z":"8af0616b.5186d8","name":"Save Lightify Accessories","func":"// save the light so we can look up its data\n// when homekit sends a command.\nglobal.set('LightifyAccessory['+msg.light.id+']',msg.light, 'memoryOnly')","outputs":1,"noerr":0,"x":850,"y":320,"wires":[[]]},{"id":"160861ae.26ef4e","type":"function","z":"8af0616b.5186d8","name":"Look up Accessory","func":"try\n{\n    var accessoryObjects = global.get('LightifyAccessory', 'memoryOnly') || 0;\n    if (accessoryObjects !== 0)\n    {\n        msg.light = getByValue3(accessoryObjects, msg.name);\n        node.send(msg);\n    }\n}\ncatch (error)\n{\n    node.warn(error)\n}\n\nfunction getByValue(arr, value)\n{\n    for (var i = 0, iLen = arr.length; i < iLen; i++)\n    {\n        if (arr[i] !== null)\n        {\n            if (arr[i].hasOwnProperty('name'))\n            {\n                if (arr[i].name !== null)\n                {\n                    if (arr[i].name == value) return arr[i];\n                }\n            }\n        }\n    }\n}\n\nfunction getByValue2(arr, value)\n{\n\n    var result = arr.filter(function(o)\n    {\n        return o.name == value;\n    });\n\n    return result ? result[0] : null; // or undefined\n\n}\n\nfunction getByValue3(arr, value)\n{\n\n    var result = [];\n\n    arr.forEach(function(o)\n    {\n        if (o.name == value) result.push(o);\n    });\n\n    return result ? result[0] : null; // or undefined\n\n}\n\nfunction getByValue4(arr, value)\n{\n    var o;\n\n    for (var i = 0, iLen = arr.length; i < iLen; i++)\n    {\n        o = arr[i];\n\n        for (var name in o)\n        {\n            if (o.hasOwnProperty(name) && o[name] == value)\n            {\n                return o;\n            }\n        }\n    }\n}","outputs":1,"noerr":0,"x":270,"y":280,"wires":[["ebc9dc19.62a2d8"]]},{"id":"c5eb91cc.cc87b8","type":"function","z":"8af0616b.5186d8","name":"Lightify Out","func":"var bridge_ip = '192.168.0.28';\n//var bridge_ip = '192.168.0.16';\n\nvar moment = global.get('moment');\nvar util = global.get('util');\nvar lightify = global.get('lightify');\nvar BusyTimerTimeMs = 20000;\n\n// how long node-lightify should wait before timing out the connection to the bridge.\n// this should ideally be shorter than your poll rate. note that this depends on a modified copy\n// of node-lightify as the master branch does not have this feature.\nvar cfgLightifyBridgeConnectTimeout = 1000; // ms\n\nvar LightifyIsResponding = flow.get('LightifyIsResponding', 'memoryOnly');\nif (LightifyIsResponding > 0)\n{\n    var device_in = msg.light\n    var connection = new lightify.lightify(bridge_ip);\n\n    if (msg.payload.hasOwnProperty('Brightness'))\n    {\n        //node.warn('Brightness');\n        //node.warn(device);\n        //if(setBrightnessTimer) {\n        // clearTimeout(setBrightnessTimer);\n        //}\n        //setBrightnessTimer = setTimeout(function() {\n        var brightness = msg.payload.Brightness;\n        connection.connect(cfgLightifyBridgeConnectTimeout).then(function()\n        {\n            return connection.nodeBrightness(device_in.mac, brightness, 0, device_in.type ? false : true);\n        }).then(function()\n        {\n            msg.light.brightness = brightness;\n            node.send(msg);\n            ClearBusyTimer();\n            return connection.dispose();\n        }).catch(function()\n        {\n            ClearBusyTimer();\n            return connection.dispose();\n        });\n        //}, 80);\n    }\n    else if (msg.payload.hasOwnProperty('On'))\n    {\n        //node.warn('On');\n        //node.warn(device);\n        var state = msg.payload.On;\n        connection.connect(cfgLightifyBridgeConnectTimeout).then(function()\n        {\n            return connection.nodeOnOff(device_in.mac, state ? true : false, device_in.type ? false : true);\n        }).then(function()\n        {\n            msg.light.status = state ? 1 : 0;\n            node.send(msg);\n            ClearBusyTimer();\n            return connection.dispose();\n        }).catch(function()\n        {\n            ClearBusyTimer();\n            return connection.dispose();\n        });\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire)\n{\n\n    // show lightify as busy\n    flow.set('LightifyIsBusy', 1, 'memoryOnly');\n\n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n\n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function()\n    {\n        // do some stuff here if timeout\n        node.warn('Lightify Busy Timer Expired');\n        flow.set('LightifyIsBusy', 0, 'memoryOnly');\n    }, TimeTillExpire || 5000);\n\n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer', LightifyIsBusyTimeoutTimer, 'memoryOnly')\n\n}\n\nfunction ClearBusyTimer()\n{\n\n    // show lightify as not busy\n    flow.set('LightifyIsBusy', 0, 'memoryOnly');\n\n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n\n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n\n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer', LightifyIsBusyTimeoutTimer, 'memoryOnly');\n\n}\n\nfunction discover(connection)\n{\n    //node.warn('discover')\n    var self = this;\n    return connection.connect().then(function()\n    {\n        //node.warn('Connected to Lightify Bridge');\n        //have to discover nodes for light status of group\n        return connection.discover();\n    }).then(function(data)\n    {\n        return !showGroups ? Promise.resolve(data) :\n            new Promise(function(resolve, reject)\n            {\n                //node.warn('discover zones');\n                connection.discoverZone()\n                    .then(function(zones)\n                    {\n                        //get zone info. if one of them is off, then this group is off\n                        zones.result.reduce(function(av, zone)\n                            {\n                                return av.then(function()\n                                {\n                                    return connection\n                                        .getZoneInfo(zone.id)\n                                        .then(function(zoneInfo)\n                                        {\n                                            zone.online = 2; // group always online\n                                            zone.status = 0; // default to off\n                                            zone.isBrightnessSupported = false;\n                                            zone.isColorSupported = false;\n                                            zone.isTemperatureSupported = false;\n                                            if (!zoneInfo.result || zoneInfo.result.length === 0)\n                                            {\n                                                return Promise.reject('no result for zone');\n                                            }\n                                            for (var mac of zoneInfo.result[0].devices)\n                                            {\n                                                var device = data.result.find(function(d)\n                                                {\n                                                    return d.mac === mac;\n                                                });\n                                                if (device && device.online && device.status === 1)\n                                                {\n                                                    zone.status = 1;\n                                                    node.warn('Lightify Zone is on');\n                                                }\n                                                if (device && lightify.isBrightnessSupported(device.type))\n                                                {\n                                                    zone.isBrightnessSupported = true;\n                                                    zone.brightness = device.brightness;\n                                                    node.warn('Lightify Zone support brightness, current brightness=[%d]', device.brightness);\n                                                }\n                                                if (device && lightify.isColorSupported(device.type))\n                                                {\n                                                    zone.isColorSupported = true;\n                                                    zone.red = device.red;\n                                                    zone.green = device.green;\n                                                    c = device.blue;\n                                                    node.warn('Lightify Zone support color, current red=[%d], green=[%d], blue=[%d]', device.red, zone.green, zone.blue);\n                                                }\n                                                if (device && lightify.isTemperatureSupported(device.type))\n                                                {\n                                                    zone.isTemperatureSupported = true;\n                                                    zone.temperature = device.temperature;\n                                                    node.warn('Lightify Zone support temperature, current temperature=[%d]', device.temperature);\n                                                }\n                                            }\n                                            return Promise.resolve();\n                                        });\n                                });\n                            }, Promise.resolve())\n                            .then(function()\n                            {\n                                Array.prototype.push.apply(data.result, zones.result);\n                                resolve(data);\n                            })\n                            .catch(function(error)\n                            {\n                                node.warn('error 2');\n                                reject(error);\n                            });\n                    })\n                    .catch(function(error)\n                    {\n                        node.warn('error 1');\n                        reject(error);\n                    });\n            });\n    });\n}\n\nfunction accessories()\n{\n    //node.warn('accessories')\n    var self = this;\n    //var connection = new lightify.lightify(bridge_ip, self.log);\n    var connection = new lightify.lightify(bridge_ip);\n    discover(connection).then(function(data)\n    {\n        var foundAccessories = [];\n        data.result.forEach(function(light)\n        {\n            //node.warn(light);\n            msg.topic = light.name;\n            light.isBrightnessSupported = lightify.isBrightnessSupported(light.type);\n            light.isColorSupported = lightify.isColorSupported(light.type);\n            light.isTemperatureSupported = lightify.isTemperatureSupported(light.type);\n            msg.light = light;\n            node.send(msg);\n            if (!hideNodes && light.type && lightify.isLight(light.type))\n            {\n                //node.warn('Lightify Light [%s]', light.name);\n                foundAccessories.push(new LightifyAccessory(self, light));\n                //msg.light.name = light.name;\n                //msg.light.type = light.type;\n                //msg.light.status = light.status;\n                //node.send(msg);\n            }\n            else if (!hideNodes && light.type && lightify.isPlug(light.type))\n            {\n                //node.warn('Lightify Plug [%s]', light.name);\n                foundAccessories.push(new LightifyOutlet(self, light));\n            }\n            else if (!hideNodes && light.type && lightify.isSensor(light.type))\n            {\n                //node.warn('Lightify Sensor [%s]', light.name);\n                foundAccessories.push(new LightifySensor(self, light));\n            }\n            else if (!light.type)\n            {\n                foundAccessories.push(new LightifyAccessory(self, light));\n            }\n        });\n        //node.warn(foundAccessories);\n        connection.dispose();\n        //callback(self.foundAccessories);\n        //node.warn('Lightify accessories');\n        //self.refreshTimer();\n    }).catch(function(error)\n    {\n        node.warn('Discovered failed', error);\n        throw 'can not connect to lightify bridge.';\n    });\n}\n\nfunction LightifyAccessory(platform, device)\n{\n    //node.warn('LightifyAccessory');\n    /*\n    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Lightbulb(device.name || 'Unknown');\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n\n    var self = this;\n    if (device.isColorSupported || lightify.isColorSupported(device.type))\n    {\n        this.colorBulb(platform);\n    }\n    else if (device.isTemperatureSupported || lightify.isTemperatureSupported(device.type))\n    {\n        this.temperatureBulb(platform);\n    }\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type))\n    {\n        this.service.addOptionalCharacteristic(Characteristic.Brightness);\n        this.service.getCharacteristic(Characteristic.Brightness).value = self.device.brightness;\n        this.service.getCharacteristic(Characteristic.Brightness)\n            .on('get', function(callback)\n            {\n                callback(null, self.device.brightness);\n            })\n            .on('set', function(brightness, callback)\n            {\n                if (self.setBrightnessTimer)\n                {\n                    clearTimeout(self.setBrightnessTimer);\n                }\n                self.setBrightnessTimer = setTimeout(function()\n                {\n                    var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n                    connection.connect().then(function()\n                    {\n                        return connection.nodeBrightness(self.device.mac, brightness, 0, self.device.type ? false : true);\n                    }).then(function()\n                    {\n                        self.device.brightness = brightness;\n                        return connection.dispose();\n                    });\n                }, 80);\n                callback(null);\n            });\n    }\n\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback)\n        {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function()\n            {\n                return connection.nodeOnOff(self.device.mac, state ? true : false, self.device.type ? false : true);\n            }).then(function()\n            {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function()\n            {\n                callback(null);\n                return connection.dispose();\n            });\n        });\n        */\n}\nLightifyAccessory.prototype.setHSV = function(hsv)\n{\n    var rgb = HSVtoRGB(hsv.h, hsv.s, hsv.v);\n\n    this.device.red = rgb.r;\n    this.device.green = rgb.g;\n    this.device.blue = rgb.b;\n\n    var self = this;\n    if (this.setHSVTimer)\n    {\n        clearTimeout(this.setHSVTimer);\n    }\n    this.setHSVTimer = setTimeout(function()\n    {\n        var connection = new lightify.lightify(self.platform.config.bridge_ip, self.log);\n\n        connection.connect().then(function()\n        {\n            return connection.nodeColor(self.device.mac,\n                self.device.red, self.device.green, self.device.blue, self.device.alpha, 0, self.device.type ? false : true);\n        }).then(function()\n        {\n            return connection.dispose();\n        });\n    }, 100);\n\n}\nLightifyAccessory.prototype.colorBulb = function(platform)\n{\n    this.service.addOptionalCharacteristic(Characteristic.Hue);\n    this.service.addOptionalCharacteristic(Characteristic.Saturation);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n\n    var hsv = RGBtoHSV(this.device.red, this.device.green, this.device.blue);\n\n    this.service.getCharacteristic(Characteristic.Hue).value = hsv.h * 360;\n    this.service.getCharacteristic(Characteristic.Saturation).value = hsv.h * 100;\n    this.service.getCharacteristic(Characteristic.Brightness).value = hsv.v * 100;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.Hue)\n        .on('get', function(callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            callback(null, hsv.h * 360);\n        })\n        .on('set', function(h, callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            hsv.h = h / 360.0;\n            self.setHSV(hsv);\n            callback(null);\n        });\n\n    this.service.getCharacteristic(Characteristic.Saturation)\n        .on('get', function(callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            callback(null, hsv.s * 100);\n        })\n        .on('set', function(s, callback)\n        {\n            hsv = RGBtoHSV(self.device.red, self.device.green, self.device.blue);\n            hsv.s = s / 100.0;\n            self.setHSV(hsv);\n            callback(null);\n        });\n}\nLightifyAccessory.prototype.temperatureBulb = function(platform)\n{\n    this.service.addOptionalCharacteristic(Characteristic.ColorTemperature);\n    this.service.addOptionalCharacteristic(Characteristic.Brightness);\n    var mired = 1000000 / this.device.temperature;\n\n    this.log.debug('temperatureBulb', mired);\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.ColorTemperature)\n        .on('get', function(callback)\n        {\n            self.log.error('get temperature:', self.device.temperature, 'mired:', mired);\n            callback(null, mired);\n        })\n        .on('set', function(mired, callback)\n        {\n            var temperature = 1000000 / mired;\n            self.log.error('sent temperature to set: ', temperature, 'mired:', mired);\n\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function()\n            {\n                return connection.nodeTemperature(self.device.mac, temperature, 0, self.device.type ? false : true).then(function(data)\n                {\n                    self.log.error('set temperature (via mired): ', temperature);\n                    self.device.temperature = temperature;\n                    callback(null, mired);\n                    return connection.dispose();\n                });\n            });\n        });\n}\nLightifyAccessory.prototype.updateDevice = function(device)\n{\n    this.device = device;\n    var self = this;\n    / send updated status to HomeKit /\n    self.service.getCharacteristic(Characteristic.On).updateValue(device.status);\n    if (device.isBrightnessSupported || lightify.isBrightnessSupported(device.type))\n    {\n        self.service.getCharacteristic(Characteristic.Brightness).updateValue(self.device.brightness);\n    }\n}\nLightifyAccessory.prototype.getServices = function()\n{\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if (this.service)\n    {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifyOutlet(platform, device)\n{\n    //node.warn('LightifyOutlet');\n    /*\n    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    this.service = new Service.Outlet(device.name);\n\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.On).value = device.status;\n    this.service.getCharacteristic(Characteristic.OutletInUse).value = true;\n\n    var self = this;\n    this.service.getCharacteristic(Characteristic.OutletInUse)\n        .on('get', function(callback)\n        {\n            callback(null, true);\n        });\n    this.service.getCharacteristic(Characteristic.On)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.online == 2 && self.device.status);\n        })\n        .on('set', function(state, callback)\n        {\n            var connection = new lightify.lightify(platform.config.bridge_ip, self.log);\n            connection.connect().then(function()\n            {\n                return connection.nodeOnOff(self.device.mac, state ? true : false);\n            }).then(function()\n            {\n                self.device.status = state;\n                callback(null);\n                return connection.dispose();\n            }).catch(function()\n            {\n                callback(null);\n                return connection.dispose();\n            });\n        });\n        */\n}\nLightifyOutlet.prototype.updateDevice = function(device)\n{\n    this.device = device;\n}\nLightifyOutlet.prototype.getServices = function()\n{\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Outlet')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if (this.service)\n    {\n        services.push(this.service);\n    }\n    return services;\n}\n\nfunction LightifySensor(platform, device)\n{\n    //node.warn('LightifySensor');\n    /*\n    this.log = platform.log;\n    this.device = device;\n    this.name = device.name;\n    this.platform = platform;\n\n    var self = this;\n\n    // contact status\n    this.service = new Service.ContactSensor(device.name);\n    this.service.getCharacteristic(Characteristic.Name).value = device.name;\n    this.service.getCharacteristic(Characteristic.ContactSensorState).value = true;\n    this.service.getCharacteristic(Characteristic.ContactSensorState)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.online == 2 && self.device.green == 1)\n        });\n\n    // battery service\n    this.batteryService = new Service.BatteryService(device.name);\n    this.batteryService.getCharacteristic(Characteristic.Name).value = device.name;\n    this.batteryService.getCharacteristic(Characteristic.BatteryLevel)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.brightness)\n        });\n\n    this.batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n    this.batteryService.getCharacteristic(Characteristic.ChargingState)\n        .on('get', function(callback)\n        {\n            callback(null, false)\n        });\n\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n    this.batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n        .on('get', function(callback)\n        {\n            callback(null, false)\n        });\n    */\n}\nLightifySensor.prototype.updateDevice = function(device)\n{\n    this.device = device;\n    var self = this;\n    /* send updated status to HomeKit */\n    self.service.getCharacteristic(Characteristic.ContactSensorState).updateValue(self.device.green);\n}\nLightifySensor.prototype.getServices = function()\n{\n    var services = [];\n    var service = new Service.AccessoryInformation();\n    service.setCharacteristic(Characteristic.Name, this.name)\n        .setCharacteristic(Characteristic.Manufacturer, 'Osram')\n        .setCharacteristic(Characteristic.Model, 'Lightify Sensor')\n        .setCharacteristic(Characteristic.SerialNumber, this.device.friendlyMac)\n        .setCharacteristic(Characteristic.FirmwareRevision,\n            ((this.device.firmware_version >> 24) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 16) & 0xFF) + '.' +\n            ((this.device.firmware_version >> 8) & 0xFF) + '.' +\n            (this.device.firmware_version & 0xFF)\n        )\n        .setCharacteristic(Characteristic.HardwareRevision, '1.0.0');\n    services.push(service);\n    if (this.service)\n    {\n        services.push(this.service);\n    }\n\n    var self = this;\n\n    // battery service\n    var batteryService = new Service.BatteryService();\n    batteryService.getCharacteristic(Characteristic.Name).value = this.name;\n    batteryService.getCharacteristic(Characteristic.BatteryLevel)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.brightness)\n        });\n\n    batteryService.getCharacteristic(Characteristic.ChargingState).value = false;\n    batteryService.getCharacteristic(Characteristic.ChargingState)\n        .on('get', function(callback)\n        {\n            callback(null, false)\n        });\n\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery).value = false;\n    batteryService.getCharacteristic(Characteristic.StatusLowBattery)\n        .on('get', function(callback)\n        {\n            callback(null, self.device.brightness < 15 ? true : false)\n        });\n    services.push(batteryService);\n\n    if (this.batteryService)\n    {\n        services.push(this.batteryService);\n    }\n\n    return services;\n}","outputs":1,"noerr":0,"x":810,"y":380,"wires":[["33d86e38.a6e3c2"]]},{"id":"e7275b81.609ec","type":"catch","z":"8af0616b.5186d8","name":"","scope":null,"uncaught":false,"x":100,"y":60,"wires":[["75f3294.7f94c58"]]},{"id":"75f3294.7f94c58","type":"debug","z":"8af0616b.5186d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":230,"y":60,"wires":[]},{"id":"6b943092.ba8b08","type":"subflow:8bea8c79.ed4d2","z":"8af0616b.5186d8","name":"","env":[{"name":"Buffer_Size","type":"num","value":"20"}],"x":430,"y":340,"wires":[["df5f93e8.35b93","cab9fdb9.a9b29"],[]]},{"id":"ebc9dc19.62a2d8","type":"change","z":"8af0616b.5186d8","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"put","tot":"str"},{"t":"move","p":"light","pt":"msg","to":"payload.light","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":280,"wires":[["6b943092.ba8b08","a69a26e5.f71f2"]]},{"id":"2a71076.78d7578","type":"inject","z":"8af0616b.5186d8","name":"Unload FIFO (500ms)","topic":"get","payload":"","payloadType":"date","repeat":"0.5","crontab":"","once":true,"onceDelay":0.1,"x":180,"y":320,"wires":[["6b943092.ba8b08"]]},{"id":"141c500a.5e4c98","type":"change","z":"8af0616b.5186d8","name":"","rules":[{"t":"move","p":"payload.light","pt":"msg","to":"light","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":440,"wires":[["c5eb91cc.cc87b8"]]},{"id":"df5f93e8.35b93","type":"function","z":"8af0616b.5186d8","name":"Filter valid messages","func":"// when topic == put a new message is being put\n// into the buffer. likewise, when the payload is null\n// a trigger is being fired from the inject.\n\n// other nodes may be interacting with the gateway so\n// check if it is busy first. 'LightifyIsBusy' is just a \n// variable used for handshaking between the nodes.\nvar BusyTimerTimeMs = 20000;\n\nvar LightifyIsBusy = flow.get('LightifyIsBusy', 'memoryOnly') || 0;\n\nif (msg.topic != 'put' && msg.payload)\n{\n    if (!LightifyIsBusy)\n    {\n        SetBusyTimer(BusyTimerTimeMs);\n        return [null, msg]; // null to first output, msg to second\n    }\n    else\n    {\n        msg.topic = 'put';\n        return [msg, null]; // to first output, null to second\n    }\n}\n\nfunction SetBusyTimer(TimeTillExpire)\n{\n    // show lightify as busy\n    flow.set('LightifyIsBusy', 1, 'memoryOnly');\n\n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n\n    // set the LightifyIsBusyTimeout timer\n    LightifyIsBusyTimeoutTimer = setTimeout(function()\n    {\n        // do some stuff here if timeout\n        node.warn('Lightify Busy Timer Expired');\n        flow.set('LightifyIsBusy', 0, 'memoryOnly');\n    }, TimeTillExpire || 5000);\n\n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer', LightifyIsBusyTimeoutTimer, 'memoryOnly')\n}\n\nfunction ClearBusyTimer()\n{\n    // show lightify as not busy\n    flow.set('LightifyIsBusy', 0, 'memoryOnly');\n\n    // get the LightifyIsBusyTimeout timer if it exists\n    var LightifyIsBusyTimeoutTimer = flow.get('LightifyIsBusyTimeoutTimer', 'memoryOnly') || 0;\n\n    // clear the LightifyIsBusyTimeout timer if it exists\n    if (LightifyIsBusyTimeoutTimer !== 0) clearTimeout(LightifyIsBusyTimeoutTimer);\n\n    // store the LightifyIsBusyTimeout timer in context for later\n    flow.set('LightifyIsBusyTimeoutTimer', LightifyIsBusyTimeoutTimer, 'memoryOnly');\n}","outputs":2,"noerr":0,"x":460,"y":420,"wires":[["ed4eedde.e9c5f"],["141c500a.5e4c98"]]},{"id":"301cd745.3c7a8","type":"debug","z":"8af0616b.5186d8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":810,"y":220,"wires":[]},{"id":"fb292f75.edc9a","type":"switch","z":"8af0616b.5186d8","name":"Devices","property":"topic","propertyType":"msg","rules":[{"t":"cont","v":"Contact","vt":"str"},{"t":"cont","v":"Light","vt":"str"},{"t":"cont","v":"Switch","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":680,"y":120,"wires":[["3115d19c.4c8906"],["4a69604c.ee4ed8"],["65c6888.5b66078"]]},{"id":"3115d19c.4c8906","type":"debug","z":"8af0616b.5186d8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"light","targetType":"msg","x":820,"y":80,"wires":[]},{"id":"16507332.ef6e55","type":"catch","z":"8af0616b.5186d8","name":"","scope":["df5f93e8.35b93","fe8cb5c5.df54d","c5eb91cc.cc87b8"],"uncaught":false,"x":90,"y":100,"wires":[["16d508c8.0fa247"]]},{"id":"16d508c8.0fa247","type":"function","z":"8af0616b.5186d8","name":"Reset Variables","func":"flow.set('LightifyIsBusy',0, 'memoryOnly');\nreturn msg;","outputs":1,"noerr":0,"x":260,"y":100,"wires":[["26b5dcdd.d016d4"]]},{"id":"26b5dcdd.d016d4","type":"debug","z":"8af0616b.5186d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":410,"y":100,"wires":[]},{"id":"9c8bb5fc.78a288","type":"link in","z":"8af0616b.5186d8","name":"","links":["ed4eedde.e9c5f"],"x":175,"y":440,"wires":[["6b943092.ba8b08"]]},{"id":"ed4eedde.e9c5f","type":"link out","z":"8af0616b.5186d8","name":"","links":["9c8bb5fc.78a288"],"x":615,"y":400,"wires":[]},{"id":"4a69604c.ee4ed8","type":"debug","z":"8af0616b.5186d8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"light","targetType":"msg","x":820,"y":120,"wires":[]},{"id":"65c6888.5b66078","type":"debug","z":"8af0616b.5186d8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"light","targetType":"msg","x":820,"y":160,"wires":[]},{"id":"1868f8e8.a5edb7","type":"inject","z":"8af0616b.5186d8","name":"Single Shot","topic":"flush","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":150,"y":480,"wires":[["cfbe02c2.9549d","6b943092.ba8b08"]]},{"id":"cfbe02c2.9549d","type":"function","z":"8af0616b.5186d8","name":"Initialize Lightify","func":"var LightifyRetryCount = flow.set('LightifyRetryCount',0, 'memoryOnly');\nvar LightifyIsResponding = flow.set('LightifyIsResponding',1, 'memoryOnly');\nvar LightifyIsBusy = flow.set('LightifyIsBusy',0, 'memoryOnly');\nvar LightifyGettingGroups = flow.set('LightifyGettingGroups',false, 'memoryOnly');\n\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":540,"wires":[[]]},{"id":"42dcc5d2.810cb4","type":"inject","z":"8af0616b.5186d8","name":"Manual Unload FIFO","topic":"get","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":360,"wires":[["6b943092.ba8b08"]]},{"id":"f31f4fb3.e7e108","type":"inject","z":"8af0616b.5186d8","name":"Flush FIFO","topic":"flush","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":400,"wires":[["6b943092.ba8b08"]]},{"id":"a69a26e5.f71f2","type":"debug","z":"8af0616b.5186d8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":620,"y":280,"wires":[]},{"id":"cab9fdb9.a9b29","type":"debug","z":"8af0616b.5186d8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":610,"y":340,"wires":[]}]

That's fair, I have 40+ bulbs, 10 contact sensors, and 10+ zones - basically my whole house so I need it to be very robust least the wifey get upset when her reading lamp flakes out!
I started trying to work out the Android app but didn't get too far with that.
I really like the hardware and it's been a real workhorse for me over the years. I'm sure that I'm going to dump it for Habitat one day. However, I would love to go 100% open source. I started playing around with the CC31 zigbee module from Motorola a while back and had some great success - perhaps I'll go that route.
Let me know if I can help you out in any other way in the future.

That's funny you say that. I put these bulbs in the kitchen and my wife was like "what do I do if they don't work and you're out of town!!!!!! Lol... wives... ;) I'm not sure how, but let's connect up via email so we can take this off line. I'll let you know what I've done. My house is predominately open source, using Tasmota with Sonoff devices. I've also hacked some AiLight Bulbs but I'm totally off cloud, except for these bulbs. I also have a few Tuya smart sockets as well. This is my first encounter with zigbee. I have a door lock that's z-wave. I also made my own curtains and blinds smart hardware ;) I'm a big fan of ESP8266's! Did my heater/thermostat as well.

Oh man, love the ESPs but dang they hog up the wifi slots. Ouside of Lightify I use MySensors open source protocol running on battery powered wireless Arduino sensors.
My email is dalethomas@me.com.
Sent from my iPhone

On Mar 23, 2020, at 7:42 PM, nospam2k notifications@github.com wrote:

That's funny you say that. I put these bulbs in the kitchen and my wife was like "what do I do if they don't work and you're out of town!!!!!! Lol... wives... ;) I'm not sure how, but let's connect up via email so we can take this off line. I'll let you know what I've done. My house is predominately open source, using Tasmota with Sonoff devices. I've also hacked some AiLight Bulbs but I'm totally off cloud, except for these bulbs. I also have a few Tuya smart sockets as well. This is my first encounter with zigbee. I have a door lock that's z-wave. I also made my own curtains and blinds smart hardware ;) I'm a big fan of ESP8266's! Did my heater/thermostat as well.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

repo: rainlake/node-lightify