zwave-js
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
80 lines • 3.53 kB
JavaScript
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