UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

273 lines 11.8 kB
import { KeypadMode, UserIDStatus } from "@zwave-js/cc"; import { UserCodeCCAdminCodeGet, UserCodeCCAdminCodeReport, UserCodeCCAdminCodeSet, UserCodeCCCapabilitiesGet, UserCodeCCCapabilitiesReport, UserCodeCCExtendedUserCodeSet, UserCodeCCGet, UserCodeCCKeypadModeGet, UserCodeCCKeypadModeReport, UserCodeCCKeypadModeSet, UserCodeCCReport, UserCodeCCSet, UserCodeCCUserCodeChecksumGet, UserCodeCCUserCodeChecksumReport, UserCodeCCUsersNumberGet, UserCodeCCUsersNumberReport, } from "@zwave-js/cc/UserCodeCC"; import { CRC16_CCITT, CommandClasses } from "@zwave-js/core"; import { Bytes } from "@zwave-js/shared"; export const defaultCapabilities = { numUsers: 1, supportedASCIIChars: "0123456789", supportsAdminCode: true, supportsAdminCodeDeactivation: true, supportsUserCodeChecksum: true, supportedKeypadModes: [KeypadMode.Normal], supportedUserIDStatuses: [ UserIDStatus.Available, UserIDStatus.Enabled, UserIDStatus.Disabled, ], }; const STATE_KEY_PREFIX = "UserCode_"; const StateKeys = { userCode: (userId) => `${STATE_KEY_PREFIX}userCode_${userId}`, userIdStatus: (userId) => `${STATE_KEY_PREFIX}userIdStatus_${userId}`, adminCode: `${STATE_KEY_PREFIX}adminCode`, keypadMode: `${STATE_KEY_PREFIX}keypadMode`, }; const respondToUsersNumberGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCUsersNumberGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; const cc = new UserCodeCCUsersNumberReport({ nodeId: controller.ownNodeId, supportedUsers: capabilities.numUsers ?? 1, }); return { action: "sendCC", cc }; } }, }; const respondToUserGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; const userId = receivedCC.userId; let cc; if (capabilities.numUsers >= userId) { cc = new UserCodeCCReport({ nodeId: controller.ownNodeId, userId, userIdStatus: (self.state.get(StateKeys.userIdStatus(userId)) ?? UserIDStatus.Available), userCode: self.state.get(StateKeys.userCode(userId)), }); } else { cc = new UserCodeCCReport({ nodeId: controller.ownNodeId, userId, userIdStatus: UserIDStatus.StatusNotAvailable, }); } return { action: "sendCC", cc }; } }, }; const respondToUserCodeSet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCSet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; const userId = receivedCC.userId; const userIdStatus = receivedCC.userIdStatus; if (capabilities.numUsers >= userId) { self.state.set(StateKeys.userIdStatus(userId), userIdStatus); const code = userIdStatus !== UserIDStatus.Available && userIdStatus !== UserIDStatus.StatusNotAvailable ? receivedCC.userCode : undefined; self.state.set(StateKeys.userCode(userId), code); return { action: "ok" }; } return { action: "fail" }; } }, }; const respondToExtendedUserCodeSet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCExtendedUserCodeSet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; // Process each user code in the request for (const userCodeData of receivedCC.userCodes) { const userId = userCodeData.userId; const userIdStatus = userCodeData.userIdStatus; // Skip if userId is 0 and we're clearing all codes if (userId === 0 && userIdStatus === UserIDStatus.Available) { // Clear all user codes const numUsers = capabilities.numUsers ?? 0; for (let i = 1; i <= numUsers; i++) { self.state.set(StateKeys.userIdStatus(i), UserIDStatus.Available); self.state.set(StateKeys.userCode(i), undefined); } continue; } if (capabilities.numUsers != undefined && capabilities.numUsers >= userId) { self.state.set(StateKeys.userIdStatus(userId), userIdStatus); const code = userIdStatus !== UserIDStatus.Available // @ts-expect-error Just making sure that we're not accidentally // passing the wrong status && userIdStatus !== UserIDStatus.StatusNotAvailable ? userCodeData.userCode : undefined; self.state.set(StateKeys.userCode(userId), code); } else { return { action: "fail" }; } } return { action: "ok" }; } }, }; const respondToUserCodeCapabilitiesGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCCapabilitiesGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; const cc = new UserCodeCCCapabilitiesReport({ nodeId: controller.ownNodeId, supportsAdminCode: capabilities.supportsAdminCode, supportsAdminCodeDeactivation: capabilities .supportsAdminCodeDeactivation, supportsUserCodeChecksum: capabilities .supportsUserCodeChecksum, supportsMultipleUserCodeReport: false, supportsMultipleUserCodeSet: false, supportedUserIDStatuses: capabilities.supportedUserIDStatuses, supportedKeypadModes: capabilities.supportedKeypadModes, supportedASCIIChars: capabilities.supportedASCIIChars, }); return { action: "sendCC", cc }; } }, }; const respondToUserCodeKeypadModeGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCKeypadModeGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; const cc = new UserCodeCCKeypadModeReport({ nodeId: controller.ownNodeId, keypadMode: (self.state.get(StateKeys.keypadMode) ?? capabilities.supportedKeypadModes?.[0] ?? KeypadMode.Normal), }); return { action: "sendCC", cc }; } }, }; const respondToUserCodeKeypadModeSet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCKeypadModeSet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; if (capabilities.supportedKeypadModes?.includes(receivedCC.keypadMode)) { self.state.set(StateKeys.keypadMode, receivedCC.keypadMode); return { action: "ok" }; } return { action: "fail" }; } }, }; const respondToUserCodeAdminCodeSet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCAdminCodeSet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; const adminCode = receivedCC.adminCode; if (capabilities.supportsAdminCode) { if (adminCode.length > 0 || capabilities.supportsAdminCodeDeactivation) { self.state.set(StateKeys.adminCode, receivedCC.adminCode); return { action: "ok" }; } } return { action: "fail" }; } }, }; const respondToUserCodeAdminCodeGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCAdminCodeGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; let adminCode; if (capabilities.supportsAdminCode) { adminCode = self.state.get(StateKeys.adminCode); } const cc = new UserCodeCCAdminCodeReport({ nodeId: controller.ownNodeId, adminCode: adminCode ?? "", }); return { action: "sendCC", cc }; } }, }; const respondToUserCodeUserCodeChecksumGet = { handleCC(controller, self, receivedCC) { if (receivedCC instanceof UserCodeCCUserCodeChecksumGet) { const capabilities = { ...defaultCapabilities, ...self.getCCCapabilities(CommandClasses["User Code"], receivedCC.endpointIndex), }; if (capabilities.supportsUserCodeChecksum) { let data = new Bytes(); for (let i = 1; i <= capabilities.numUsers; i++) { const status = self.state.get(StateKeys.userIdStatus(i)); let code = (self.state.get(StateKeys.userCode(i)) ?? ""); if (status === undefined || status === UserIDStatus.Available || code.length === 0) { continue; } const tmp = new Bytes(3 + code.length); tmp.writeUInt16BE(i, 0); tmp[2] = status; if (typeof code === "string") { code = Bytes.from(code, "ascii"); } tmp.set(code, 3); data = Bytes.concat([data, tmp]); } const checksum = data.length > 0 ? CRC16_CCITT(data) : 0x0000; const cc = new UserCodeCCUserCodeChecksumReport({ nodeId: controller.ownNodeId, userCodeChecksum: checksum, }); return { action: "sendCC", cc }; } return { action: "stop" }; } }, }; export const UserCodeCCBehaviors = [ respondToUsersNumberGet, respondToUserGet, respondToUserCodeSet, respondToExtendedUserCodeSet, respondToUserCodeCapabilitiesGet, respondToUserCodeKeypadModeGet, respondToUserCodeKeypadModeSet, respondToUserCodeAdminCodeGet, respondToUserCodeAdminCodeSet, respondToUserCodeUserCodeChecksumGet, ]; //# sourceMappingURL=UserCode.js.map