UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

91 lines (90 loc) 4.52 kB
import { CentralSceneCCValues, CentralSceneKeys, } from "@zwave-js/cc"; import { setTimer, stringify } from "@zwave-js/shared"; export function getDefaultCentralSceneHandlerStore() { return { keyHeldDownContext: undefined, lastSequenceNumber: undefined, forcedKeyUp: false, }; } /** Handles the receipt of a ThermostatModeCC Set */ export function handleCentralSceneNotification(ctx, node, command, store) { // Did we already receive this command? if (command.sequenceNumber === store.lastSequenceNumber) { return; } else { store.lastSequenceNumber = command.sequenceNumber; } /* If the Slow Refresh field is false: - A new Key Held Down notification MUST be sent every 200ms until the key is released. - The Sequence Number field MUST be updated at each notification transmission. - If not receiving a new Key Held Down notification within 400ms, a controlling node SHOULD use an adaptive timeout approach as described in 4.17.1: A controller SHOULD apply an adaptive approach based on the reception of the Key Released Notification. Initially, the controller SHOULD time out if not receiving any Key Held Down Notification refresh after 400ms and consider this to be a Key Up Notification. If, however, the controller subsequently receives a Key Released Notification, the controller SHOULD consider the sending node to be operating with the Slow Refresh capability enabled. If the Slow Refresh field is true: - A new Key Held Down notification MUST be sent every 55 seconds until the key is released. - The Sequence Number field MUST be updated at each notification refresh. - If not receiving a new Key Held Down notification within 60 seconds after the most recent Key Held Down notification, a receiving node MUST respond as if it received a Key Release notification. */ const setSceneValue = (sceneNumber, key) => { const valueId = CentralSceneCCValues.scene(sceneNumber).id; node.valueDB.setValue(valueId, key, { stateful: false }); }; const forceKeyUp = () => { store.forcedKeyUp = true; // force key up event setSceneValue(store.keyHeldDownContext.sceneNumber, CentralSceneKeys.KeyReleased); // clear old timer store.keyHeldDownContext?.timeout?.clear(); // clear the key down context store.keyHeldDownContext = undefined; }; if (store.keyHeldDownContext && store.keyHeldDownContext.sceneNumber !== command.sceneNumber) { // The user pressed another button, force release forceKeyUp(); } const slowRefreshValueId = CentralSceneCCValues.slowRefresh.endpoint(command.endpointIndex); if (command.keyAttribute === CentralSceneKeys.KeyHeldDown) { // Set or refresh timer to force a release of the key store.forcedKeyUp = false; store.keyHeldDownContext?.timeout?.clear(); // If the node does not advertise support for the slow refresh capability, we might still be dealing with a // slow refresh node. We use the stored value for fallback behavior const slowRefresh = command.slowRefresh // Prefer the stored value, even if the command claims slowRefresh == false || node.valueDB.getValue(slowRefreshValueId); store.keyHeldDownContext = { sceneNumber: command.sceneNumber, // Unref'ing long running timers allows the process to exit mid-timeout timeout: setTimer(forceKeyUp, slowRefresh ? 60000 : 400).unref(), }; } else if (command.keyAttribute === CentralSceneKeys.KeyReleased) { // Stop the release timer if (store.keyHeldDownContext) { store.keyHeldDownContext.timeout.clear(); store.keyHeldDownContext = undefined; } else if (store.forcedKeyUp) { // If we timed out and the controller subsequently receives a Key Released Notification, // we SHOULD consider the sending node to be operating with the Slow Refresh capability enabled. node.valueDB.setValue(slowRefreshValueId, true); // Do not raise the duplicate event return; } } setSceneValue(command.sceneNumber, command.keyAttribute); ctx.logNode(node.id, { message: `received CentralScene notification ${stringify(command)}`, direction: "inbound", }); } //# sourceMappingURL=CentralSceneCC.js.map