UNPKG

iobroker.zwave2

Version:
614 lines (613 loc) 20.2 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var objects_exports = {}; __export(objects_exports, { DEVICE_ID_BROADCAST: () => DEVICE_ID_BROADCAST, ccNameToChannelIdFragment: () => ccNameToChannelIdFragment, computeChannelId: () => computeChannelId, computeNotificationId: () => computeNotificationId, computeStateId: () => computeStateId, computeVirtualChannelId: () => computeVirtualChannelId, computeVirtualStateId: () => computeVirtualStateId, ensureBroadcastNode: () => ensureBroadcastNode, extendCC: () => extendCC, extendMetadata: () => extendMetadata, extendNode: () => extendNode, extendNotificationValue: () => extendNotificationValue, extendNotification_NotificationCC: () => extendNotification_NotificationCC, extendValue: () => extendValue, extendVirtualMetadata: () => extendVirtualMetadata, extendVirtualNodeCC: () => extendVirtualNodeCC, nameToStateId: () => nameToStateId, nodeStatusToStatusState: () => nodeStatusToStatusState, removeNode: () => removeNode, removeValue: () => removeValue, setControllerStatistics: () => setControllerStatistics, setNodeReady: () => setNodeReady, setNodeStatistics: () => setNodeStatistics, setNodeStatus: () => setNodeStatus, setRFRegionState: () => setRFRegionState }); module.exports = __toCommonJS(objects_exports); var import_core = require("@zwave-js/core"); var import_objects = require("alcalzone-shared/objects"); var import_strings = require("alcalzone-shared/strings"); var import_typeguards = require("alcalzone-shared/typeguards"); var import_zwave_js = require("zwave-js"); var import_Node = require("zwave-js/Node"); var import_global = require("./global"); var import_shared = require("./shared"); function nodeStatusToStatusState(status) { switch (status) { case import_Node.NodeStatus.Awake: return "awake"; case import_Node.NodeStatus.Asleep: return "asleep"; case import_Node.NodeStatus.Alive: return "alive"; case import_Node.NodeStatus.Dead: return "dead"; case import_Node.NodeStatus.Unknown: return "unknown"; } } function safeValue(value) { if (value == void 0) return null; if (Buffer.isBuffer(value)) { return (0, import_shared.buffer2hex)(value); } else if ((0, import_typeguards.isArray)(value) || (0, import_typeguards.isObject)(value)) { return JSON.stringify(value); } return value; } const isCamelCasedSafeNameRegex = /^(?!.*[\-_]$)[a-z]([a-zA-Z0-9\-_]+)$/; const DEVICE_ID_BROADCAST = "Broadcast"; function nameToStateId(label) { if (isCamelCasedSafeNameRegex.test(label)) return label; let safeName = label; while (true) { let replaced = safeName; replaced = replaced.trim(); replaced = replaced.replace(/\s+/g, " "); replaced = replaced.replace(/[^a-zA-Z0-9\-_ ]+/g, "_"); replaced = replaced.replace(/_\s/g, " "); replaced = replaced.replace(/\s_/g, " "); replaced = replaced.replace(/^_\s*/, ""); replaced = replaced.replace(/\s*_$/, ""); if (safeName === replaced) break; safeName = replaced; } return camelCase(safeName); } function camelCase(str) { return str.split(" ").map( (substr, i) => i === 0 ? substr.toLowerCase() : substr[0].toUpperCase() + substr.slice(1).toLowerCase() ).join(""); } function ccNameToChannelIdFragment(ccName) { return ccName.replace(/[\s]+/g, "_"); } function computeChannelIdInternal(prefix, ccName) { return `${prefix}.${ccNameToChannelIdFragment(ccName)}`; } function computeChannelId(nodeId, ccName) { return computeChannelIdInternal((0, import_shared.computeDeviceId)(nodeId), ccName); } function computeVirtualChannelId(prefix, ccName) { return computeChannelIdInternal(prefix, ccName); } function computeStateIdInternal(prefix, args) { var _a, _b; return [ prefix, ccNameToChannelIdFragment(args.commandClassName), [ ((_a = args.propertyName) == null ? void 0 : _a.trim()) && nameToStateId(args.propertyName), args.endpoint && (0, import_strings.padStart)(args.endpoint.toString(), 3, "0"), ((_b = args.propertyKeyName) == null ? void 0 : _b.trim()) && nameToStateId(args.propertyKeyName) ].filter((s) => !!s).join("_") ].join("."); } function computeStateId(nodeId, args) { return computeStateIdInternal((0, import_shared.computeDeviceId)(nodeId), args); } function computeVirtualStateId(prefix, args) { return computeStateIdInternal(prefix, args); } const secClassDefinitions = [ [import_core.SecurityClass.S2_AccessControl, import_core.CommandClasses["Security 2"]], [import_core.SecurityClass.S2_Authenticated, import_core.CommandClasses["Security 2"]], [import_core.SecurityClass.S2_Unauthenticated, import_core.CommandClasses["Security 2"]], [import_core.SecurityClass.S0_Legacy, import_core.CommandClasses["Security"]] ]; function securityClassesToRecord(node) { const ret = {}; for (const [secClass, cc] of secClassDefinitions) { if (!node.supportsCC(cc)) continue; ret[import_core.SecurityClass[secClass]] = node.hasSecurityClass(secClass) === true; } return ret; } function nodeToNative(node) { return { id: node.id, isControllerNode: node.isControllerNode, manufacturerId: node.manufacturerId, productType: node.productType, productId: node.productId, ...node.deviceClass && { type: { basic: node.deviceClass.basic.label, generic: node.deviceClass.generic.label, ...node.deviceClass.specific.key !== 0 ? { specific: node.deviceClass.specific.label } : {} } }, endpointIndizes: node.getEndpointIndizes(), securityClasses: securityClassesToRecord(node), secure: node.isSecure, canSleep: node.canSleep, supportsFirmwareUpdate: node.supportsCC( import_core.CommandClasses["Firmware Update Meta Data"] ) }; } function nodeToCommon(node) { return { name: node.deviceConfig ? `${node.deviceConfig.manufacturer} ${node.deviceConfig.label}` : `Node ${(0, import_strings.padStart)(node.id.toString(), 3, "0")}` }; } const fallbackNodeNameRegex = /^Node \d+$/; async function extendNode(node) { const deviceId = (0, import_shared.computeDeviceId)(node.id); const originalObject = import_global.Global.adapter.oObjects[`${import_global.Global.adapter.namespace}.${deviceId}`]; const nodeCommon = nodeToCommon(node); let newName = originalObject == null ? void 0 : originalObject.common.name; newName = newName && !fallbackNodeNameRegex.test(newName) ? newName : nodeCommon.name; const desiredObject = { type: "device", common: { ...nodeCommon, ...originalObject == null ? void 0 : originalObject.common, name: newName }, native: nodeToNative(node) }; await setOrExtendObject(deviceId, desiredObject, originalObject); } async function ensureBroadcastNode() { const deviceId = DEVICE_ID_BROADCAST; const originalObject = import_global.Global.adapter.oObjects[`${import_global.Global.adapter.namespace}.${deviceId}`]; const desiredObject = { type: "device", common: { name: (originalObject == null ? void 0 : originalObject.common.name) || "Broadcast" }, native: { broadcast: true } }; await setOrExtendObject(deviceId, desiredObject, originalObject); } async function removeNode(nodeId) { const deviceId = `${import_global.Global.adapter.namespace}.${(0, import_shared.computeDeviceId)(nodeId)}`; try { await import_global.Global.adapter.delForeignObjectAsync(deviceId); } catch (e) { } const existingObjs = { ...await import_global.Global.$$(`${deviceId}.*`, { type: "channel" }), ...await import_global.Global.$$(`${deviceId}.*`, { type: "state" }) }; for (const [id, obj] of (0, import_objects.entries)(existingObjs)) { if (obj.type === "state") { try { await import_global.Global.adapter.delForeignStateAsync(id); } catch (e) { } } try { await import_global.Global.adapter.delForeignObjectAsync(id); } catch (e) { } } } async function extendCCInternal(node, channelId, cc, ccName) { const common = { name: ccName }; const native = { cc, version: node.getCCVersion(cc) }; const originalObject = import_global.Global.adapter.oObjects[`${import_global.Global.adapter.namespace}.${channelId}`]; if (originalObject == void 0) { await import_global.Global.adapter.setObjectAsync(channelId, { type: "channel", common, native }); } else if (JSON.stringify(common) !== JSON.stringify(originalObject.common) || JSON.stringify(native) !== JSON.stringify(originalObject.native)) { await import_global.Global.adapter.extendObjectAsync(channelId, { common, native }); } } async function extendCC(node, cc, ccName) { await extendCCInternal(node, computeChannelId(node.id, ccName), cc, ccName); } async function extendVirtualNodeCC(node, deviceId, cc, ccName) { await extendCCInternal( node, computeVirtualChannelId(deviceId, ccName), cc, ccName ); } async function extendValue(node, args, fromCache = false) { const stateId = computeStateId(node.id, args); await extendMetadata(node, args); try { const state = { val: safeValue(args.newValue), ack: true }; if (fromCache) { state.q = 64; } if (fromCache) { await import_global.Global.adapter.setStateChangedAsync(stateId, state); } else { await import_global.Global.adapter.setStateAsync(stateId, state); } } catch (e) { import_global.Global.adapter.log.error( `Cannot set state "${stateId}" in ioBroker: ${(0, import_shared.getErrorMessage)(e)}` ); } } async function extendNotificationValue(node, args) { const stateId = computeStateId(node.id, args); await extendMetadata(node, args); try { const state = { val: safeValue(args.value), ack: true, expire: 1 }; await import_global.Global.adapter.setStateAsync(stateId, state); } catch (e) { import_global.Global.adapter.log.error( `Cannot set state "${stateId}" in ioBroker: ${(0, import_shared.getErrorMessage)(e)}` ); } } async function extendMetadata(node, args) { const stateId = computeStateId(node.id, args); const metadata = "metadata" in args && args.metadata || node.getValueMetadata(args); await extendMetadataInternal(stateId, metadata, args, { nodeId: node.id }); } async function extendVirtualMetadata(node, deviceId, { metadata, ccVersion, ...valueId }) { const stateId = computeVirtualStateId(deviceId, valueId); await extendMetadataInternal( stateId, metadata, valueId, node.id === import_core.NODE_ID_BROADCAST ? { broadcast: true } : { nodeIds: node.physicalNodes.map((n) => n.id) } ); } async function extendMetadataInternal(stateId, metadata, valueId, nativePart = {}) { const stateType = valueTypeToIOBrokerType(metadata.type); const originalObject = import_global.Global.adapter.oObjects[`${import_global.Global.adapter.namespace}.${stateId}`]; const newStateName = import_global.Global.adapter.config.preserveStateNames && (originalObject == null ? void 0 : originalObject.common.name) ? originalObject.common.name : metadata.label ? `${metadata.label}${valueId.endpoint ? ` (Endpoint ${valueId.endpoint})` : ""}` : stateId; const stateRole = (originalObject == null ? void 0 : originalObject.common.role) || metadataToStateRole(stateType, metadata); const objectDefinition = { type: "state", common: { role: stateRole, read: metadata.readable, write: metadata.writeable, name: newStateName, desc: metadata.description, type: stateType, min: metadata.min, max: metadata.max, def: metadata.default, unit: metadata.unit, states: metadata.states }, native: { ...nativePart, valueId: { commandClass: valueId.commandClass, endpoint: valueId.endpoint, property: valueId.property, propertyKey: valueId.propertyKey }, steps: metadata.steps } }; await setOrExtendObject(stateId, objectDefinition, originalObject); } async function removeValue(nodeId, args) { const stateId = computeStateId(nodeId, args); try { await import_global.Global.adapter.delObjectAsync(stateId); } catch { } } function valueTypeToIOBrokerType(valueType) { switch (valueType) { case "number": case "boolean": case "string": return valueType; case "any": return "mixed"; default: if (valueType == null ? void 0 : valueType.endsWith("[]")) return "array"; } return "mixed"; } function metadataToStateRole(stateType, meta) { if (stateType === "number") { return meta.writeable ? "level" : "value"; } else if (stateType === "boolean") { return meta.readable && !meta.writeable ? "indicator" : "switch"; } return "state"; } async function setNodeStatus(nodeId, status) { const stateId = `${(0, import_shared.computeDeviceId)(nodeId)}.status`; await import_global.Global.adapter.setObjectNotExistsAsync(stateId, { type: "state", common: { name: "Node status", role: "indicator", type: "string", read: true, write: false }, native: {} }); await import_global.Global.adapter.setStateAsync(stateId, status, true); } async function setNodeReady(nodeId, ready) { const stateId = `${(0, import_shared.computeDeviceId)(nodeId)}.ready`; await import_global.Global.adapter.setObjectNotExistsAsync(stateId, { type: "state", common: { name: "Ready to use", role: "indicator", type: "boolean", read: true, write: false, def: false }, native: {} }); await import_global.Global.adapter.setStateAsync(stateId, ready, true); } async function setControllerStatistics(statistics) { const stateId = `info.statistics`; await import_global.Global.adapter.setObjectNotExistsAsync(stateId, { type: "state", common: { name: "Communication statistics", role: "indicator", type: "object", read: true, write: false }, native: {} }); await import_global.Global.adapter.setStateAsync( stateId, statistics ? JSON.stringify(statistics) : null, true ); } async function setNodeStatistics(nodeId, statistics) { const channelId = `${(0, import_shared.computeDeviceId)(nodeId)}.info`; const stateId = `${channelId}.statistics`; await import_global.Global.adapter.setObjectNotExistsAsync(channelId, { type: "channel", common: { name: "Information" }, native: {} }); await import_global.Global.adapter.setObjectNotExistsAsync(stateId, { type: "state", common: { name: "Transmission statistics", role: "indicator", type: "object", read: true, write: false }, native: {} }); await import_global.Global.adapter.setStateAsync( stateId, statistics ? JSON.stringify(statistics) : null, true ); } function computeNotificationId(nodeId, notificationLabel, eventLabel, property) { return [ (0, import_shared.computeDeviceId)(nodeId), ccNameToChannelIdFragment("Notification"), [ nameToStateId(notificationLabel), nameToStateId(eventLabel), property && nameToStateId(property) ].filter((s) => !!s).join("_") ].join("."); } async function setOrExtendObject(id, definition, original) { if (original == void 0) { await import_global.Global.adapter.setObjectAsync(id, definition); } else if (JSON.stringify(definition.common) !== JSON.stringify(original.common) || JSON.stringify(definition.native) !== JSON.stringify(original.native)) { await import_global.Global.adapter.extendObjectAsync(id, definition); } } async function setNotificationValue(nodeId, notificationLabel, eventLabel, property, value = true) { var _a; const stateId = computeNotificationId( nodeId, notificationLabel, eventLabel, property ); const originalObject = import_global.Global.adapter.oObjects[`${import_global.Global.adapter.namespace}.${stateId}`]; const newStateName = import_global.Global.adapter.config.preserveStateNames && (originalObject == null ? void 0 : originalObject.common.name) ? originalObject.common.name : `${notificationLabel}: ${eventLabel}${!!property ? ` (${property})` : ""}`; const objectDefinition = { type: "state", common: typeof value === "boolean" ? { role: "indicator", read: true, write: false, name: newStateName, type: "boolean" } : typeof value === "number" ? { role: "value", read: true, write: false, name: newStateName, type: "number" } : value instanceof import_core.Duration ? { role: "value.interval", read: true, write: false, name: newStateName, type: "number", unit: "seconds" } : { role: "text", read: true, write: false, name: newStateName, type: "string" }, native: { nodeId, notificationEvent: true } }; let val; if (value instanceof import_core.Duration) { val = value.toMilliseconds(); if (val == void 0) val = "unknown"; else val /= 1e3; } else { val = value; } await setOrExtendObject(stateId, objectDefinition, originalObject); await import_global.Global.adapter.setStateAsync( stateId, { val, expire: (_a = import_global.Global.adapter.config.notificationEventValidity) != null ? _a : 1e3 }, true ); } async function extendNotification_NotificationCC(node, args) { const { label, eventLabel, parameters } = args; if (parameters == void 0) { await setNotificationValue(node.id, label, eventLabel, void 0, true); } else if (Buffer.isBuffer(parameters)) { await setNotificationValue( node.id, label, eventLabel, void 0, parameters.toString("hex") ); } else if (parameters instanceof import_core.Duration) { await setNotificationValue( node.id, label, eventLabel, void 0, parameters ); } else { for (const [key, value] of Object.entries(parameters)) { await setNotificationValue(node.id, label, eventLabel, key, value); } } } async function setRFRegionState(rfRegion) { const stateId = `info.rfRegion`; await import_global.Global.adapter.setObjectNotExistsAsync(stateId, { type: "state", common: { name: "RF Region", role: "info.region", type: "number", read: true, write: false, states: (0, import_core.enumValuesToMetadataStates)(import_zwave_js.RFRegion) }, native: {} }); await import_global.Global.adapter.setStateAsync(stateId, rfRegion != null ? rfRegion : null, true); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { DEVICE_ID_BROADCAST, ccNameToChannelIdFragment, computeChannelId, computeNotificationId, computeStateId, computeVirtualChannelId, computeVirtualStateId, ensureBroadcastNode, extendCC, extendMetadata, extendNode, extendNotificationValue, extendNotification_NotificationCC, extendValue, extendVirtualMetadata, extendVirtualNodeCC, nameToStateId, nodeStatusToStatusState, removeNode, removeValue, setControllerStatistics, setNodeReady, setNodeStatistics, setNodeStatus, setRFRegionState }); //# sourceMappingURL=objects.js.map