mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
Big WeMo node update (#295)
* Reduce resubscription time Halve the resubscrciption timeout to make sure event subscriptions get renewed * Big Update Includes: - New lookup node to check state of a device - Fix dimming control for lights - Fix light group control - Set the node label to match the device name - The event now includes the text description of the light capability * Fix groups properly * Fix travis error with comparitor * Bump node-ssdp version
This commit is contained in:
parent
a06ad8f1a7
commit
3f4261f3b7
@ -24,7 +24,7 @@ The node accecpts the following inputs
|
||||
* Strings on/off
|
||||
* integers 1/0
|
||||
* boolean true/false
|
||||
* an Object like this (lights only, coming soon)
|
||||
* an Object like this (lights only & color control is still work in the progress)
|
||||
```
|
||||
{
|
||||
state: 1,
|
||||
|
@ -29,8 +29,9 @@
|
||||
<li>Light Groups</li>
|
||||
<li>Motion Detector</li>
|
||||
</ul>
|
||||
<p>Sockets will generate msg.payload with values of 0/1 for off or on, all other
|
||||
types will return an object like this:</p>
|
||||
<p>Sockets will generate msg.payload with values of 0/1/8 for off or on
|
||||
(8 is on but at standby load for insight sockets), lightswill return an
|
||||
object like this:</p>
|
||||
<pre>
|
||||
{
|
||||
name: 'Bedroom light',
|
||||
@ -44,6 +45,8 @@
|
||||
<ul>
|
||||
<li>10006 - on/off</li>
|
||||
<li>10008 - brightness</li>
|
||||
<li>10300 - color</li>
|
||||
<li>30301 - color temperature</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
@ -53,7 +56,8 @@
|
||||
defaults: { // defines the editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
topic: {value:"wemo", required: true},
|
||||
device: {value:"", type: "wemo-dev"}
|
||||
device: {value:"", type: "wemo-dev"},
|
||||
label: {value:""}
|
||||
},
|
||||
color: "LawnGreen",
|
||||
inputs:0, // set the number of inputs - only 0 or 1
|
||||
@ -61,10 +65,17 @@
|
||||
// set the icon (held in icons dir below where you save the node)
|
||||
icon: "belkin.png", // saved in icons/myicon.png
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||"wemo";
|
||||
if (this.name){
|
||||
return this.name;
|
||||
} else {
|
||||
return this.label||"wemo";
|
||||
}
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditsave: function(){
|
||||
this.label = $('#node-input-device option:selected').text();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -106,6 +117,7 @@
|
||||
temperature: 25000
|
||||
}
|
||||
</pre>
|
||||
<p>color control is still a work in progress, but the rest should work</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -113,17 +125,80 @@
|
||||
category: 'output', // the palette category
|
||||
defaults: { // defines the editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
device: {type: "wemo-dev", required: true}
|
||||
device: {type: "wemo-dev", required: true},
|
||||
label: {value: ""}
|
||||
},
|
||||
color: "LawnGreen",
|
||||
inputs: 1, // set the number of inputs - only 0 or 1
|
||||
// set the icon (held in icons dir below where you save the node)
|
||||
icon: "belkin.png", // saved in icons/myicon.png
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||"wemo";
|
||||
if (this.name){
|
||||
return this.name;
|
||||
} else {
|
||||
return this.label||"wemo";
|
||||
}
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditsave: function(){
|
||||
this.label = $('#node-input-device option:selected').text();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="wemo lookup">
|
||||
<div class="form-row">
|
||||
<label for="node-input-device"><i class="fa fa-tasks"></i> Device</label>
|
||||
<input type="text" id="node-input-device" placeholder="Device">
|
||||
</div>
|
||||
<br/>
|
||||
<!-- By convention, most nodes have a 'name' property. The following div -->
|
||||
<!-- provides the necessary field. Should always be the last option -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="wemo lookup">
|
||||
<p>This node queries the current state of a device</p>
|
||||
<p>For lights it return a msg.payload that looks like this:</p>
|
||||
<pre>{
|
||||
available: true,
|
||||
state: 0,
|
||||
dim: 13
|
||||
}</pre>
|
||||
<p>Where <em>available</em> is if the blub is actually turned on
|
||||
at the wall switch<p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('wemo lookup',{
|
||||
category: 'function', // the palette category
|
||||
defaults: { // defines the editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
device: {type: "wemo-dev", required: true},
|
||||
label: {value:""}
|
||||
},
|
||||
color: "LawnGreen",
|
||||
inputs: 1, // set the number of inputs - only 0 or 1
|
||||
outputs: 1,
|
||||
// set the icon (held in icons dir below where you save the node)
|
||||
icon: "belkin.png", // saved in icons/myicon.png
|
||||
label: function() { // sets the default label contents
|
||||
if (this.name){
|
||||
return this.name;
|
||||
} else {
|
||||
return this.label||"wemo";
|
||||
}
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditsave: function(){
|
||||
this.label = $('#node-input-device option:selected').text();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -45,7 +45,7 @@ module.exports = function(RED) {
|
||||
console.log('problem with resubscription %s - %s', res.statusCode, res.statusMessage);
|
||||
console.log('opts - %s', util.inspect(reSubOptions));
|
||||
console.log('dev - %s', util.inspect(dev));
|
||||
delete subscriptions[dev];
|
||||
delete subscriptions[subs[s]];
|
||||
delete sub2dev[sub.sid];
|
||||
subscribe({dev: subs[s]});
|
||||
}
|
||||
@ -58,7 +58,7 @@ module.exports = function(RED) {
|
||||
resub_request.on('error', function() {
|
||||
//console.log("failed to resubscribe to %s", dev.name );
|
||||
//need to find a way to resubsribe
|
||||
delete subscriptions[dev];
|
||||
delete subscriptions[subs[s]];
|
||||
delete sub2dev[sub.sid];
|
||||
subscribe({dev: subs[s]});
|
||||
});
|
||||
@ -231,6 +231,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
var on = 0;
|
||||
var capability = '10006';
|
||||
if (typeof msg.payload === 'string') {
|
||||
if (msg.payload == 'on' || msg.payload == '1' || msg.payload == 'true') {
|
||||
on = 1;
|
||||
@ -238,44 +239,53 @@ module.exports = function(RED) {
|
||||
else if (msg.payload === 'toggle') {
|
||||
on = 2;
|
||||
}
|
||||
}
|
||||
else if (typeof msg.payload === 'number') {
|
||||
} else if (typeof msg.payload === 'number') {
|
||||
if (msg.payload >= 0 && msg.payload < 3) {
|
||||
on = msg.payload;
|
||||
}
|
||||
}
|
||||
else if (typeof msg.payload === 'object') {
|
||||
} else if (typeof msg.payload === 'object') {
|
||||
//object need to get complicated here
|
||||
if (msg.payload.state && typeof msg.payload.state === 'number') {
|
||||
if (msg.payload.hasOwnProperty('state') && typeof msg.payload.state === 'number') {
|
||||
if (dev.type === 'socket') {
|
||||
if (msg.payload >= 0 && msg.payload < 2) {
|
||||
if (msg.payload.state >= 0 && msg.payload.state < 2) {
|
||||
on = msg.payload.state;
|
||||
}
|
||||
}
|
||||
else if (dev.type === 'light' || dev.type === 'group') {
|
||||
if (msg.payload >= 0 && msg.payload < 3) {
|
||||
on = msg.payload.state;
|
||||
// if (msg.payload.state >= 0 && msg.payload.state < 3) {
|
||||
// on = msg.payload.state;
|
||||
// }
|
||||
var keys = Object.keys(msg.payload);
|
||||
var caps = [];
|
||||
var states = [];
|
||||
for (var i=0; i<keys.length; i++) {
|
||||
if (msg.payload.hasOwnProperty(keys[i])) {
|
||||
if (wemo.reverseCapabilityMap.hasOwnProperty(keys[i])) {
|
||||
caps.push(wemo.reverseCapabilityMap[keys[i]]);
|
||||
states.push(msg.payload[keys[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (caps.length > 0) {
|
||||
capability = caps.join(',');
|
||||
on = states.join(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeof msg.payload === 'boolean') {
|
||||
} else if (typeof msg.payload === 'boolean') {
|
||||
if (msg.payload) {
|
||||
on = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev.type === 'socket') {
|
||||
if (dev.type == 'socket') {
|
||||
//console.log("socket");
|
||||
wemo.toggleSocket(dev, on);
|
||||
}
|
||||
else if (dev.type === 'light`') {
|
||||
//console.log("light");
|
||||
wemo.setStatus(dev,'10006', on);
|
||||
}
|
||||
else {
|
||||
console.log('group');
|
||||
wemo.setStatus(dev, '10006', on);
|
||||
} else if (dev.type === 'light') {
|
||||
wemo.setStatus(dev,capability, on);
|
||||
} else {
|
||||
//console.log('group');
|
||||
wemo.setStatus(dev, capability, on);
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -366,6 +376,76 @@ module.exports = function(RED) {
|
||||
};
|
||||
RED.nodes.registerType('wemo in', wemoNGEvent);
|
||||
|
||||
var wemoNGLookup = function(n){
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
node.device = n.device;
|
||||
node.name = n.name;
|
||||
node.dev = RED.nodes.getNode(node.device).device;
|
||||
node.status({fill: 'red',shape: 'dot',text: 'searching'});
|
||||
|
||||
if (!wemo.get(node.dev)) {
|
||||
wemo.on('discovered', function(d) {
|
||||
if (node.dev === d) {
|
||||
node.status({fill: 'green',shape: 'dot',text: 'found'});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.status({fill: 'green',shape: 'dot',text: 'found'});
|
||||
}
|
||||
|
||||
node.on('input', function(msg) {
|
||||
var dev = wemo.get(node.dev);
|
||||
|
||||
if (!dev) {
|
||||
//need to show that dev not currently found
|
||||
console.log('no device found');
|
||||
return;
|
||||
}
|
||||
|
||||
//console.log(dev.type);
|
||||
if (dev.type === 'light' || dev.type === 'group') {
|
||||
//console.log("light");
|
||||
wemo.getLightStatus(dev)
|
||||
.then(function(status){
|
||||
// if (status.available) {
|
||||
var caps = status.capabilities.split(',');
|
||||
var vals = status.state.split(',');
|
||||
for (var i=0; i<caps.length; i++) {
|
||||
if (wemo.capabilityMap.hasOwnProperty(caps[i])) {
|
||||
if (vals[i] !== '' && vals[i].indexOf(':') == -1) {
|
||||
status[wemo.capabilityMap[caps[i]]] = parseInt(vals[i]);
|
||||
} else {
|
||||
status[wemo.capabilityMap[caps[i]]] = parseInt(vals[i].substring(0,vals[i].indexOf(':')));
|
||||
}
|
||||
}
|
||||
}
|
||||
delete status.capabilities;
|
||||
// }
|
||||
msg.payload = status;
|
||||
node.send(msg);
|
||||
});
|
||||
} else {
|
||||
console.log("socket");
|
||||
//socket
|
||||
wemo.getSocketStatus(dev)
|
||||
.then(function(status){
|
||||
msg.payload = {
|
||||
state: status
|
||||
};
|
||||
node.send(msg);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
node.on('close', function(done) {
|
||||
done();
|
||||
});
|
||||
|
||||
};
|
||||
RED.nodes.registerType("wemo lookup", wemoNGLookup);
|
||||
|
||||
RED.httpAdmin.get('/wemoNG/devices', function(req, res) {
|
||||
res.json(wemo.devices);
|
||||
});
|
||||
|
@ -11,17 +11,16 @@ var url = require('url');
|
||||
var Q = require('q');
|
||||
|
||||
var urn = 'urn:Belkin:service:basicevent:1';
|
||||
|
||||
var postbodyheader = [
|
||||
'<?xml version="1.0" encoding="utf-8"?>',
|
||||
'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">',
|
||||
'<s:Body>'].join('\n');
|
||||
|
||||
|
||||
var postbodyfooter = ['</s:Body>',
|
||||
'</s:Envelope>'
|
||||
].join('\n');
|
||||
|
||||
|
||||
var getenddevs = {};
|
||||
getenddevs.path = '/upnp/control/bridge1';
|
||||
getenddevs.action = '"urn:Belkin:service:bridge:1#GetEndDevices"';
|
||||
@ -45,6 +44,58 @@ getcapabilities.body = [
|
||||
postbodyfooter
|
||||
].join('\n');
|
||||
|
||||
var getDevStatus = {
|
||||
method: 'POST',
|
||||
path: '/upnp/control/bridge1',
|
||||
action: '"urn:Belkin:service:bridge:1#GetDeviceStatus"',
|
||||
body: [
|
||||
postbodyheader,
|
||||
'<u:GetDeviceStatus xmlns:u="urn:Belkin:service:bridge:1">',
|
||||
'<DeviceIDs>%s</DeviceIDs>',
|
||||
'</u:GetDeviceStatus>',
|
||||
postbodyfooter
|
||||
].join('\n')
|
||||
};
|
||||
|
||||
var getSocketState = {
|
||||
method: 'POST',
|
||||
path: '/upnp/control/basicevent1',
|
||||
action: '"urn:Belkin:service:basicevent:1#GetBinaryState"',
|
||||
body: [
|
||||
postbodyheader,
|
||||
'<u:GetBinaryState xmlns:u="urn:Belkin:service:basicevent:1">',
|
||||
'</u:GetBinaryState>',
|
||||
postbodyfooter
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
|
||||
var setdevstatus = {};
|
||||
setdevstatus.path = '/upnp/control/bridge1';
|
||||
setdevstatus.action = '"urn:Belkin:service:bridge:1#SetDeviceStatus"';
|
||||
setdevstatus.body = [
|
||||
postbodyheader,
|
||||
'<u:SetDeviceStatus xmlns:u="urn:Belkin:service:bridge:1">',
|
||||
'<DeviceStatusList>',
|
||||
'<?xml version="1.0" encoding="UTF-8"?><DeviceStatus><IsGroupAction>%s</IsGroupAction><DeviceID available="YES">%s</DeviceID><CapabilityID>%s</CapabilityID><CapabilityValue>%s</CapabilityValue></DeviceStatus>',
|
||||
'</DeviceStatusList>',
|
||||
'</u:SetDeviceStatus>',
|
||||
postbodyfooter
|
||||
].join('\n');
|
||||
|
||||
var capabilityMap = {
|
||||
'10006': 'state',
|
||||
'10008': 'dim',
|
||||
'10300': 'color',
|
||||
'30301': 'temperature'
|
||||
};
|
||||
|
||||
var reverseCapabilityMap = {
|
||||
'state': '10006',
|
||||
'dim': '10008',
|
||||
'color': '10300',
|
||||
'temperature': '30301'
|
||||
};
|
||||
|
||||
var WeMoNG = function () {
|
||||
this.devices = {};
|
||||
@ -52,6 +103,10 @@ var WeMoNG = function () {
|
||||
this._interval;
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
this.capabilityMap = capabilityMap;
|
||||
|
||||
this.reverseCapabilityMap = reverseCapabilityMap;
|
||||
|
||||
}
|
||||
|
||||
util.inherits(WeMoNG, events.EventEmitter);
|
||||
@ -68,7 +123,7 @@ WeMoNG.prototype.start = function start() {
|
||||
request.get(location.href, function(err, res, xml) {
|
||||
if (!err) {
|
||||
xml2js.parseString(xml, function(err, json) {
|
||||
if (!err) {
|
||||
if (!err && json) {
|
||||
var device = { ip: location.hostname, port: location.port };
|
||||
for (var key in json.root.device[0]) {
|
||||
device[key] = json.root.device[0][key][0];
|
||||
@ -248,20 +303,114 @@ WeMoNG.prototype.toggleSocket = function toggleSocket(socket, on) {
|
||||
post_request.end();
|
||||
}
|
||||
|
||||
WeMoNG.prototype.setStatus = function setStatus(light, capability, value) {
|
||||
var setdevstatus = {};
|
||||
setdevstatus.path = '/upnp/control/bridge1';
|
||||
setdevstatus.action = '"urn:Belkin:service:bridge:1#SetDeviceStatus"';
|
||||
setdevstatus.body = [
|
||||
postbodyheader,
|
||||
'<u:SetDeviceStatus xmlns:u="urn:Belkin:service:bridge:1">',
|
||||
'<DeviceStatusList>',
|
||||
'<?xml version="1.0" encoding="UTF-8"?><DeviceStatus><IsGroupAction>NO</IsGroupAction><DeviceID available="YES">%s</DeviceID><CapabilityID>%s</CapabilityID><CapabilityValue>%s</CapabilityValue></DeviceStatus>',
|
||||
'</DeviceStatusList>',
|
||||
'</u:SetDeviceStatus>',
|
||||
postbodyfooter
|
||||
].join('\n');
|
||||
WeMoNG.prototype.getSocketStatus = function getSocketStatus(socket) {
|
||||
var postoptions = {
|
||||
host: socket.ip,
|
||||
port: socket.port,
|
||||
path: getSocketState.path,
|
||||
method: getSocketState.method,
|
||||
headers: {
|
||||
'SOAPACTION': getSocketState.action,
|
||||
'Content-Type': 'text/xml; charset="utf-8"',
|
||||
'Accept': ''
|
||||
}
|
||||
}
|
||||
|
||||
var def = Q.defer();
|
||||
|
||||
var post_request = http.request(postoptions, function(res){
|
||||
var data = "";
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk){
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function(){
|
||||
xml2js.parseString(data, function(err, result){
|
||||
if (!err) {
|
||||
var status = result["s:Envelope"]["s:Body"][0]["u:GetBinaryStateResponse"][0]["BinaryState"][0];
|
||||
status = parseInt(status);
|
||||
def.resolve(status);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
post_request.on('error', function (e) {
|
||||
console.log(e);
|
||||
console.log("%j", postoptions);
|
||||
def.reject();
|
||||
});
|
||||
|
||||
post_request.write(getSocketState.body);
|
||||
post_request.end();
|
||||
|
||||
return def.promise;
|
||||
};
|
||||
|
||||
WeMoNG.prototype.getLightStatus = function getLightStatus(light) {
|
||||
var postoptions = {
|
||||
host: light.ip,
|
||||
port: light.port,
|
||||
path: getDevStatus.path,
|
||||
method: getDevStatus.method,
|
||||
headers: {
|
||||
'SOAPACTION': getDevStatus.action,
|
||||
'Content-Type': 'text/xml; charset="utf-8"',
|
||||
'Accept': ''
|
||||
}
|
||||
};
|
||||
|
||||
var def = Q.defer();
|
||||
|
||||
var post_request = http.request(postoptions, function(res){
|
||||
var data = "";
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
xml2js.parseString(data, function(err, result){
|
||||
if(!err) {
|
||||
if (result["s:Envelope"]) {
|
||||
var status = result["s:Envelope"]["s:Body"][0]["u:GetDeviceStatusResponse"][0].DeviceStatusList[0];
|
||||
xml2js.parseString(status, function(err,result2){
|
||||
if (!err) {
|
||||
var available = result2['DeviceStatusList']['DeviceStatus'][0]['DeviceID'][0]['$'].available === 'YES';
|
||||
var state = result2['DeviceStatusList']['DeviceStatus'][0]['CapabilityValue'][0];
|
||||
var capabilities = result2['DeviceStatusList']['DeviceStatus'][0]['CapabilityID'][0];
|
||||
var obj = {
|
||||
available: available,
|
||||
state: state,
|
||||
capabilities: capabilities
|
||||
};
|
||||
def.resolve(obj);
|
||||
} else {
|
||||
console.log("err");
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log("err");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
post_request.on('error', function (e) {
|
||||
console.log(e);
|
||||
console.log("%j", postoptions);
|
||||
def.reject();
|
||||
});
|
||||
|
||||
post_request.write(util.format(getDevStatus.body, light.id));
|
||||
post_request.end();
|
||||
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
WeMoNG.prototype.setStatus = function setStatus(light, capability, value) {
|
||||
var postoptions = {
|
||||
host: light.ip,
|
||||
port: light.port,
|
||||
@ -269,7 +418,7 @@ WeMoNG.prototype.setStatus = function setStatus(light, capability, value) {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'SOAPACTION': setdevstatus.action,
|
||||
'Content-Type': 'text/xml; charset="utf-8"',
|
||||
'Content-Type': 'text/xml; charset="utf-8"',
|
||||
'Accept': ''
|
||||
}
|
||||
};
|
||||
@ -293,7 +442,7 @@ WeMoNG.prototype.setStatus = function setStatus(light, capability, value) {
|
||||
|
||||
//console.log(util.format(setdevstatus.body, light.id, capability, value));
|
||||
|
||||
post_request.write(util.format(setdevstatus.body, light.id, capability, value));
|
||||
post_request.write(util.format(setdevstatus.body, light.type === 'light'?'NO':'YES',light.id, capability, value));
|
||||
post_request.end();
|
||||
}
|
||||
|
||||
@ -312,6 +461,7 @@ WeMoNG.prototype.parseEvent = function parseEvent(evt) {
|
||||
if (!err && res != null) {
|
||||
msg.id = res['StateEvent']['DeviceID'][0]['_'];
|
||||
msg.capability = res['StateEvent']['CapabilityId'][0];
|
||||
msg.capabilityName = capabilityMap[msg.capability];
|
||||
msg.value = res['StateEvent']['Value'][0];
|
||||
def.resolve(msg);
|
||||
}
|
||||
@ -364,4 +514,27 @@ WeMoNG.prototype.rgb2xy = function rgb2xy(red, green, blue) {
|
||||
];
|
||||
};
|
||||
|
||||
//http://stackoverflow.com/questions/22894498/philips-hue-convert-xy-from-api-to-hex-or-rgb
|
||||
WeMoNG.prototype.xy2rgb = function xy2rgb(x,y,bri) {
|
||||
z = 1.0 - x - y;
|
||||
Y = bri / 255.0; // Brightness of lamp
|
||||
X = (Y / y) * x;
|
||||
Z = (Y / y) * z;
|
||||
r = X * 1.612 - Y * 0.203 - Z * 0.302;
|
||||
g = -X * 0.509 + Y * 1.412 + Z * 0.066;
|
||||
b = X * 0.026 - Y * 0.072 + Z * 0.962;
|
||||
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
|
||||
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
|
||||
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
|
||||
maxValue = Math.max(r,g,b);
|
||||
r /= maxValue;
|
||||
g /= maxValue;
|
||||
b /= maxValue;
|
||||
r = r * 255; if (r < 0) { r = 255 };
|
||||
g = g * 255; if (g < 0) { g = 255 };
|
||||
b = b * 255; if (b < 0) { b = 255 };
|
||||
|
||||
return [r,g,b];
|
||||
};
|
||||
|
||||
module.exports = WeMoNG;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red-node-wemo",
|
||||
"version": "0.1.10",
|
||||
"version": "0.1.11",
|
||||
"description": "Input and Output nodes for Belkin WeMo devices",
|
||||
"repository": "https://github.com/node-red/node-red-nodes/tree/master/hardware",
|
||||
"main": "WeMoNG.js",
|
||||
@ -9,7 +9,8 @@
|
||||
},
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"wemo"
|
||||
"wemo",
|
||||
"belkin"
|
||||
],
|
||||
"author": {
|
||||
"email": "hardillb@gmail.com",
|
||||
@ -18,7 +19,7 @@
|
||||
},
|
||||
"license": "APACHE-2.0",
|
||||
"dependencies": {
|
||||
"node-ssdp": "~2.6.3",
|
||||
"node-ssdp": "~2.9.1",
|
||||
"request": "~2.74.0",
|
||||
"xml2js": "~0.4.13",
|
||||
"util": "~0.10.3",
|
||||
|
Loading…
x
Reference in New Issue
Block a user