UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

80 lines 3.53 kB
import { MessagePriority, normalizeValueID, valueEquals, } from "@zwave-js/core"; import { ObjectKeyMap, setTimer } from "@zwave-js/shared"; import { EndpointsMixin } from "./50_Endpoints.js"; export class SchedulePollMixin extends EndpointsMixin { constructor(nodeId, driver, endpointIndex, deviceClass, supportedCCs, valueDB) { super(nodeId, driver, endpointIndex, deviceClass, supportedCCs, valueDB); // Avoid verifying a value change for which we recently received an update for (const event of ["value updated", "value removed"]) { this.valueDB.on(event, (args) => { // Value updates caused by the driver should never cancel a scheduled poll if ("source" in args && args.source === "driver") return; if (this.cancelScheduledPoll(args, args.newValue)) { this.driver.controllerLog.logNode(this.id, "Scheduled poll canceled because expected value was received", "verbose"); } }); } } /** * All polls that are currently scheduled for this node */ _scheduledPolls = new ObjectKeyMap(); hasScheduledPolls() { return this._scheduledPolls.size > 0; } schedulePoll(valueId, options = {}) { const { timeoutMs = this.driver.options.timeouts.refreshValue, expectedValue, } = options; // Avoid false positives or false negatives due to a mis-formatted value ID valueId = normalizeValueID(valueId); // Try to retrieve the corresponding CC API const endpointInstance = this.getEndpoint(valueId.endpoint || 0); if (!endpointInstance) return false; const api = endpointInstance.commandClasses[valueId.commandClass].withOptions({ // We do not want to delay more important communication by polling, so give it // the lowest priority and don't retry unless overwritten by the options maxSendAttempts: 1, priority: MessagePriority.Poll, }); // Check if the pollValue method is implemented if (!api.pollValue) return false; // make sure there is only one timeout instance per poll this.cancelScheduledPoll(valueId); const timeout = setTimer(async () => { // clean up after the timeout this.cancelScheduledPoll(valueId); try { await api.pollValue.call(api, valueId); } catch { /* ignore */ } }, timeoutMs).unref(); this._scheduledPolls.set(valueId, { timeout, expectedValue }); return true; } cancelScheduledPoll(valueId, actualValue) { // Avoid false positives or false negatives due to a mis-formatted value ID valueId = normalizeValueID(valueId); const poll = this._scheduledPolls.get(valueId); if (!poll) return false; if (actualValue !== undefined && poll.expectedValue !== undefined && !valueEquals(poll.expectedValue, actualValue)) { return false; } poll.timeout.clear(); this._scheduledPolls.delete(valueId); return true; } cancelAllScheduledPolls() { // Remove queued polls that would interfere with the interview for (const valueId of this._scheduledPolls.keys()) { this.cancelScheduledPoll(valueId); } } } //# sourceMappingURL=60_ScheduledPoll.js.map