From cc28584641f5b237dbd00c9dbdfac35ac9505b4e Mon Sep 17 00:00:00 2001 From: Paddy O'Reilly
Date: Tue, 24 Mar 2020 13:59:35 +0000 Subject: [PATCH] Added multiZoneSetEffect --- README.md | 32 +++++++++++++++++++++ lib/lifx-lan-composer.js | 61 ++++++++++++++++++++++++++++++++++++++++ lib/lifx-lan-device.js | 15 ++++++++++ package.json | 5 ++-- 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d3e375e..1de99dd 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ $ npm install node-lifx-lan * [lightSetInfrared() method](#LifxLanDevice-lightSetInfrared-method) * [multiZoneSetColorZones() method](#LifxLanDevice-multiZoneSetColorZones-method) * [multiZoneGetColorZones() method](#LifxLanDevice-multiZoneGetColorZones-method) + * [multiZoneSetEffect() method](#LifxLanDevice-multiZoneSetEffect-method) * [tileGetDeviceChain() method](#LifxLanDevice-tileGetDeviceChain-method) * [tileSetUserPosition() method](#LifxLanDevice-tileSetUserPosition-method) * [tileGetTileState64() method](#LifxLanDevice-tileGetTileState64-method) @@ -1780,6 +1781,35 @@ The code above will output the result as follows: } ``` +### multiZoneSetEffect(*params*) method + +The `multiZoneSetEffect()` method sets the firmware effect to display on a multizone device [[SetMultiZoneEffect - 508](https://lan.developer.lifx.com/docs/firmware-effects#section-setmultizoneeffect-508)]. This method returns a `Promise` object. + +This method takes a hash object as an argument containing properties as follows: + +Property | Type | Requred | Description +:-----------|:--------|:---------|:----------- +`type` | Integer | Required | `0`: OFF, `1`: MOVE +`speed` | Integer | Required | Time in milliseconds for a complete animation cycle to occur +`duration` | Integer | Optional | Duration of effect in milliseconds. The default value is `0` a.k.a. infinite +`direction` | Integer | Optional | `0`: TOWARDS, `1`: AWAY + +```JavaScript +Lifx.discover().then((device_list) => { + let dev = device_list[0]; + return dev.multiZoneSetEffect({ + type : 1, + speed : 1000, + duration : 0, + direction : 1 + }); +}).then((res) => { + console.log('Done!'); +}).catch((error) => { + console.error(error); +}); +``` + ### tileGetDeviceChain() method The `tileGetDeviceChain()` method returns information about the tiles in the chain [[GetDeviceChain - 701](https://lan.developer.lifx.com/docs/tile-messages#section-getdevicechain-701)]. This method returns a `Promise` object. @@ -2130,6 +2160,8 @@ Note that the actual number of elements in the `tiles` array equals however many --------------------------------------- ## Release Note +* v0.4.1 (2020-04-24) + * Added support for [multizone effects](https://lan.developer.lifx.com/docs/firmware-effects) (thanks to [@paddy2k]) * v0.4.0 (2019-10-08) * Supported the [tile messages](https://lan.developer.lifx.com/docs/tile-messages) (thanks to [@furey](https://github.com/futomi/node-lifx-lan/pull/19)) * v0.3.1 (2018-09-17) diff --git a/lib/lifx-lan-composer.js b/lib/lifx-lan-composer.js index c2ae282..1ca1009 100644 --- a/lib/lifx-lan-composer.js +++ b/lib/lifx-lan-composer.js @@ -138,6 +138,8 @@ LifxLanComposer.prototype._composePayload = function(type, payload) { return this._composePayload501(payload); } else if(type === 502) { // multiZoneGetColorZones return this._composePayload502(payload); + } else if(type === 508) { // setMultiZoneEffect + return this._composePayload508(payload); } else if(type === 703) { // tileSetUserPosition return this._composePayload703(payload); } else if(type === 707) { // tileGetTitleState64 @@ -952,4 +954,63 @@ LifxLanComposer.prototype._composePayload715 = function(payload) { return {buffer: buf}; }; +/* ------------------------------------------------------------------ +* Method: _composePayload508(payload) : SetMultiZoneEffect +* - payload: +* - type | Integer | Required | 0 or 1 +* - speed | Integer | Required | Speed in milliseconds +* - duration | Integer | Optional | Duration in milliseconds (default: 0 - infinite) +* - direction | Integer | Optional | (default: 0) +* ---------------------------------------------------------------- */ +// +LifxLanComposer.prototype._composePayload508 = function(payload) { + const instance_id = mCrypto.randomBytes(4).readUInt32LE(0, true); + + // Check the parameter `type` + let type = payload['type']; + if(typeof(type) !== 'number' || type % 1 !== 0) { + return {error: new Error('The value of the `type` must be an integer.')}; + } else if(!(type === 0 || type === 1)) { + return {error: new Error('The value of the `type` must be 0 or 1.')}; + } + + // Check the `speed` + let speed = 0; + if('speed' in payload) { + speed = payload['speed']; + if(typeof(speed) !== 'number' || speed % 1 !== 0 || speed < 0 || speed > 65535) { + return {error: new Error('The `speed` must be an integer between 0 and 65535.')}; + } + } + + // Check the `duration` + let duration = 0; + if('duration' in payload) { + duration = payload['duration'] * 1000000; // convert from miliseconds to nanoseconds + if(typeof(duration) !== 'number' || duration % 1 !== 0 || duration < 0 || duration > Math.pow(2, 64)) { + return {error: new Error('The `duration` must be an integer between 0 and 2^64.')}; + } + } + + // Check the parameter `direction` + let direction = 0; + if('direction' in payload) { + direction = payload['direction']; + if(typeof(direction) !== 'number' || direction % 1 !== 0) { + return {error: new Error('The value of the `direction` must be an integer.')}; + } else if(!(direction === 0 || direction === 1)) { + return {error: new Error('The value of the `direction` must be 0 or 1.')}; + } + } + + // Compose a payload + let buf = Buffer.alloc(63); + buf.writeUInt32LE(instance_id, 0); + buf.writeUInt8(type, 4); + buf.writeUInt32LE(speed, 7); + buf.writeBigInt64LE(BigInt(duration), 11); + buf.writeUInt32LE(direction, 31); + return {buffer: buf}; +} + module.exports = new LifxLanComposer(); diff --git a/lib/lifx-lan-device.js b/lib/lifx-lan-device.js index bf94af5..0874e63 100644 --- a/lib/lifx-lan-device.js +++ b/lib/lifx-lan-device.js @@ -763,6 +763,21 @@ LifxLanDevice.prototype.lightSetInfrared = function (params) { return this._request(122, params); }; + +/* ------------------------------------------------------------------ +* Method: multiZoneSetEffect(params) +* - params: +* - brightness | Float | Required | 0.0 - 1.0 +* - type | Integer | Required | OFF or MOVE +* - speed | Integer | Required | Speed in milliseconds +* - duration | Integer | Optional | Duration in milliseconds (default: 0 - infinite) +* - direction | Integer | Optional | TOWARDS or AWAY (default: TOWARDS) +* ---------------------------------------------------------------- */ +LifxLanDevice.prototype.multiZoneSetEffect = function (params) { + return this._request(508, params); +}; + + /* ------------------------------------------------------------------ * Method: multiZoneSetColorZones(params) * - params: diff --git a/package.json b/package.json index 6b7c192..179d671 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-lifx-lan", - "version": "0.4.0", + "version": "0.4.1", "description": "The node-lifx-lan is a Node.js module which allows you to communicate with the Wi-Fi LED smart light products \"LIFX\" using the LAN protocol.", "main": "./lib/lifx-lan.js", "files": [ @@ -27,6 +27,5 @@ "url": "https://github.com/futomi/node-lifx-lan.git" }, "readmeFilename": "README.md", - "dependencies": { - } + "dependencies": {} }