From 3fe1dfefb4146545683d2d15d3c049661a63f5bd Mon Sep 17 00:00:00 2001 From: Teodor Ivanov Date: Mon, 21 Oct 2019 23:26:13 +0300 Subject: [PATCH] Add RGB color as hub input (#15) --- api/hue/templates/lights/all.json | 2 +- api/hue/templates/lights/get-state.json | 6 +- index.html | 23 +++- index.js | 165 +++++++++++------------- package-lock.json | 18 +-- package.json | 2 +- 6 files changed, 101 insertions(+), 115 deletions(-) diff --git a/api/hue/templates/lights/all.json b/api/hue/templates/lights/all.json index 00f6f08..78c7719 100644 --- a/api/hue/templates/lights/all.json +++ b/api/hue/templates/lights/all.json @@ -31,7 +31,7 @@ "control": { "mindimlevel": 5000, "maxlumen": 600, - "colorgamuttype": "B", + "colorgamuttype": "A", "colorgamut": [ [ 0.675, diff --git a/api/hue/templates/lights/get-state.json b/api/hue/templates/lights/get-state.json index 1ef44d8..2bb9924 100644 --- a/api/hue/templates/lights/get-state.json +++ b/api/hue/templates/lights/get-state.json @@ -19,8 +19,8 @@ "state": "noupdates", "lastinstall": "{{ date }}" }, - "type": "Color Temperature Light", + "type": "Extended color light", "name": "{{ name }}", - "modelid": "LTW011", - "swversion": "1.29.0_r21169" + "modelid": "LCT007", + "swversion": "5.105.0.21169" } diff --git a/index.html b/index.html index 541d3a4..1aa0ea7 100644 --- a/index.html +++ b/index.html @@ -79,6 +79,15 @@

Inputs

payload.ct string
The mired color temperature of the light (min 153, max 500)
+ +
payload.xy array
+
The x and y coordinates of a color in CIE color space (Both x and y are between 0 and 1)
+ +
payload.rgb array
+
The light color in RGB format
+ +
payload.colormode string
+
Indicates the color mode (ct - Color Temperature | hs - Hue and Saturation)

Outputs

@@ -101,12 +110,15 @@

Outputs

ct string
The mired color temperature of the light (min 153, max 500)
-
colormode string
-
Indicates the color mode (ct - Color Temperature | hs - Hue and Saturation)
+
xy array
+
The x and y coordinates of a color in CIE color space (Both x and y are between 0 and 1)
rgb array
The light color in RGB format
+
colormode string
+
Indicates the color mode (ct - Color Temperature | hs - Hue and Saturation)
+
percentage number
The brightness % level (min 1, max 100)
@@ -187,12 +199,15 @@

Outputs

ct string
The mired color temperature of the light (min 153, max 500)
-
colormode string
-
Indicates the color mode (ct - Color Temperature | hs - Hue and Saturation)
+
xy array
+
The x and y coordinates of a color in CIE color space (Both x and y are between 0 and 1)
rgb array
The light color in RGB format
+
colormode string
+
Indicates the color mode (ct - Color Temperature | hs - Hue and Saturation)
+
percentage number
The brightness % level (min 1, max 100)
diff --git a/index.js b/index.js index 0eba1eb..5904581 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,8 @@ module.exports = function(RED) { 'use strict'; + const HueColor = require('hue-colors').default; + function AmazonEchoDeviceNode(config) { RED.nodes.createNode(this, config); var deviceNode = this; @@ -98,32 +100,20 @@ module.exports = function(RED) { msg.payload.deviceid = formatUUID(nodeDeviceId); - // Send payload if state is changed - var stateChanged = false; - var deviceAttributes = getDeviceAttributes(msg.payload.deviceid, hubNode.context()); - - for (var key in msg.payload) { - if (key in deviceAttributes && msg.payload[key] !== deviceAttributes[key]) { - stateChanged = true; + var meta = { + insert: { + by: 'input', + details: {} } } - if (stateChanged) { - - var meta = { - insert: { - by: 'input', - details: {} - } - } - - setDeviceAttributes(msg.payload.deviceid, msg.payload, meta, hubNode.context()); + var deviceAttributes = setDeviceAttributes(msg.payload.deviceid, msg.payload, meta, hubNode.context()); - // Output only if 'Process and output' option is selected - if (config.processinput == 2) { - payloadHandler(hubNode, msg.payload.deviceid); - } + // Output only if 'Process and output' option is selected and state is changed + if (config.processinput == 2 && Object.keys(deviceAttributes.meta.changes).length > 0) { + payloadHandler(hubNode, msg.payload.deviceid); } + } }); @@ -259,8 +249,8 @@ module.exports = function(RED) { by: 'alexa', details: { ip: req.headers['x-forwarded-for'] || - req.connection.remoteAddress || - '', + req.connection.remoteAddress || + '', user_agent: req.headers['user-agent'] } } @@ -362,9 +352,12 @@ module.exports = function(RED) { var defaultAttributes = { on: false, bri: 254, + percentage: 100, hue: 0, sat: 254, + xy: [0.6484272236872118, 0.33085610147277794], ct: 199, + rgb: [254, 0, 0], colormode: 'ct', meta: {} }; @@ -387,42 +380,77 @@ module.exports = function(RED) { function setDeviceAttributes(id, attributes, meta, context) { - var currentAttributes = getDeviceAttributes(id, context); - // Reset meta attribute meta['insert']['details']['date'] = new Date(); meta['input'] = attributes; meta['changes'] = {}; - if (attributes.xy !== undefined && attributes.xy !== null) { - var xy = attributes.xy; - var hsb = colorXYY2SHB(xy[0], xy[1], 100); - attributes.hue = hsb[0]; - attributes.sat = hsb[1]; + var saved = getDeviceAttributes(id, context); + var current = {}; + + // Set defaults + for (var key in saved) { + current[key] = valueOrDefault(attributes[key], saved[key]); } - // Set correct color mode + // Set color temperature if (attributes.ct !== undefined) { - attributes.colormode = 'ct'; - } else if (attributes.hue !== undefined || attributes.sat !== undefined) { - attributes.colormode = 'hs'; + current.colormode = 'ct'; } - for (var key in currentAttributes) { - // Find changes - if (attributes[key] !== currentAttributes[key] && attributes[key] !== undefined) { - meta['changes'][key] = currentAttributes[key]; + // Set Hue color + if (attributes.hue !== undefined && attributes.sat !== undefined) { + var hueColor = HueColor.fromHsb(current.hue, current.sat, current.bri); + var cie = hueColor.toCie(); + var rgb = hueColor.toRgb(); + current.xy = [cie[0] || 0, cie[1] || 0]; + current.rgb = rgb; + current.colormode = 'hs'; + } + + // Set CIE + if (attributes.xy !== undefined && Array.isArray(attributes.xy) && attributes.xy.length == 2) { + var hueColor = HueColor.fromCIE(current.xy[0], current.xy[1], current.bri); + var hsb = hueColor.toHsb(); + var rgb = hueColor.toRgb(); + current.hue = hsb[0] || 0; + current.sat = hsb[1] || 0; + current.rgb = rgb; + current.colormode = 'hs'; + } + + // Set RGB + if (attributes.rgb !== undefined && Array.isArray(attributes.rgb) && attributes.rgb.length == 3) { + var hueColor = HueColor.fromRgb(current.rgb[0], current.rgb[1], current.rgb[2]); + var hsb = hueColor.toHsb(); + var cie = hueColor.toCie(); + current.hue = hsb[0] || 0; + current.sat = hsb[1] || 0; + current.bri = hsb[2] || 0; + current.xy = [cie[0] || 0, cie[1] || 0] + current.colormode = 'hs'; + } + + // Set brightness percentage + current.percentage = Math.floor(current.bri / 253 * 100); + + // Populate meta.changes + for (var key in saved) { + if (JSON.stringify(saved[key]) !== JSON.stringify(current[key])) { + meta['changes'][key] = saved[key]; } - currentAttributes[key] = valueOrDefault(attributes[key], currentAttributes[key]); } // Include meta - currentAttributes['meta'] = meta; + current['meta'] = meta; // Save attributes - context.set(id, currentAttributes); + context.set(id, current); + + // Set payload + current.payload = current.on ? 'on' : 'off'; - return getOrDefault(id, currentAttributes, context); + return getOrDefault(id, current, context); } // @@ -431,61 +459,12 @@ module.exports = function(RED) { function payloadHandler(hubNode, deviceId) { var msg = getDeviceAttributes(deviceId, hubNode.context()); - msg.rgb = colorSHB2RGB(msg.hue, msg.sat, 254); - msg.percentage = Math.floor(msg.bri / 253 * 100); - msg.payload = msg.on ? 'on' : 'off'; msg.deviceid = deviceId; msg.topic = ''; - hubNode.send(msg); - } - - // - // Colors conversion - // - var colorConvert = require('color-convert'); - - function colorXYY2XYZ(xs, ys, yc) { - var xc = xs * yc / ys; - var zc = (1 - xs - ys) * yc / ys; - - return [xc, yc, zc]; - } - - function colorXYZ2SHV(x, y, z) { - var hsv = colorConvert.xyz.hsv(x, y, z); - - return hsv; - } - - function colorSHV2HSB(h, s, v) { - var hh = h / 360 * 65535; - var ss = s / 100 * 254; - var bb = v / 100 * 254; + console.log(msg); - return [hh, ss, bb] - } - - function colorSHB2HSV(h, s, b) { - var hh = h * 360 / 65535; - var ss = s * 100 / 254; - var vv = b * 100 / 254; - - return [hh, ss, vv] - } - - function colorXYY2SHB(xs, ys, yc) { - var xyz = colorXYY2XYZ(xs, ys, yc); - var hsv = colorXYZ2SHV(xyz[0], xyz[1], xyz[2]); - var hsb = colorSHV2HSB(hsv[0], hsv[1], hsv[2]); - - return hsb; + hubNode.send(msg); } - function colorSHB2RGB(h, s, b) { - var hsv = colorSHB2HSV(h, s, b); - var rgb = colorConvert.hsv.rgb(hsv[0], hsv[1], hsv[2]); - - return rgb; - } } diff --git a/package-lock.json b/package-lock.json index 306be3b..913c6ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,19 +53,6 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, - "color-convert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.0.tgz", - "integrity": "sha512-hzTicsCJIHdxih9+2aLR1tNGZX5qSJGRHDPVwSY26tVrEf55XNajLOBWz2UuWSIergszA09/bqnOiHyqx9fxQg==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -215,6 +202,11 @@ "statuses": ">= 1.4.0 < 2" } }, + "hue-colors": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hue-colors/-/hue-colors-0.5.2.tgz", + "integrity": "sha512-3wDLYgXnjAtGzcWP+VTlnxVbh7Vc4RC56ubOS9X0Skv55sjhUtrG6fF7WKDezXPAdmprR5MbQK0fPSjezMA9iQ==" + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", diff --git a/package.json b/package.json index a7c6822..6a1d671 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,6 @@ "mustache": "^3.0.1", "express": "^4.16.4", "body-parser": "^1.18.3", - "color-convert": "^2.0.0" + "hue-colors": "^0.5.2" } }