diff --git a/README.md b/README.md index 3d3a1df9..c624ff70 100644 --- a/README.md +++ b/README.md @@ -89,11 +89,177 @@ key | description | example | default | required | unit tested `debug` | Outputs some additional logs, useful for figuring out issues. | true | false | No | Yes `host` | The IP or MAC address of the Broadlink RM device. | 192.168.1.32 | (auto-discovered) | No | No +## Hex Object Structure +Any hex value in the config can be either a hex string or a hex object that can be configured to send multiple codes. + +### Hex String +When a simple hex string is used, the hex code will be sent when an accessory is turned on, but not when it is turned off. + +``` +{ + ... + "data": "ON_HEX_CODE" + ... +} +``` + +Sometimes, specific keys may be required such as `open`, `lock`, or `swingToggle`. +``` +{ + ... + "data": { + "open": "OPEN_HEX_CODE" + } + ... +} +``` + + +### On/Off +In switches you may want to also send an `off` hex code: + +``` +{ + ... + "data": { + on: "ON_HEX_CODE", + off: "OFF_HEX_CODE" + } + ... +} +``` + +### Repeat +You may wish for a hex code to be sent multiple times. A delay can be added between each send of the hex code by adding an `"interval"`. + +The following will perform the following sequence when turning the accessory on: + +Send "ON_HEX_CODE" +Wait 0.3s +Send "ON_HEX_CODE" +Wait 0.3s +Send "ON_HEX_CODE" + +``` +{ + ... + "data": [ + { + "data": "ON_HEX_CODE", + "sendCount": 3, + "interval": 0.3 + } + ] + ... +} +``` + +### Repeat On/Off +You can also separate the hex object to have separate "on" and "off" outcomes: + +The following will perform the following sequence when turning the accessory off: + +Send "OFF_HEX_CODE" +Wait 0.3s +Send "OFF_HEX_CODE" +Wait 0.3s +Send "OFF_HEX_CODE" + +``` +{ + ... + "data": { + "on": "ON_HEX_CODE", + "off": [ + { + "data": "OFF_HEX_CODE", + "sendCount": 3, + "interval": 0.3 + } + ] + } + ... +} +``` + +### Multiple Hex Codes +You may wish for different hex codes to be sent at once. A delay can be added between each hex code by adding an `"pause"` value. + +The following will perform the following sequence when turning the accessory on: + +Send "ON_HEX_CODE_1" +Wait 0.3s +Send "ON_HEX_CODE_2" +Wait 0.3s +Send "ON_HEX_CODE_3" + +``` +{ + ... + "data": { + "on": [ + { + "data": "ON_HEX_CODE_1", + "pause": 0.3 + }, + { + "data": "ON_HEX_CODE_2", + "pause": 0.3 + }, + { + "data": "ON_HEX_CODE_3", + } + ], + "off": "OFF_HEX" + } + ... +} +``` + +### Multiple Hex Codes With Repeats +You may wish for different hex codes to be sent at once, with some repeating. A delay can be added between each hex code by adding an `"pause"` value. A delay can be added between each repeats of the same hex code by adding an `"interval"`. + +The following will perform the following sequence when turning the accessory on: + +Send "ON_HEX_CODE_1" +Wait 0.1s +Send "ON_HEX_CODE_1" +Wait 0.1s +Send "ON_HEX_CODE_1" +Wait 0.3s +Send "ON_HEX_CODE_2" +Wait 0.3s +Send "ON_HEX_CODE_3" + +``` +{ + ... + "data": { + "on": [ + { + "data": "ON_HEX_CODE_1", + "sendCount": 3, + "interval": 0.1, + "pause": 0.3 + }, + { + "data": "ON_HEX_CODE_2", + "pause": 0.3 + }, + { + "data": "ON_HEX_CODE_3", + } + ], + "off": "OFF_HEX" + } + ... +} +``` + + ## Accessory Types - [switch](#switch) -- [switch-multi](#switch-multi) -- [switch-repeat](#switch-repeat) - [fan](#fan) - [light](#light) - [garage-door-opener](#garage-door-opener) @@ -118,41 +284,9 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`on` | A hex code string to be sent when the switch is changed to the on position. -`off` | A hex code string to be sent when the switch is changed to the off position. - -### switch-multi -Turn the switch on and the switch will send each hex code in the provided array. You can also set the interval between each send. +`on` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the on position. +`off` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the off position. -key | description | example | default | required | unit tested ---- | ----------- | ------- | ------- | -------- | ----------- -`data` | Hex data stored as an array of strings. You can also set separate `on` and `off` arrays of codes similar to the `switch` accessory. | [ "26005800000..." ] | - | Yes | Yes -`interval` | The amount of time between each send of a hex code in seconds. | 0.3 | 1 | No | No -`enableAutoOff` | Turn the switch off automatically when `onDuration` has been reached. | true | false | No | Yes -`onDuration` | The amount of time before the switch automatically turns itself off (used in conjunction with `enableAutoOff`). | 5 | 60 | No | Yes -`enableAutoOn` | Turn the switch on automatically when `offDuration` has been reached | false | true | No | Yes -`offDuration` | The amount of time before the switch automatically turns itself on (used in conjunction with `enableAutoOn`). | 5 | 60 | No | Yes - -### switch-repeat -Turn the switch on and the switch will repeatedly send the hex code until it reaches the defined send count. You can also set the interval between each send. - -key | description | example | default | required | unit tested ---- | ----------- | ------- | ------- | -------- | ----------- -`data` | Hex data stored as string. You can also set separate `on` and `off` codes similar to the `switch` accessory. | 26005800000... | - | Yes | Yes -`sendCount` | The number of times the hex code should be sent. | 5 | 1 | No | No -`onSendCount` | If you set separate `on` and `off` codes you can use this to override the `sendCount` when the switch is turned on. | 5 | 1 | No | Yes -`offSendCount` | If you set separate `on` and `off` codes you can use this to override the `sendCount` when the switch is turned off. | 5 | 1 | No | Yes -`interval` | The amount of time between each send of a hex code in seconds. | 0.3 | 1 | No | Yes -`enableAutoOff` | Turn the switch off automatically when `onDuration` has been reached. | true | false | No | Yes -`onDuration` | The amount of time before the switch automatically turns itself off (used in conjunction with `enableAutoOff`). | 5 | 60 | No | Yes -`enableAutoOn` | Turn the switch on automatically when `offDuration` has been reached | false | true | No | Yes -`offDuration` | The amount of time before the switch automatically turns itself on (used in conjunction with `enableAutoOn`). | 5 | 60 | No | Yes - -#### "data" key-value object -key | description ---- | ----------- -`on` | A hex code string to be sent when the switch is changed to the on position. -`off` | A hex code string to be sent when the switch is changed to the off position. ### outlet Turn the outlet on and the `on` hex code is sent, turn it off and the `off` hex code is sent. @@ -171,8 +305,8 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`on` | A hex code string to be sent when the plug is changed to the on position. -`off` | A hex code string to be sent when the plug is changed to the off position. +`on` | A hex code string or [object](#hex-object-structure) to be sent when the plug is changed to the on position. +`off` | A hex code string or [object](#hex-object-structure) to be sent when the plug is changed to the off position. ### fan Turn the fan on and the `on` hex code is sent, turn it off and the `off` hex code is sent. @@ -190,12 +324,12 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`on` | A hex code string to be sent when the switch is changed to the on position. -`off` | A hex code string to be sent when the switch is changed to the off position. -`clockwise` | A hex code string to be sent to make the fan go clockwise. -`counterClockwise` | A hex code string to be sent to make the fan go counter clockwise. -`swingToggle` | A hex code string used to toggle the swing mode on/off. -`fanSpeedX` | A hex code string where X is any fan speed you wish to support e.g. "fanSpeed100". +`on` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the on position. +`off` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the off position. +`clockwise` | A hex code string or [object](#hex-object-structure) to be sent to make the fan go clockwise. +`counterClockwise` | A hex code string or [object](#hex-object-structure) to be sent to make the fan go counter clockwise. +`swingToggle` | A hex code string or [object](#hex-object-structure) used to toggle the swing mode on/off. +`fanSpeedX` | A hex code string or [object](#hex-object-structure) where X is any fan speed you wish to support e.g. "fanSpeed100". ### light Turn the light on and the `defaultBrightness` is set unless `useLastKnownBrightness` is set to true in which case the last brightness that was set will be used. @@ -218,9 +352,9 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`off` | A hex code string to be sent when the switch is changed to the off position. -`brightnessX` | A hex code string where X is any brightness you wish to support e.g. "brightness100". -`hueX` | A hex code string where X is any hue you wish to support between 0 and 359 e.g. "hue42". +`off` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the off position. +`brightnessX` | A hex code string or [object](#hex-object-structure) where X is any brightness you wish to support e.g. "brightness100". +`hueX` | A hex code string or [object](#hex-object-structure) where X is any hue you wish to support between 0 and 359 e.g. "hue42". `on` | If set, this hex code shall be sent before brightness or hue is set using `onDelay` to create a delay between sends. ### garage-door-opener @@ -237,10 +371,10 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`open` | A hex code string to be sent when the switch is changed to the open position. -`close` | A hex code string to be sent when the switch is changed to the close position. -`unlock` | A hex code string to be sent when the switch is set to unlock. -`lock` | A hex code string to be sent when the switch is set to lock. +`open` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the open position. +`close` | A hex code string or [object](#hex-object-structure) to be sent when the switch is changed to the close position. +`unlock` | A hex code string or [object](#hex-object-structure) to be sent when the switch is set to unlock. +`lock` | A hex code string or [object](#hex-object-structure) to be sent when the switch is set to lock. ### lock Set the switch to unlock and the `unlock` hex code is sent, set it to lock and the `lock` hex code is sent. @@ -255,8 +389,8 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`unlock` | A hex code string to be sent when the switch is set to unlock. -`lock` | A hex code string to be sent when the switch is set to lock. +`unlock` | A hex code string or [object](#hex-object-structure) to be sent when the switch is set to unlock. +`lock` | A hex code string or [object](#hex-object-structure) to be sent when the switch is set to lock. ### window-covering The window-covering accessory designed to be used by IR/RF controlled blinds/shades/shutters. @@ -275,9 +409,9 @@ key | description | example | default | required | unit tested #### "data" key-value object key | description --- | ----------- -`open` | A hex code string to be sent when the window-covering is requested to open. -`close` | A hex code string to be sent when the window-covering is requested to close. -`stop` | A hex code string to be sent when the window-covering is stopped automatically. +`open` | A hex code string or [object](#hex-object-structure) to be sent when the window-covering is requested to open. +`close` | A hex code string or [object](#hex-object-structure) to be sent when the window-covering is requested to close. +`stop` | A hex code string or [object](#hex-object-structure) to be sent when the window-covering is stopped automatically. `openCompletely` | When set, this hex code will be sent when a value of 100% is requested. `closeCompletely` | When set, this hex code will be sent when a value of 0% is requested. @@ -309,7 +443,7 @@ key | description | example | default | required | unit tested key | description --- | ----------- `on` | An optional hex code to be used in conjunction with the `turnOnWhenOff` configuration. -`off` | A hex code string to be sent when the air conditioner is asked to be turned off. +`off` | A hex code string or [object](#hex-object-structure) to be sent when the air conditioner is asked to be turned off. `temperatureX` | Where X is any temperature you wish to support e.g. `temperature30`. See below. #### "temperatureX" key-value object diff --git a/accessories/accessory.js b/accessories/accessory.js index b00acb1b..2eb74b07 100644 --- a/accessories/accessory.js +++ b/accessories/accessory.js @@ -3,6 +3,8 @@ const uuid = require('uuid'); const { HomebridgeAccessory } = require('homebridge-platform-helper'); const sendData = require('../helpers/sendData'); +const delayForDuration = require('../helpers/delayForDuration'); +const catchDelayCancelError = require('../helpers/catchDelayCancelError'); class BroadlinkRMAccessory extends HomebridgeAccessory { @@ -23,6 +25,60 @@ class BroadlinkRMAccessory extends HomebridgeAccessory { performSetValueAction ({ host, data, log, name, debug }) { sendData({ host, hexData: data, log, name, debug }); } + reset () { + // Clear Multi-hex timeouts + if (this.intervalTimeoutPromise) { + this.intervalTimeoutPromise.cancel(); + this.intervalTimeoutPromise = null; + } + + if (this.pauseTimeoutPromise) { + this.pauseTimeoutPromise.cancel(); + this.pauseTimeoutPromise = null; + } + } + + async performSend (data, actionCallback) { + const { debug, config, host, log, name } = this; + + if (typeof data === 'string') { + sendData({ host, hexData: data, log, name, debug }); + + return; + } + + await catchDelayCancelError(async () => { + // Itterate through each hex config in the array + for (let index = 0; index < data.length; index++) { + const { pause } = data[index]; + + await this.performRepeatSend(data[index], actionCallback); + + if (pause) { + this.pauseTimeoutPromise = delayForDuration(pause); + await this.pauseTimeoutPromise; + } + } + }); + } + + async performRepeatSend (parentData, actionCallback) { + const { host, log, name, debug } = this; + let { data, interval, sendCount } = parentData; + + sendCount = sendCount || 1 + if (sendCount > 1) interval = interval || 0.1; + + // Itterate through each hex config in the array + for (let index = 0; index < sendCount; index++) { + sendData({ host, hexData: data, log, name, debug }); + + if (interval && index < sendCount - 1) { + this.intervalTimeoutPromise = delayForDuration(interval); + await this.intervalTimeoutPromise; + } + } + } } module.exports = BroadlinkRMAccessory; diff --git a/accessories/aircon.js b/accessories/aircon.js index d9ae9051..4cdd633e 100644 --- a/accessories/aircon.js +++ b/accessories/aircon.js @@ -2,7 +2,6 @@ const { assert } = require('chai'); const uuid = require('uuid'); const fs = require('fs'); -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration'); const { ServiceManagerTypes } = require('../helpers/serviceManager'); const catchDelayCancelError = require('../helpers/catchDelayCancelError'); @@ -94,6 +93,8 @@ class AirConAccessory extends BroadlinkRMAccessory { } reset () { + super.reset(); + this.state.isRunningAutomatically = false; if (this.shouldIgnoreAutoOnOffPromise) { @@ -182,7 +183,7 @@ class AirConAccessory extends BroadlinkRMAccessory { if (targetHeatingCoolingState === 'off') { this.updateServiceCurrentHeatingCoolingState(HeatingCoolingStates.off); - sendData({ host, hexData: data.off, log, name, debug }); + await this.performSend(data.off); return; } @@ -250,7 +251,7 @@ class AirConAccessory extends BroadlinkRMAccessory { this.serviceManager.refreshCharacteristicUI(Characteristic.CurrentHeatingCoolingState); this.serviceManager.refreshCharacteristicUI(Characteristic.TargetHeatingCoolingState); - sendData({ host, hexData: hexData.data, log, name, debug }); + await this.performSend(hexData.data); } getTemperatureHexData (temperature) { @@ -282,15 +283,15 @@ class AirConAccessory extends BroadlinkRMAccessory { return { finalTemperature, hexData } } - checkTurnOnWhenOff () { + async checkTurnOnWhenOff () { const { config, data, debug, host, log, name, state } = this; const { on } = data; if (state.currentHeatingCoolingState === Characteristic.TargetHeatingCoolingState.OFF && config.turnOnWhenOff) { log(`${name} sendTemperature (sending "on" hex before sending temperature)`); - if (on) sendData({ host, hexData: on, log, name, debug }); - + if (on) await this.performSend(on); + return true; } diff --git a/accessories/fan.js b/accessories/fan.js index 6d656cad..1093d986 100644 --- a/accessories/fan.js +++ b/accessories/fan.js @@ -1,10 +1,17 @@ -const sendData = require('../helpers/sendData'); const { ServiceManagerTypes } = require('../helpers/serviceManager'); const SwitchAccessory = require('./switch'); class FanAccessory extends SwitchAccessory { + async setSwitchState (hexData, previousValue) { + if (!this.state.switchState) { + this.lastFanSpeed = undefined; + } + + super.setSwitchState(hexData, previousValue); + } + async setFanSpeed (hexData) { const { data, host, log, state, name, debug} = this; @@ -40,7 +47,7 @@ class FanAccessory extends SwitchAccessory { // Get the closest speed's hex data hexData = data[`fanSpeed${closest}`]; - sendData({ host, hexData, log, name, debug }); + await this.performSend(hexData); this.checkAutoOnOff(); } diff --git a/accessories/garageDoorOpener.js b/accessories/garageDoorOpener.js index 168be9ff..bde6c549 100644 --- a/accessories/garageDoorOpener.js +++ b/accessories/garageDoorOpener.js @@ -1,4 +1,3 @@ -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration'); const BroadlinkRMAccessory = require('./accessory'); const { ServiceManagerTypes } = require('../helpers/serviceManager'); @@ -12,7 +11,8 @@ class GarageDoorOpenerAccessory extends BroadlinkRMAccessory { } reset () { - + super.reset(); + // Clear existing timeouts if (this.closingTimeoutPromise) { this.closingTimeoutPromise.cancel(); @@ -44,7 +44,7 @@ class GarageDoorOpenerAccessory extends BroadlinkRMAccessory { } // Send pre-determined hex data - sendData({ host, hexData, log, name, debug }); + await this.performSend(hexData); catchDelayCancelError(async () => { if (state.doorTargetState === Characteristic.TargetDoorState.OPEN) { @@ -96,9 +96,9 @@ class GarageDoorOpenerAccessory extends BroadlinkRMAccessory { } async setLockTargetState (hexData) { - const { config, data, host, log, name, state, debug, serviceManager } = this; + const { config, log, name, state, serviceManager } = this; - sendData({ host, hexData, log, name, debug }); + await this.performSend(hexData); if (!state.lockTargetState) { log(`${name} setCurrentLockState: unlocked`) @@ -108,6 +108,8 @@ class GarageDoorOpenerAccessory extends BroadlinkRMAccessory { serviceManager.setCharacteristic(Characteristic.LockCurrentState, Characteristic.LockCurrentState.SECURED); } } + + // Service Manager Setup setupServiceManager () { const { data, name, serviceManagerType } = this; diff --git a/accessories/light.js b/accessories/light.js index 855f32a5..99b6e155 100644 --- a/accessories/light.js +++ b/accessories/light.js @@ -1,5 +1,4 @@ const { ServiceManagerTypes } = require('../helpers/serviceManager'); -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration'); const catchDelayCancelError = require('../helpers/catchDelayCancelError') @@ -19,6 +18,7 @@ class LightAccessory extends SwitchAccessory { reset () { super.reset(); + // Clear existing timeouts if (this.onDelayTimeoutPromise) { this.onDelayTimeoutPromise.cancel(); this.onDelayTimeoutPromise = undefined @@ -39,12 +39,14 @@ class LightAccessory extends SwitchAccessory { state.switchState = false; serviceManager.setCharacteristic(Characteristic.Brightness, brightness); } else { - if (hexData) sendData({ host, hexData, log, name, debug }); + if (hexData) await this.performSend(hexData); this.checkAutoOnOff(); } } else { - if (hexData) sendData({ host, hexData, log, name, debug }); + this.lastBrightness = undefined; + + if (hexData) await this.performSend(hexData); this.checkAutoOnOff(); } @@ -69,7 +71,7 @@ class LightAccessory extends SwitchAccessory { if (on) { log(`${name} setHue: (turn on, wait ${onDelay}s)`); - sendData({ host, hexData: on, log, name, debug }); + await this.performSend(on); log(`${name} setHue: (wait ${onDelay}s then send data)`); this.onDelayTimeoutPromise = delayForDuration(onDelay); @@ -83,7 +85,7 @@ class LightAccessory extends SwitchAccessory { const hexData = data[`hue${closest}`]; log(`${name} setHue: (closest: hue${closest})`); - sendData({ host, hexData, log, name, debug }); + await this.performSend(hexData); }); } @@ -93,6 +95,19 @@ class LightAccessory extends SwitchAccessory { const { off, on } = data; let { onDelay } = config; + if (this.lastBrightness === state.brightness) { + + if (state.brightness > 0) { + state.switchState = true; + } + + await this.checkAutoOnOff(); + + return; + } + + this.lastBrightness = state.brightness; + this.reset(); if (state.brightness > 0) { @@ -102,7 +117,7 @@ class LightAccessory extends SwitchAccessory { if (on) { log(`${name} setBrightness: (turn on, wait ${onDelay}s)`); - sendData({ host, hexData: on, log, name, debug }); + await this.performSend(on); log(`${name} setHue: (wait ${onDelay}s then send data)`); this.onDelayTimeoutPromise = delayForDuration(onDelay); @@ -116,10 +131,10 @@ class LightAccessory extends SwitchAccessory { const hexData = data[`brightness${closest}`]; log(`${name} setBrightness: (closest: ${closest})`); - sendData({ host, hexData, log, name, debug }); + await this.performSend(hexData); } else { log(`${name} setBrightness: (off)`); - sendData({ host, hexData: off, log, name, debug }); + await this.performSend(off); } await this.checkAutoOnOff(); diff --git a/accessories/lock.js b/accessories/lock.js index 699cd429..38354ddf 100644 --- a/accessories/lock.js +++ b/accessories/lock.js @@ -1,4 +1,3 @@ -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration'); const BroadlinkRMAccessory = require('./accessory'); const { ServiceManagerTypes } = require('../helpers/serviceManager'); @@ -18,6 +17,8 @@ class LockAccessory extends BroadlinkRMAccessory { } reset () { + super.reset(); + // Clear existing timeouts if (this.lockingTimeoutPromise) { this.lockingTimeoutPromise.cancel(); @@ -38,10 +39,10 @@ class LockAccessory extends BroadlinkRMAccessory { async setLockTargetState (hexData, currentState) { const { host, log, name, debug } = this; - this.reset() + this.reset(); // Send pre-determined hex data - sendData({ host, hexData, log, name, debug }); + await this.performSend(hexData); catchDelayCancelError(async () => { if (currentState === Characteristic.LockTargetState.SECURED) { @@ -85,6 +86,8 @@ class LockAccessory extends BroadlinkRMAccessory { this.lock() } } + + // Service Manager Setup setupServiceManager () { const { data, name, serviceManagerType } = this; diff --git a/accessories/outlet.js b/accessories/outlet.js index 6d520613..8c9a8904 100644 --- a/accessories/outlet.js +++ b/accessories/outlet.js @@ -1,7 +1,6 @@ const ping = require('ping'); const { ServiceManagerTypes } = require('../helpers/serviceManager'); -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration') const SwitchAccessory = require('./switch'); @@ -27,14 +26,6 @@ class OutletAccessory extends SwitchAccessory { callback(null, value) } - async setSwitchState (hexData) { - const { data, host, log, name, state, debug } = this; - - if (hexData) sendData({ host, hexData, log, name, debug }); - - this.checkAutoOnOff(); - } - setupServiceManager () { const { data, name, config, serviceManagerType } = this; const { on, off } = data || { }; diff --git a/accessories/switch.js b/accessories/switch.js index 76b5b35e..79309961 100644 --- a/accessories/switch.js +++ b/accessories/switch.js @@ -1,5 +1,4 @@ const { ServiceManagerTypes } = require('../helpers/serviceManager'); -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration'); const catchDelayCancelError = require('../helpers/catchDelayCancelError'); const ping = require('../helpers/ping') @@ -34,6 +33,8 @@ class SwitchAccessory extends BroadlinkRMAccessory { } reset () { + super.reset(); + // Clear Timeouts if (this.delayTimeoutPromise) { this.delayTimeoutPromise.cancel(); @@ -84,7 +85,9 @@ class SwitchAccessory extends BroadlinkRMAccessory { async setSwitchState (hexData) { const { data, host, log, name, debug } = this; - if (hexData) sendData({ host, hexData, log, name, debug }); + this.reset(); + + if (hexData) await this.performSend(hexData); this.checkAutoOnOff(); } @@ -134,8 +137,8 @@ class SwitchAccessory extends BroadlinkRMAccessory { setMethod: this.setCharacteristicValue, bind: this, props: { - onData: on, - offData: off, + onData: on || data, + offData: off || undefined, setValuePromise: this.setSwitchState.bind(this) } }); diff --git a/accessories/switchMulti.js b/accessories/switchMulti.js index 23f2e17f..1b0e554e 100644 --- a/accessories/switchMulti.js +++ b/accessories/switchMulti.js @@ -62,7 +62,11 @@ class SwitchMultiAccessory extends SwitchAccessory { } setupServiceManager () { - const { data, name, config, serviceManagerType } = this; + const { data, log, name, config, serviceManagerType } = this; + + setTimeout(() => { + log(`\x1b[33m[Warning] \x1b[30m${name}: The "switch-multi" accessory is now depreciated and shall be removed in the future. Check out the updated "switch" documentation at http://github.com/lprhodes/homebridge-broadlink-rm`); + }, 1600) this.serviceManager = new ServiceManagerTypes[serviceManagerType](name, Service.Switch, this.log); diff --git a/accessories/switchMultiRepeat.js b/accessories/switchMultiRepeat.js index 36c24546..d7218992 100644 --- a/accessories/switchMultiRepeat.js +++ b/accessories/switchMultiRepeat.js @@ -91,7 +91,11 @@ class SwitchMultiAccessory extends SwitchAccessory { } setupServiceManager () { - const { data, name, config, serviceManagerType } = this; + const { data, log, name, config, serviceManagerType } = this; + + setTimeout(() => { + log(`\x1b[33m[Warning] \x1b[30m${name}: The "switch-multi-repeat" accessory is now depreciated and shall be removed in the future. Check out the updated "switch" documentation at http://github.com/lprhodes/homebridge-broadlink-rm`); + }, 1600) this.serviceManager = new ServiceManagerTypes[serviceManagerType](name, Service.Switch, this.log); diff --git a/accessories/switchRepeat.js b/accessories/switchRepeat.js index ba1c2085..9100cc75 100644 --- a/accessories/switchRepeat.js +++ b/accessories/switchRepeat.js @@ -58,8 +58,12 @@ class SwitchRepeatAccessory extends SwitchAccessory { } setupServiceManager () { - const { data, name, config, serviceManagerType } = this; - + const { data, log, name, config, serviceManagerType } = this; + + setTimeout(() => { + log(`\x1b[33m[Warning] \x1b[30m${name}: The "switch-repeat" accessory is now depreciated and shall be removed in the future. Check out the updated "switch" documentation at http://github.com/lprhodes/homebridge-broadlink-rm`); + }, 1600) + this.serviceManager = new ServiceManagerTypes[serviceManagerType](name, Service.Switch, this.log); this.serviceManager.addToggleCharacteristic({ diff --git a/accessories/windowCovering.js b/accessories/windowCovering.js index 85a7ff05..1578001e 100644 --- a/accessories/windowCovering.js +++ b/accessories/windowCovering.js @@ -1,6 +1,5 @@ const { assert } = require('chai'); -const sendData = require('../helpers/sendData'); const delayForDuration = require('../helpers/delayForDuration'); const { ServiceManagerTypes } = require('../helpers/serviceManager'); const catchDelayCancelError = require('../helpers/catchDelayCancelError'); @@ -11,7 +10,7 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { setDefaults () { const { config, state } = this; const { currentPosition, positionState } = state; - const { initialDelay, percentageChangePerSend, totalDurationOpen, totalDurationClose } = config; + const { initialDelay, totalDurationOpen, totalDurationClose } = config; // Check required propertoes assert.isNumber(totalDurationOpen, '`totalDurationOpen` is required and should be numeric.') @@ -26,10 +25,8 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { } reset () { - this.clearAllExistingTimers(); - } + super.reset(); - async clearAllExistingTimers () { // Clear existing timeouts if (this.initialDelayPromise) { this.initialDelayPromise.cancel(); @@ -45,17 +42,6 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { this.autoStopPromise.cancel(); this.autoStopPromise = null; } - - // Clear Multi-hex timeouts - if (this.intervalTimeoutPromise) { - this.intervalTimeoutPromise.cancel(); - this.intervalTimeoutPromise = null; - } - - if (this.pauseTimeoutPromise) { - this.pauseTimeoutPromise.cancel(); - this.pauseTimeoutPromise = null; - } } // User requested a specific position or asked the window-covering to be open or closed @@ -65,10 +51,10 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { async setTargetPositionActual (hexData, previousValue) { const { config, host, debug, data, log, name, state, serviceManager } = this; - const { initialDelay, percentageChangePerSend } = config; + const { initialDelay } = config; const { open, close, stop } = data; - this.clearAllExistingTimers(); + this.reset(); // Ignore if no change to the targetPosition if (state.targetPosition === previousValue) return; @@ -78,7 +64,8 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { this.initialDelayPromise = delayForDuration(initialDelay); await this.initialDelayPromise; - if (this.checkOpenOrCloseCompletely()) return; + const closeCompletely = await this.checkOpenOrCloseCompletely(); + if (closeCompletely) return; log(`${name} setTargetPosition: (currentPosition: ${state.currentPosition})`); @@ -88,8 +75,6 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { state.opening = (difference > 0); if (!state.opening) difference = -1 * difference; - log(`${name} setTargetPosition: (percentageChangePerSend: ${percentageChangePerSend})`); - hexData = state.opening ? open : close // Perform the actual open/close asynchronously i.e. without await so that HomeKit status can be updated @@ -106,7 +91,7 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { log(`${name} setTargetPosition: currently ${state.currentPosition}%, moving to ${state.targetPosition}%`); - this.performSend(hexData); + await this.performSend(hexData); let difference = state.targetPosition - state.currentPosition if (!state.opening) difference = -1 * difference; @@ -122,12 +107,12 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { this.autoStopPromise = delayForDuration(totalTime); await this.autoStopPromise; - this.stopWindowCovering(); + await this.stopWindowCovering(); serviceManager.setCharacteristic(Characteristic.CurrentPosition, state.targetPosition); } - stopWindowCovering () { + async stopWindowCovering () { const { data, host, log, name, state, debug, serviceManager } = this; const { stop } = data; @@ -136,12 +121,12 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { // Reset the state and timers this.reset(); - sendData({ host, hexData: stop, log, name, debug }); + await this.performSend(stop); serviceManager.setCharacteristic(Characteristic.PositionState, Characteristic.PositionState.STOPPED); } - checkOpenOrCloseCompletely () { + async checkOpenOrCloseCompletely () { const { data, debug, host, log, name, serviceManager, state } = this; const { openCompletely, closeCompletely } = data; @@ -149,7 +134,7 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { if (state.targetPosition === 0 && closeCompletely) { serviceManager.setCharacteristic(Characteristic.CurrentPosition, state.targetPosition); - sendData({ host, hexData: closeCompletely, log, name, debug }); + await this.performSend(closeCompletely); this.stopWindowCovering(); @@ -160,7 +145,7 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { if (state.targetPosition === 100 && openCompletely) { serviceManager.setCharacteristic(Characteristic.CurrentPosition, state.targetPosition); - sendData({ host, hexData: openCompletely, log, name, debug }); + await this.performSend(openCompletely); this.stopWindowCovering(); @@ -208,47 +193,6 @@ class WindowCoveringAccessory extends BroadlinkRMAccessory { }); } - async performSend (hexData) { - const { debug, config, host, log, name } = this; - - if (typeof hexData === 'string') { - sendData({ host, hexData, log, name, debug }); - - return; - } - - await catchDelayCancelError(async () => { - // Itterate through each hex config in the array - for (let index = 0; index < hexData.length; index++) { - const { pause } = hexData[index] - - await this.performRepeatSend(hexData[index]); - - if (pause) { - this.pauseTimeoutPromise = delayForDuration(pause); - await this.pauseTimeoutPromise; - } - } - }); - } - - async performRepeatSend (hexConfig) { - const { host, log, name, debug } = this; - let { data, interval, sendCount } = hexConfig; - - interval = interval || 1; - - // Itterate through each hex config in the array - for (let index = 0; index < sendCount; index++) { - sendData({ host, hexData: data, log, name, debug }); - - if (index < sendCount - 1) { - this.intervalTimeoutPromise = delayForDuration(interval); - await this.intervalTimeoutPromise; - } - } - } - setupServiceManager () { const { data, log, name, serviceManagerType } = this; diff --git a/config-sample.json b/config-sample.json index afe462a0..b5289c8f 100644 --- a/config-sample.json +++ b/config-sample.json @@ -37,50 +37,73 @@ }, { "name":"Channel Up", - "type":"switch-repeat", - "sendCount":1, - "data":"2600500000012..." + "type":"switch", + "data":"CHANNEL_UP_HEX...", + "enableAutoOff": true, + "onDuration": 1 }, { "name":"Channel Down", - "type":"switch-repeat", - "sendCount":1, - "data":"2600500000012..." + "type":"switch", + "enableAutoOff": true, + "onDuration": 1, + "data":"CHANNEL_DOWN_HEX..." }, { "name":"Volume Up", - "type":"switch-repeat", - "sendCount":5, - "interval":0.3, - "data":"2600500000012..." + "type":"switch", + "enableAutoOff": true, + "onDuration": 2.5, + "data": [ + { + "data": "VOLUME_UP_HEX...", + "sendCount": 5, + "interval": 0.3 + } + ] }, { "name":"Volume Down", - "type":"switch-repeat", - "sendCount":5, - "interval":0.3, - "data":"2600500000012..." + "type":"switch", + "enableAutoOff": true, + "onDuration": 2.5, + "data": [ + { + "data": "VOLUME_DOWN_HEX...", + "sendCount": 5, + "interval": 0.3 + } + ] }, { "name":"Entertainment", - "type":"switch-multi", - "interval":0.5, - "data": [ - "2600500000012...", - "2600500000012...", - "2600500000012..." + "type":"switch", + "enableAutoOff": true, + "onDuration": 1.5, + "data":[ + { + "data": "HEX_1...", + "pause": 0.3 + }, + { + "data": "HEX_2...", + "pause": 0.3 + }, + { + "data": "HEX_3...", + "pause": 0.3 + } ] }, { "name":"Entertainment 2", - "type":"switch-multi-repeat", - "interval":2, + "type":"switch", "data": [ { "data": "2600500000012...", "sendCount": 2, "interval": 0.3, - "pause": 10 + "pause": 2 }, { "data": "2600500000012...", @@ -91,30 +114,29 @@ }, { "name":"Entertainment 3", - "type":"switch-multi-repeat", - "interval":2, + "type":"switch", "data": { "on": [ { - "data": "2600500000012...", - "sendCount": 1, + "data": "ON_HEX_1...", "pause": 0.3 }, { - "data": "2600500000012...", - "sendCount": 1, + "data": "ON_HEX_2...", + "sendCount": 2, + "interval": 0.1, "pause": 0.3 } ], "off": [ { - "data": "2600500000012...", - "sendCount": 1, + "data": "OFF_HEX_1...", "pause": 0.3 }, { - "data": "2600500000012...", - "sendCount": 1, + "data": "OF_HEX_2...", + "sendCount": 2, + "interval": 0.1, "pause": 0.3 } ] diff --git a/package.json b/package.json index e773b7a6..329ae9af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homebridge-broadlink-rm", - "version": "3.0.5", + "version": "3.1.0", "description": "Broadlink RM plugin (including the mini and pro) for homebridge: https://github.com/nfarina/homebridge", "license": "ISC", "keywords": [ diff --git a/platform.js b/platform.js index 1dffe3d0..2c5d733f 100644 --- a/platform.js +++ b/platform.js @@ -24,7 +24,7 @@ const BroadlinkRMPlatform = class extends HomebridgePlatform { showMessage () { const { config } = this; - if (config && config.hideWelcomeMessage) return; + if (config && (config.hideWelcomeMessage || config.isUnitTest)) return; setTimeout(() => { console.log(`**************************************************************************************************************`) diff --git a/test/airConditioner.test.js b/test/airConditioner.test.js index 5fb42aee..13f4a4dc 100644 --- a/test/airConditioner.test.js +++ b/test/airConditioner.test.js @@ -112,7 +112,7 @@ describe('airConAccessory', async () => { // Set air-con mode to "auto" airConAccessory.serviceManager.setCharacteristic(Characteristic.TargetHeatingCoolingState, Characteristic.TargetHeatingCoolingState.AUTO); - await delayForDuration(0.3); + await delayForDuration(0.6); // Check hex codes were sent hexCheck({ device, codes: [ 'TEMPERATURE_16' ], count: 1 }); @@ -134,7 +134,7 @@ describe('airConAccessory', async () => { // Set air-con mode to "auto" airConAccessory.serviceManager.setCharacteristic(Characteristic.TargetHeatingCoolingState, Characteristic.TargetHeatingCoolingState.AUTO); - await delayForDuration(0.3); + await delayForDuration(0.6); // Check hex codes were sent hexCheck({ device, codes: [ 'TEMPERATURE_16' ], count: 1 }); @@ -521,7 +521,7 @@ describe('airConAccessory', async () => { // Set air-con mode to "auto" airConAccessory.serviceManager.setCharacteristic(Characteristic.TargetHeatingCoolingState, Characteristic.TargetHeatingCoolingState.AUTO); - await delayForDuration(0.3); + await delayForDuration(0.6); // Check hex codes were sent hexCheck({ device, codes: [ 'TEMPERATURE_30' ], count: 1 }); diff --git a/test/fan.test.js b/test/fan.test.js index 1bfdd389..0a4ae55e 100644 --- a/test/fan.test.js +++ b/test/fan.test.js @@ -24,6 +24,12 @@ const data = { fanSpeed40: 'FANSPEED40', } +const defaultConfig = { + data, + isUnitTest: true, + persistState: false +}; + describe('fanAccessory', () => { // Fan Turn On @@ -31,9 +37,8 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - persistState: false } const fanAccessory = new Fan(null, config, 'FakeServiceManager') @@ -41,6 +46,8 @@ describe('fanAccessory', () => { expect(fanAccessory.state.switchState).to.equal(true); + await delayForDuration(.2); + // Check hex code was sent const hasSentCode = device.hasSentCode('ON'); expect(hasSentCode).to.equal(true); @@ -56,9 +63,8 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - persistState: false } const fanAccessory = new Fan(null, config, 'FakeServiceManager') @@ -87,8 +93,7 @@ describe('fanAccessory', () => { const config = { host: device.host.address, - persistState: false, - data + ...defaultConfig, } const fanAccessory = new Fan(null, config, 'FakeServiceManager') @@ -111,9 +116,8 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, - host: device.host.address, - persistState: false + ...defaultConfig, + host: device.host.address } @@ -138,13 +142,10 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, host: device.host.address, - persistState: false + ...defaultConfig, } - - const fanAccessory = new Fan(null, config, 'FakeServiceManager') fanAccessory.serviceManager.setCharacteristic(Characteristic.RotationSpeed, 36) @@ -165,9 +166,8 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, host: device.host.address, - persistState: false + ...defaultConfig, } @@ -192,13 +192,10 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, host: device.host.address, - persistState: false + ...defaultConfig, } - - const fanAccessory = new Fan(null, config, 'FakeServiceManager') // Turn On Swing Mode @@ -224,13 +221,11 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, persistState: false, hideSwingMode: true, - } - - ; + }; const fanAccessory = new Fan(null, config, 'FakeServiceManager'); @@ -249,13 +244,10 @@ describe('fanAccessory', () => { const { device } = setup();; const config = { - data, host: device.host.address, - persistState: false + ...defaultConfig, }; - ; - const fanAccessory = new Fan(null, config, 'FakeServiceManager'); fanAccessory.serviceManager.setCharacteristic(Characteristic.RotationDirection, 0); @@ -276,9 +268,8 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, host: device.host.address, - persistState: false + ...defaultConfig } const fanAccessory = new Fan(null, config, 'FakeServiceManager') @@ -310,14 +301,11 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - persistState: false, hideRotationDirection: true, } - ; - const fanAccessory = new Fan(null, config, 'FakeServiceManager') // Attempt To Set Rotation Direction To Clockwise @@ -335,8 +323,8 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { + ...defaultConfig, name: 'Unit Test Fan', - data, host: device.host.address, persistState: true } @@ -348,6 +336,8 @@ describe('fanAccessory', () => { fanAccessory.serviceManager.setCharacteristic(Characteristic.On, true) expect(fanAccessory.state.switchState).to.equal(true); + await delayForDuration(.1); + // Should still be on when loading within a new instance fanAccessory = new Fan(null, config, 'FakeServiceManager') expect(fanAccessory.state.switchState).to.equal(true); @@ -365,10 +355,9 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, host: device.host.address, name: 'Unit Test Fan', - persistState: false + ...defaultConfig, } let fanAccessory @@ -389,16 +378,13 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, persistState: true, resendHexAfterReload: true, - resendDataAfterReloadDelay: 0.1, - isUnitTest: true + resendDataAfterReloadDelay: 0.1 } - - - + let fanAccessory // Turn On Fan @@ -434,15 +420,12 @@ describe('fanAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, persistState: true, resendHexAfterReload: false, - resendDataAfterReloadDelay: 0.1, - isUnitTest: true + resendDataAfterReloadDelay: 0.1 } - - let fanAccessory diff --git a/test/garageDoorOpener.test.js b/test/garageDoorOpener.test.js index b0fd00f1..97bb2c10 100644 --- a/test/garageDoorOpener.test.js +++ b/test/garageDoorOpener.test.js @@ -16,6 +16,12 @@ const data = { unlock: 'UNLOCK_HEX' } +const defaultConfig = { + data, + isUnitTest: true, + persistState: false +}; + describe('doorAccessory', () => { // Closing -> Closed @@ -23,10 +29,9 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { - persistState: false, + ...defaultConfig, host: device.host.address, - closeDuration: 0.2, - data + closeDuration: 0.2 } const doorAccessory = new GarageDoorOpener(null, config, 'FakeServiceManager') @@ -49,17 +54,15 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { - persistState: false, + ...defaultConfig, host: device.host.address, closeDuration: 0.2, - openDuration: 0.2, - data + openDuration: 0.2 } const doorAccessory = new GarageDoorOpener(null, config, 'FakeServiceManager') doorAccessory.serviceManager.setCharacteristic(Characteristic.TargetDoorState, Characteristic.TargetDoorState.CLOSED) - let sentHexCodeCount // Check hex code was sent @@ -112,12 +115,11 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { - persistState: false, + ...defaultConfig, host: device.host.address, closeDuration: 0.2, openDuration: 0.2, - autoCloseDelay: 0.2, - data + autoCloseDelay: 0.2 } const doorAccessory = new GarageDoorOpener(null, config, 'FakeServiceManager') @@ -168,12 +170,12 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { + ...defaultConfig, name: 'Unit Test Door', host: device.host.address, persistState: true, closeDuration: 0.2, - openDuration: 0.2, - data + openDuration: 0.2 } let doorAccessory @@ -184,7 +186,7 @@ describe('doorAccessory', () => { expect(doorAccessory.state.doorTargetState).to.equal(Characteristic.TargetDoorState.CLOSED); // Delay to allow for `closeDuration` - await delayForDuration(0.2) + await delayForDuration(0.3) expect(doorAccessory.state.doorTargetState).to.equal(Characteristic.TargetDoorState.CLOSED); expect(doorAccessory.state.doorCurrentState).to.equal(Characteristic.CurrentDoorState.CLOSED); @@ -212,12 +214,11 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { + ...defaultConfig, name: 'Unit Test Door', host: device.host.address, - persistState: false, closeDuration: 0.2, - openDuration: 0.2, - data + openDuration: 0.2 } let doorAccessory @@ -241,14 +242,13 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { + ...defaultConfig, persistState: true, host: device.host.address, resendHexAfterReload: true, resendDataAfterReloadDelay: 0.1, closeDuration: 0.2, - openDuration: 0.2, - data, - isUnitTest: true + openDuration: 0.2 } let doorAccessory @@ -291,14 +291,13 @@ describe('doorAccessory', () => { const { device } = setup(); const config = { + ...defaultConfig, persistState: true, host: device.host.address, resendHexAfterReload: false, resendDataAfterReloadDelay: 0.1, closeDuration: 0.2, - openDuration: 0.2, - data, - isUnitTest: true + openDuration: 0.2 } @@ -399,6 +398,8 @@ describe('doorAccessory', () => { const lockAccessory = new GarageDoorOpener(null, config, 'FakeServiceManager') lockAccessory.serviceManager.setCharacteristic(Characteristic.LockTargetState, Characteristic.LockTargetState.SECURED) + await delayForDuration(.1); + // Locked expect(lockAccessory.state.lockCurrentState).to.equal(Characteristic.LockCurrentState.SECURED); expect(lockAccessory.state.lockTargetState).to.equal(Characteristic.LockTargetState.SECURED); @@ -428,6 +429,8 @@ describe('doorAccessory', () => { // Lock lockAccessory.serviceManager.setCharacteristic(Characteristic.LockTargetState, Characteristic.LockTargetState.SECURED) + await delayForDuration(.1); + let sentHexCodeCount // Check hex code was sent @@ -448,6 +451,8 @@ describe('doorAccessory', () => { // Unlock lockAccessory.serviceManager.setCharacteristic(Characteristic.LockTargetState, Characteristic.LockTargetState.UNSECURED) + await delayForDuration(.1); + // Check hex sent const hasSentUnlockCode = device.hasSentCode('UNLOCK_HEX') expect(hasSentUnlockCode).to.equal(true); diff --git a/test/generalAccessories.test.js b/test/generalAccessories.test.js index cab2ae1c..3d6feb65 100644 --- a/test/generalAccessories.test.js +++ b/test/generalAccessories.test.js @@ -11,6 +11,7 @@ describe('disableLogs', () => { it('disableLogs true returns empty function', async () => { const config = { + isUnitTest: true, hideScanFrequencyButton: true, disableLogs: true, hideLearnButton: true, @@ -33,6 +34,7 @@ describe('disableLogs', () => { it('disableLogs false returns useful function', async () => { const config = { + isUnitTest: true, hideScanFrequencyButton: true, hideLearnButton: true, accessories: [ diff --git a/test/learnAccessories.test.js b/test/learnAccessories.test.js index 5a5d91bf..61083994 100644 --- a/test/learnAccessories.test.js +++ b/test/learnAccessories.test.js @@ -7,7 +7,7 @@ describe('learnAccessories', () => { // // Empty Config it('empty config results in 2 accessories', async () => { - const config = { disableLogs: true }; + const config = { disableLogs: true, isUnitTest: true }; const accessories = await getAccessories(config); expect(accessories.length).to.equal(2); @@ -15,7 +15,7 @@ describe('learnAccessories', () => { // hideScanFrequencyButton it('hideScanFrequencyButton set to true in config results in 1 accessory', async () => { - const config = { disableLogs: true, hideScanFrequencyButton: true }; + const config = { disableLogs: true, hideScanFrequencyButton: true, isUnitTest: true }; const accessories = await getAccessories(config); expect(accessories.length).to.equal(1); @@ -23,7 +23,7 @@ describe('learnAccessories', () => { // hideLearnButton it('hideLearnButton set to true in config results in 1 accessory', async () => { - const config = { disableLogs: true, hideLearnButton: true }; + const config = { disableLogs: true, hideLearnButton: true, isUnitTest: true }; const accessories = await getAccessories(config); expect(accessories.length).to.equal(1); diff --git a/test/light.test.js b/test/light.test.js index 1eeadec6..0d14f00b 100644 --- a/test/light.test.js +++ b/test/light.test.js @@ -24,6 +24,12 @@ const data = { hue40: 'HUE40', } +const defaultConfig = { + data, + isUnitTest: true, + persistState: false +}; + describe('lightAccessory', () => { // Light Turn On @@ -31,9 +37,8 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - persistState: false, onDelay: 0.1 } @@ -67,9 +72,8 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, - host: device.host.address, - persistState: false + ...defaultConfig, + host: device.host.address } const lightAccessory = new Light(null, config, 'FakeServiceManager') @@ -99,11 +103,10 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, onDelay: 0.1, useLastKnownBrightness: true, - host: device.host.address, - persistState: false + host: device.host.address } const lightAccessory = new Light(null, config, 'FakeServiceManager') @@ -122,7 +125,7 @@ describe('lightAccessory', () => { let hasSentCodes = device.hasSentCodes([ 'ON', 'BRIGHTNESS20' ]); expect(hasSentCodes).to.equal(true); - // Check that only one code has been sent + // Check that 2 codes have been sent let sentHexCodeCount = device.getSentHexCodeCount(); expect(sentHexCodeCount).to.equal(2); @@ -134,7 +137,7 @@ describe('lightAccessory', () => { hasSentCodes = device.hasSentCodes(['OFF', 'ON', 'BRIGHTNESS20' ]); expect(hasSentCodes).to.equal(true); - // Check that only one code has been sent + // Check that 3 codes have been sent sentHexCodeCount = device.getSentHexCodeCount(); expect(sentHexCodeCount).to.equal(3); @@ -159,10 +162,9 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, onDelay: 0.1, - host: device.host.address, - persistState: false + host: device.host.address } const lightAccessory = new Light(null, config, 'FakeServiceManager') @@ -221,9 +223,8 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - persistState: false, enableAutoOff: true, onDuration: 1 } @@ -252,9 +253,8 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - persistState: false, enableAutoOn: true, offDuration: 1 } @@ -291,10 +291,9 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.1, - persistState: false + onDelay: 0.1 } const lightAccessory = new Light(null, config, 'FakeServiceManager') @@ -322,13 +321,10 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.1, - persistState: false + onDelay: 0.1 } - - const lightAccessory = new Light(null, config, 'FakeServiceManager') lightAccessory.serviceManager.setCharacteristic(Characteristic.Brightness, 32) @@ -355,10 +351,9 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.1, - persistState: false + onDelay: 0.1 } @@ -390,10 +385,9 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.1, - persistState: false + onDelay: 0.1 } @@ -423,13 +417,10 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.1, - persistState: false + onDelay: 0.1 } - - const lightAccessory = new Light(null, config, 'FakeServiceManager') lightAccessory.serviceManager.setCharacteristic(Characteristic.Hue, 32) @@ -456,13 +447,10 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.1, - persistState: false + onDelay: 0.1 } - - const lightAccessory = new Light(null, config, 'FakeServiceManager') lightAccessory.serviceManager.setCharacteristic(Characteristic.Hue, 36) @@ -491,13 +479,10 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - onDelay: 0.5, - persistState: false + onDelay: 0.5 } - - const lightAccessory = new Light(null, config, 'FakeServiceManager') lightAccessory.serviceManager.setCharacteristic(Characteristic.Brightness, 20) @@ -541,7 +526,7 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, name: 'Unit Test Light', persistState: true @@ -571,10 +556,9 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, - name: 'Unit Test Light', - persistState: false + name: 'Unit Test Light' } let lightAccessory @@ -593,18 +577,17 @@ describe('lightAccessory', () => { // Ensure the hex is resent after reload it('"resendHexAfterReload": true, "persistState": true', async () => { const { device } = setup(); - + const config = { - data, + ...defaultConfig, host: device.host.address, persistState: true, onDelay: 0.1, resendHexAfterReload: true, - resendDataAfterReloadDelay: 0.1, - isUnitTest: true + resendDataAfterReloadDelay: 0.1 } - let lightAccessory + let lightAccessory; // Turn On Light lightAccessory = new Light(null, config, 'FakeServiceManager') @@ -647,12 +630,11 @@ describe('lightAccessory', () => { const { device } = setup(); const config = { - data, + ...defaultConfig, host: device.host.address, persistState: true, resendHexAfterReload: false, - resendDataAfterReloadDelay: 0.1, - isUnitTest: true + resendDataAfterReloadDelay: 0.1 } let lightAccessory diff --git a/test/lock.test.js b/test/lock.test.js index c254bd65..3c3b76af 100644 --- a/test/lock.test.js +++ b/test/lock.test.js @@ -189,7 +189,8 @@ describe('lockAccessory', () => { expect(lockAccessory.state.lockTargetState).to.equal(Characteristic.LockTargetState.SECURED); // Delay to allow for `lockDuration` - await delayForDuration(0.2) + await delayForDuration(0.3) + expect(lockAccessory.state.lockTargetState).to.equal(Characteristic.LockTargetState.SECURED); expect(lockAccessory.state.lockCurrentState).to.equal(Characteristic.LockCurrentState.SECURED); diff --git a/test/windowCovering.test.js b/test/windowCovering.test.js index 39d34724..7bb5297f 100644 --- a/test/windowCovering.test.js +++ b/test/windowCovering.test.js @@ -114,6 +114,7 @@ describe('windowCoveringAccessory', () => { // Check value at 50% await delayForDuration(50 * durationPerPercent); + await delayForDuration(.1); expect(windowCoveringAccessory.state.currentPosition).to.equal(50); // Check hex code was sent @@ -155,6 +156,7 @@ describe('windowCoveringAccessory', () => { // Check value at 20% await delayForDuration(20 * durationPerPercent); + await delayForDuration(.1); expect(windowCoveringAccessory.state.currentPosition).to.equal(20); // Set blinds to 50% @@ -166,6 +168,7 @@ describe('windowCoveringAccessory', () => { // Check value at 50% await delayForDuration(50 * durationPerPercent); + await delayForDuration(.1); expect(windowCoveringAccessory.state.currentPosition).to.equal(50); // Check hex code was sent @@ -213,6 +216,7 @@ describe('windowCoveringAccessory', () => { // Check value at 90% await delayForDuration(90 * openDurationPerPercent); + await delayForDuration(.1); expect(windowCoveringAccessory.state.currentPosition).to.equal(90); // Set blinds to 60% @@ -224,6 +228,7 @@ describe('windowCoveringAccessory', () => { // Check value at 60% await delayForDuration(30 * closeDurationPerPercent); + await delayForDuration(.1); expect(windowCoveringAccessory.state.currentPosition).to.equal(60); // Check hex code was sent @@ -297,6 +302,8 @@ describe('windowCoveringAccessory', () => { await delayForDuration(windowCoveringAccessory.config.initialDelay); expect(windowCoveringAccessory.state.currentPosition).to.equal(100); + await delayForDuration(.1); + // Check hex code was sent const hasSentCodes = device.hasSentCodes([ 'OPEN_COMPLETELY', 'STOP' ]); expect(hasSentCodes).to.equal(true); @@ -334,6 +341,8 @@ describe('windowCoveringAccessory', () => { await delayForDuration(windowCoveringAccessory.config.initialDelay); expect(windowCoveringAccessory.state.currentPosition).to.equal(100); + await delayForDuration(.1); + // Check hex code was sent let hasSentCodes = device.hasSentCodes([ 'OPEN_COMPLETELY', 'STOP' ]); expect(hasSentCodes).to.equal(true); @@ -349,6 +358,8 @@ describe('windowCoveringAccessory', () => { await delayForDuration(windowCoveringAccessory.config.initialDelay); expect(windowCoveringAccessory.state.currentPosition).to.equal(0); + await delayForDuration(.1); + // Check hex code was sent hasSentCodes = device.hasSentCodes([ 'OPEN_COMPLETELY', 'STOP', 'CLOSE_COMPLETELY' ]); expect(hasSentCodes).to.equal(true);