@willieee802/zigbee-herdsman 0.48.3 → 0.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/copilot-instructions.md +689 -0
- package/.github/dependabot.yml +22 -0
- package/.github/prompts/copilot-instructions-blueprint-generator.prompt.md +294 -0
- package/.github/prompts/create-agentsmd.prompt.md +249 -0
- package/.github/prompts/create-specification.prompt.md +127 -0
- package/.github/prompts/review-and-refactor.prompt.md +15 -0
- package/.github/prompts/update-specification.prompt.md +127 -0
- package/.github/workflows/ci.yml +70 -0
- package/.github/workflows/release-please.yml +18 -0
- package/.github/workflows/stale.yml +20 -0
- package/.github/workflows/typedoc.yaml +47 -0
- package/.release-please-manifest.json +2 -2
- package/.vscode/extensions.json +3 -0
- package/.vscode/settings.json +11 -0
- package/AGENTS.md +441 -0
- package/CHANGELOG.md +1283 -0
- package/README.md +1 -1
- package/biome.json +103 -0
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/adapterDiscovery.d.ts.map +1 -0
- package/dist/adapter/const.d.ts.map +1 -0
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/endpoints.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/tokensManager.d.ts.map +1 -1
- package/dist/adapter/ember/ezsp/ezsp.d.ts.map +1 -1
- package/dist/adapter/ember/utils/initters.d.ts.map +1 -1
- package/dist/adapter/events.d.ts.map +1 -1
- package/dist/adapter/ezsp/adapter/backup.d.ts.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/index.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/multicast.d.ts.map +1 -1
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/endpoints.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/manager.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
- package/dist/adapter/z-stack/models/startup-options.d.ts.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -0
- package/dist/adapter/zboss/driver.d.ts.map +1 -0
- package/dist/adapter/zboss/frame.d.ts.map +1 -0
- package/dist/adapter/zboss/frame.js +200 -0
- package/dist/adapter/zboss/frame.js.map +1 -0
- package/dist/adapter/zboss/uart.d.ts.map +1 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.js +70 -62
- package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
- package/dist/adapter/zigate/driver/ziGateObject.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
- package/dist/adapter/zoh/adapter/zohAdapter.d.ts.map +1 -0
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/controller/controller.js +524 -350
- package/dist/controller/controller.js.map +1 -1
- package/dist/controller/database.d.ts.map +1 -1
- package/dist/controller/events.d.ts.map +1 -1
- package/dist/controller/events.js +0 -110
- package/dist/controller/events.js.map +1 -1
- package/dist/controller/greenPower.d.ts.map +1 -1
- package/dist/controller/greenPower.js +330 -121
- package/dist/controller/greenPower.js.map +1 -1
- package/dist/controller/helpers/index.d.ts.map +1 -1
- package/dist/controller/helpers/ota.d.ts.map +1 -0
- package/dist/controller/helpers/ota.js +467 -0
- package/dist/controller/helpers/ota.js.map +1 -0
- package/dist/controller/helpers/request.d.ts.map +1 -1
- package/dist/controller/helpers/requestQueue.d.ts.map +1 -1
- package/dist/controller/helpers/zclFrameConverter.d.ts.map +1 -1
- package/dist/controller/helpers/zclFrameConverter.js +36 -22
- package/dist/controller/helpers/zclFrameConverter.js.map +1 -1
- package/dist/controller/index.d.ts.map +1 -1
- package/dist/controller/model/device.d.ts.map +1 -1
- package/dist/controller/model/device.js +1052 -402
- package/dist/controller/model/device.js.map +1 -1
- package/dist/controller/model/endpoint.d.ts.map +1 -1
- package/dist/controller/model/endpoint.js +447 -292
- package/dist/controller/model/endpoint.js.map +1 -1
- package/dist/controller/model/entity.d.ts.map +1 -1
- package/dist/controller/model/group.d.ts.map +1 -1
- package/dist/controller/model/group.js +202 -85
- package/dist/controller/model/group.js.map +1 -1
- package/dist/controller/model/index.d.ts.map +1 -1
- package/dist/controller/model/zigbeeEntity.d.ts.map +1 -0
- package/dist/controller/touchlink.d.ts.map +1 -1
- package/dist/controller/tstype.d.ts.map +1 -1
- package/dist/controller/tstype.js +0 -6
- package/dist/controller/tstype.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/utils/timeService.d.ts.map +1 -0
- package/dist/utils/timeService.js +127 -0
- package/dist/utils/timeService.js.map +1 -0
- package/dist/zspec/zcl/buffaloZcl.d.ts.map +1 -1
- package/dist/zspec/zcl/buffaloZcl.js +327 -287
- package/dist/zspec/zcl/buffaloZcl.js.map +1 -1
- package/dist/zspec/zcl/definition/cluster.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/cluster.js +6050 -4043
- package/dist/zspec/zcl/definition/cluster.js.map +1 -1
- package/dist/zspec/zcl/definition/clusters-types.d.ts +8135 -0
- package/dist/zspec/zcl/definition/clusters-types.d.ts.map +1 -0
- package/dist/zspec/zcl/definition/clusters-types.js +3 -0
- package/dist/zspec/zcl/definition/clusters-types.js.map +1 -0
- package/dist/zspec/zcl/definition/foundation.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/foundation.js +170 -99
- package/dist/zspec/zcl/definition/foundation.js.map +1 -1
- package/dist/zspec/zcl/definition/tstype.d.ts +190 -31
- package/dist/zspec/zcl/definition/tstype.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/tstype.js +0 -1
- package/dist/zspec/zcl/definition/tstype.js.map +1 -1
- package/dist/zspec/zcl/index.d.ts.map +1 -1
- package/dist/zspec/zcl/index.js +23 -13
- package/dist/zspec/zcl/index.js.map +1 -1
- package/dist/zspec/zcl/utils.d.ts.map +1 -1
- package/dist/zspec/zcl/utils.js +288 -103
- package/dist/zspec/zcl/utils.js.map +1 -1
- package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
- package/dist/zspec/zcl/zclFrame.js +121 -97
- package/dist/zspec/zcl/zclFrame.js.map +1 -1
- package/dist/zspec/zcl/zclHeader.d.ts.map +1 -1
- package/dist/zspec/zcl/zclHeader.js +13 -13
- package/dist/zspec/zcl/zclHeader.js.map +1 -1
- package/examples/join-and-log.js +18 -18
- package/package.json +23 -3
- package/release-please-config.json +8 -8
- package/scripts/check-clusters-changes.ts +328 -0
- package/scripts/clusters-changes.log +584 -0
- package/scripts/clusters-typegen.ts +608 -0
- package/scripts/utils.ts +88 -0
- package/scripts/zap-update-clusters-report.json +303 -0
- package/scripts/zap-update-clusters.ts +1520 -0
- package/scripts/zap-update-types.ts +707 -0
- package/scripts/zap-xml-clusters-overrides-data.ts +52 -0
- package/scripts/zap-xml-clusters-overrides.ts +400 -0
- package/scripts/zap-xml-types.ts +146 -0
- package/src/adapter/adapter.ts +210 -0
- package/src/adapter/adapterDiscovery.ts +736 -0
- package/src/adapter/const.ts +12 -0
- package/src/adapter/deconz/adapter/deconzAdapter.ts +888 -0
- package/src/adapter/deconz/driver/constants.ts +246 -0
- package/src/adapter/deconz/driver/driver.ts +1528 -0
- package/src/adapter/deconz/driver/frame.ts +11 -0
- package/src/adapter/deconz/driver/frameParser.ts +766 -0
- package/src/adapter/deconz/driver/parser.ts +45 -0
- package/src/adapter/deconz/driver/writer.ts +22 -0
- package/src/adapter/deconz/types.d.ts +13 -0
- package/src/adapter/ember/adapter/emberAdapter.ts +2262 -0
- package/src/adapter/ember/adapter/endpoints.ts +86 -0
- package/src/adapter/ember/adapter/oneWaitress.ts +324 -0
- package/src/adapter/ember/adapter/tokensManager.ts +780 -0
- package/src/adapter/ember/consts.ts +178 -0
- package/src/adapter/ember/enums.ts +1746 -0
- package/src/adapter/ember/ezsp/buffalo.ts +1392 -0
- package/src/adapter/ember/ezsp/consts.ts +148 -0
- package/src/adapter/ember/ezsp/enums.ts +1114 -0
- package/src/adapter/ember/ezsp/ezsp.ts +9073 -0
- package/src/adapter/ember/ezspError.ts +10 -0
- package/src/adapter/ember/types.ts +866 -0
- package/src/adapter/ember/uart/ash.ts +1933 -0
- package/src/adapter/ember/uart/consts.ts +109 -0
- package/src/adapter/ember/uart/enums.ts +192 -0
- package/src/adapter/ember/uart/parser.ts +42 -0
- package/src/adapter/ember/uart/queues.ts +247 -0
- package/src/adapter/ember/uart/writer.ts +50 -0
- package/src/adapter/ember/utils/initters.ts +58 -0
- package/src/adapter/ember/utils/math.ts +71 -0
- package/src/adapter/events.ts +21 -0
- package/src/adapter/ezsp/adapter/backup.ts +100 -0
- package/src/adapter/ezsp/adapter/ezspAdapter.ts +632 -0
- package/src/adapter/ezsp/driver/commands.ts +2497 -0
- package/src/adapter/ezsp/driver/consts.ts +11 -0
- package/src/adapter/ezsp/driver/driver.ts +1002 -0
- package/src/adapter/ezsp/driver/ezsp.ts +802 -0
- package/src/adapter/ezsp/driver/frame.ts +101 -0
- package/src/adapter/ezsp/driver/index.ts +4 -0
- package/src/adapter/ezsp/driver/multicast.ts +78 -0
- package/src/adapter/ezsp/driver/parser.ts +81 -0
- package/src/adapter/ezsp/driver/types/basic.ts +201 -0
- package/src/adapter/ezsp/driver/types/index.ts +239 -0
- package/src/adapter/ezsp/driver/types/named.ts +2330 -0
- package/src/adapter/ezsp/driver/types/struct.ts +844 -0
- package/src/adapter/ezsp/driver/uart.ts +460 -0
- package/src/adapter/ezsp/driver/utils/crc16ccitt.ts +44 -0
- package/src/adapter/ezsp/driver/utils/index.ts +32 -0
- package/src/adapter/ezsp/driver/writer.ts +64 -0
- package/src/adapter/index.ts +3 -0
- package/src/adapter/serialPort.ts +58 -0
- package/src/adapter/tstype.ts +57 -0
- package/src/adapter/utils.ts +41 -0
- package/src/adapter/z-stack/adapter/adapter-backup.ts +509 -0
- package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +457 -0
- package/src/adapter/z-stack/adapter/endpoints.ts +60 -0
- package/src/adapter/z-stack/adapter/manager.ts +543 -0
- package/src/adapter/z-stack/adapter/tstype.ts +6 -0
- package/src/adapter/z-stack/adapter/zStackAdapter.ts +1350 -0
- package/src/adapter/z-stack/constants/af.ts +27 -0
- package/src/adapter/z-stack/constants/common.ts +285 -0
- package/src/adapter/z-stack/constants/dbg.ts +23 -0
- package/src/adapter/z-stack/constants/index.ts +11 -0
- package/src/adapter/z-stack/constants/mac.ts +128 -0
- package/src/adapter/z-stack/constants/sapi.ts +25 -0
- package/src/adapter/z-stack/constants/sys.ts +72 -0
- package/src/adapter/z-stack/constants/util.ts +82 -0
- package/src/adapter/z-stack/constants/utils.ts +14 -0
- package/src/adapter/z-stack/constants/zdo.ts +103 -0
- package/src/adapter/z-stack/models/startup-options.ts +13 -0
- package/src/adapter/z-stack/structs/entries/address-manager-entry.ts +44 -0
- package/src/adapter/z-stack/structs/entries/address-manager-table.ts +19 -0
- package/src/adapter/z-stack/structs/entries/aps-link-key-data-entry.ts +12 -0
- package/src/adapter/z-stack/structs/entries/aps-link-key-data-table.ts +21 -0
- package/src/adapter/z-stack/structs/entries/aps-tc-link-key-entry.ts +19 -0
- package/src/adapter/z-stack/structs/entries/aps-tc-link-key-table.ts +21 -0
- package/src/adapter/z-stack/structs/entries/channel-list.ts +8 -0
- package/src/adapter/z-stack/structs/entries/has-configured.ts +16 -0
- package/src/adapter/z-stack/structs/entries/index.ts +16 -0
- package/src/adapter/z-stack/structs/entries/nib.ts +66 -0
- package/src/adapter/z-stack/structs/entries/nwk-key-descriptor.ts +15 -0
- package/src/adapter/z-stack/structs/entries/nwk-key.ts +13 -0
- package/src/adapter/z-stack/structs/entries/nwk-pan-id.ts +8 -0
- package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.ts +20 -0
- package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.ts +19 -0
- package/src/adapter/z-stack/structs/entries/security-manager-entry.ts +33 -0
- package/src/adapter/z-stack/structs/entries/security-manager-table.ts +22 -0
- package/src/adapter/z-stack/structs/index.ts +4 -0
- package/src/adapter/z-stack/structs/serializable-memory-object.ts +14 -0
- package/src/adapter/z-stack/structs/struct.ts +367 -0
- package/src/adapter/z-stack/structs/table.ts +198 -0
- package/src/adapter/z-stack/unpi/constants.ts +33 -0
- package/src/adapter/z-stack/unpi/frame.ts +62 -0
- package/src/adapter/z-stack/unpi/index.ts +4 -0
- package/src/adapter/z-stack/unpi/parser.ts +67 -0
- package/src/adapter/z-stack/unpi/writer.ts +37 -0
- package/src/adapter/z-stack/utils/channel-list.ts +40 -0
- package/src/adapter/z-stack/utils/index.ts +2 -0
- package/src/adapter/z-stack/utils/network-options.ts +26 -0
- package/src/adapter/z-stack/znp/buffaloZnp.ts +175 -0
- package/src/adapter/z-stack/znp/definition.ts +2713 -0
- package/src/adapter/z-stack/znp/index.ts +2 -0
- package/src/adapter/z-stack/znp/parameterType.ts +22 -0
- package/src/adapter/z-stack/znp/tstype.ts +44 -0
- package/src/adapter/z-stack/znp/utils.ts +10 -0
- package/src/adapter/z-stack/znp/znp.ts +345 -0
- package/src/adapter/z-stack/znp/zpiObject.ts +148 -0
- package/src/adapter/zboss/adapter/zbossAdapter.ts +535 -0
- package/src/adapter/zboss/commands.ts +1184 -0
- package/src/adapter/zboss/consts.ts +9 -0
- package/src/adapter/zboss/driver.ts +422 -0
- package/src/adapter/zboss/enums.ts +360 -0
- package/src/adapter/zboss/frame.ts +227 -0
- package/src/adapter/zboss/reader.ts +65 -0
- package/src/adapter/zboss/types.ts +0 -0
- package/src/adapter/zboss/uart.ts +428 -0
- package/src/adapter/zboss/utils.ts +58 -0
- package/src/adapter/zboss/writer.ts +49 -0
- package/src/adapter/zigate/adapter/patchZdoBuffaloBE.ts +25 -0
- package/src/adapter/zigate/adapter/zigateAdapter.ts +633 -0
- package/src/adapter/zigate/driver/LICENSE +17 -0
- package/src/adapter/zigate/driver/buffaloZiGate.ts +210 -0
- package/src/adapter/zigate/driver/commandType.ts +418 -0
- package/src/adapter/zigate/driver/constants.ts +150 -0
- package/src/adapter/zigate/driver/frame.ts +197 -0
- package/src/adapter/zigate/driver/messageType.ts +287 -0
- package/src/adapter/zigate/driver/parameterType.ts +32 -0
- package/src/adapter/zigate/driver/ziGateObject.ts +146 -0
- package/src/adapter/zigate/driver/zigate.ts +422 -0
- package/src/adapter/zoh/adapter/utils.ts +27 -0
- package/src/adapter/zoh/adapter/zohAdapter.ts +931 -0
- package/src/buffalo/buffalo.ts +336 -0
- package/src/buffalo/index.ts +1 -0
- package/src/controller/controller.ts +1159 -0
- package/src/controller/database.ts +148 -0
- package/src/controller/events.ts +52 -0
- package/src/controller/greenPower.ts +613 -0
- package/src/controller/helpers/index.ts +1 -0
- package/src/controller/helpers/installCodes.ts +107 -0
- package/src/controller/helpers/ota.ts +578 -0
- package/src/controller/helpers/request.ts +96 -0
- package/src/controller/helpers/requestQueue.ts +126 -0
- package/src/controller/helpers/zclFrameConverter.ts +64 -0
- package/src/controller/helpers/zclTransactionSequenceNumber.ts +15 -0
- package/src/controller/index.ts +6 -0
- package/src/controller/model/device.ts +1791 -0
- package/src/controller/model/endpoint.ts +1235 -0
- package/src/controller/model/entity.ts +43 -0
- package/src/controller/model/group.ts +446 -0
- package/src/controller/model/index.ts +5 -0
- package/src/controller/model/konnextConfig.ts +6 -0
- package/src/controller/model/zigbeeEntity.ts +30 -0
- package/src/controller/touchlink.ts +195 -0
- package/src/controller/tstype.ts +374 -0
- package/src/index.ts +14 -0
- package/src/models/backup-storage-legacy.ts +48 -0
- package/src/models/backup-storage-unified.ts +47 -0
- package/src/models/backup.ts +37 -0
- package/src/models/index.ts +5 -0
- package/src/models/network-options.ts +11 -0
- package/src/utils/aes.ts +218 -0
- package/src/utils/async-mutex.ts +31 -0
- package/src/utils/backup.ts +152 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/logger.ts +20 -0
- package/src/utils/patchBigIntSerialization.ts +8 -0
- package/src/utils/queue.ts +79 -0
- package/src/utils/timeService.ts +139 -0
- package/src/utils/utils.ts +19 -0
- package/src/utils/wait.ts +5 -0
- package/src/utils/waitress.ts +96 -0
- package/src/zspec/consts.ts +89 -0
- package/src/zspec/enums.ts +22 -0
- package/src/zspec/index.ts +3 -0
- package/src/zspec/tstypes.ts +18 -0
- package/src/zspec/utils.ts +247 -0
- package/src/zspec/zcl/buffaloZcl.ts +1073 -0
- package/src/zspec/zcl/definition/cluster.ts +7554 -0
- package/src/zspec/zcl/definition/clusters-types.ts +8228 -0
- package/src/zspec/zcl/definition/consts.ts +24 -0
- package/src/zspec/zcl/definition/datatypes.ts +2454 -0
- package/src/zspec/zcl/definition/enums.ts +224 -0
- package/src/zspec/zcl/definition/foundation.ts +342 -0
- package/src/zspec/zcl/definition/manufacturerCode.ts +730 -0
- package/src/zspec/zcl/definition/status.ts +69 -0
- package/src/zspec/zcl/definition/tstype.ts +432 -0
- package/src/zspec/zcl/index.ts +11 -0
- package/src/zspec/zcl/utils.ts +504 -0
- package/src/zspec/zcl/zclFrame.ts +383 -0
- package/src/zspec/zcl/zclHeader.ts +102 -0
- package/src/zspec/zcl/zclStatusError.ts +10 -0
- package/src/zspec/zdo/buffaloZdo.ts +2336 -0
- package/src/zspec/zdo/definition/clusters.ts +722 -0
- package/src/zspec/zdo/definition/consts.ts +16 -0
- package/src/zspec/zdo/definition/enums.ts +99 -0
- package/src/zspec/zdo/definition/status.ts +105 -0
- package/src/zspec/zdo/definition/tstypes.ts +1062 -0
- package/src/zspec/zdo/index.ts +7 -0
- package/src/zspec/zdo/utils.ts +76 -0
- package/src/zspec/zdo/zdoStatusError.ts +10 -0
- package/test/adapter/adapter.test.ts +1276 -0
- package/test/adapter/ember/ash.test.ts +337 -0
- package/test/adapter/ember/consts.ts +131 -0
- package/test/adapter/ember/emberAdapter.test.ts +3447 -0
- package/test/adapter/ember/ezsp.test.ts +389 -0
- package/test/adapter/ember/ezspBuffalo.test.ts +93 -0
- package/test/adapter/ember/ezspError.test.ts +12 -0
- package/test/adapter/ember/math.test.ts +190 -0
- package/test/adapter/ezsp/frame.test.ts +30 -0
- package/test/adapter/ezsp/uart.test.ts +181 -0
- package/test/adapter/z-stack/adapter.test.ts +4260 -0
- package/test/adapter/z-stack/constants.test.ts +33 -0
- package/test/adapter/z-stack/structs.test.ts +115 -0
- package/test/adapter/z-stack/unpi.test.ts +213 -0
- package/test/adapter/z-stack/znp.test.ts +1288 -0
- package/test/adapter/zboss/fixZdoResponse.test.ts +179 -0
- package/test/adapter/zigate/patchZdoBuffaloBE.test.ts +81 -0
- package/test/adapter/zigate/zdo.test.ts +187 -0
- package/test/adapter/zoh/utils.test.ts +36 -0
- package/test/adapter/zoh/zohAdapter.test.ts +1451 -0
- package/test/benchOptions.ts +14 -0
- package/test/buffalo.test.ts +431 -0
- package/test/controller.bench.ts +215 -0
- package/test/controller.test.ts +10038 -0
- package/test/data/integrity-code-1166-012B-24031511-upgradeMe-RB 249 T.zigbee +0 -0
- package/test/data/manuf-tags-tradfri-cv-cct-unified_release_prod_v587757105_33e34452-9267-4665-bc5a-844c8f61f063.ota +0 -0
- package/test/data/padded-tretakt_smart_plug_soc-0x1100-2.4.25-prod.ota.ota.signed +0 -0
- package/test/data/telink-aes-A60_RGBW_T-0x00B6-0x03483712-MF_DIS.OTA +0 -0
- package/test/data/zbminir2_v1.0.8.ota +0 -0
- package/test/device-ota.test.ts +3332 -0
- package/test/greenpower.test.ts +1409 -0
- package/test/mockAdapters.ts +95 -0
- package/test/mockDevices.ts +623 -0
- package/test/requests.bench.ts +321 -0
- package/test/testUtils.ts +20 -0
- package/test/timeService.test.ts +214 -0
- package/test/tsconfig.json +9 -0
- package/test/utils/math.ts +19 -0
- package/test/utils.test.ts +352 -0
- package/test/vitest.config.mts +28 -0
- package/test/vitest.ts +9 -0
- package/test/zcl.test.ts +2887 -0
- package/test/zspec/utils.test.ts +68 -0
- package/test/zspec/zcl/buffalo.test.ts +1316 -0
- package/test/zspec/zcl/frame.test.ts +1056 -0
- package/test/zspec/zcl/utils.test.ts +650 -0
- package/test/zspec/zdo/buffalo.test.ts +1850 -0
- package/test/zspec/zdo/utils.test.ts +241 -0
- package/tsconfig.json +8 -10
- package/.babelrc.js +0 -6
- package/.eslintignore +0 -3
- package/dist/adapter/adapter.d.ts +0 -64
- package/dist/adapter/adapter.js +0 -157
- package/dist/adapter/adapter.js.map +0 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +0 -71
- package/dist/adapter/deconz/adapter/deconzAdapter.js +0 -1072
- package/dist/adapter/deconz/adapter/deconzAdapter.js.map +0 -1
- package/dist/adapter/deconz/adapter/index.d.ts +0 -3
- package/dist/adapter/deconz/adapter/index.d.ts.map +0 -1
- package/dist/adapter/deconz/adapter/index.js +0 -11
- package/dist/adapter/deconz/adapter/index.js.map +0 -1
- package/dist/adapter/deconz/driver/constants.d.ts +0 -105
- package/dist/adapter/deconz/driver/constants.d.ts.map +0 -1
- package/dist/adapter/deconz/driver/constants.js +0 -56
- package/dist/adapter/deconz/driver/constants.js.map +0 -1
- package/dist/adapter/deconz/driver/driver.d.ts +0 -82
- package/dist/adapter/deconz/driver/driver.d.ts.map +0 -1
- package/dist/adapter/deconz/driver/driver.js +0 -751
- package/dist/adapter/deconz/driver/driver.js.map +0 -1
- package/dist/adapter/deconz/driver/frame.d.ts +0 -7
- package/dist/adapter/deconz/driver/frame.d.ts.map +0 -1
- package/dist/adapter/deconz/driver/frame.js +0 -14
- package/dist/adapter/deconz/driver/frame.js.map +0 -1
- package/dist/adapter/deconz/driver/frameParser.d.ts +0 -3
- package/dist/adapter/deconz/driver/frameParser.d.ts.map +0 -1
- package/dist/adapter/deconz/driver/frameParser.js +0 -444
- package/dist/adapter/deconz/driver/frameParser.js.map +0 -1
- package/dist/adapter/deconz/driver/parser.d.ts +0 -13
- package/dist/adapter/deconz/driver/parser.d.ts.map +0 -1
- package/dist/adapter/deconz/driver/parser.js +0 -64
- package/dist/adapter/deconz/driver/parser.js.map +0 -1
- package/dist/adapter/deconz/driver/writer.d.ts +0 -9
- package/dist/adapter/deconz/driver/writer.d.ts.map +0 -1
- package/dist/adapter/deconz/driver/writer.js +0 -45
- package/dist/adapter/deconz/driver/writer.js.map +0 -1
- package/dist/adapter/ember/adapter/emberAdapter.d.ts +0 -806
- package/dist/adapter/ember/adapter/emberAdapter.js +0 -2942
- package/dist/adapter/ember/adapter/emberAdapter.js.map +0 -1
- package/dist/adapter/ember/adapter/endpoints.d.ts +0 -27
- package/dist/adapter/ember/adapter/endpoints.js +0 -68
- package/dist/adapter/ember/adapter/endpoints.js.map +0 -1
- package/dist/adapter/ember/adapter/index.d.ts +0 -3
- package/dist/adapter/ember/adapter/index.d.ts.map +0 -1
- package/dist/adapter/ember/adapter/index.js +0 -6
- package/dist/adapter/ember/adapter/index.js.map +0 -1
- package/dist/adapter/ember/adapter/oneWaitress.d.ts +0 -108
- package/dist/adapter/ember/adapter/oneWaitress.js +0 -241
- package/dist/adapter/ember/adapter/oneWaitress.js.map +0 -1
- package/dist/adapter/ember/adapter/requestQueue.d.ts +0 -57
- package/dist/adapter/ember/adapter/requestQueue.d.ts.map +0 -1
- package/dist/adapter/ember/adapter/requestQueue.js +0 -139
- package/dist/adapter/ember/adapter/requestQueue.js.map +0 -1
- package/dist/adapter/ember/adapter/tokensManager.d.ts +0 -69
- package/dist/adapter/ember/adapter/tokensManager.js +0 -688
- package/dist/adapter/ember/adapter/tokensManager.js.map +0 -1
- package/dist/adapter/ember/consts.d.ts +0 -191
- package/dist/adapter/ember/consts.d.ts.map +0 -1
- package/dist/adapter/ember/consts.js +0 -246
- package/dist/adapter/ember/consts.js.map +0 -1
- package/dist/adapter/ember/enums.d.ts +0 -2172
- package/dist/adapter/ember/enums.d.ts.map +0 -1
- package/dist/adapter/ember/enums.js +0 -2375
- package/dist/adapter/ember/enums.js.map +0 -1
- package/dist/adapter/ember/ezsp/buffalo.d.ts +0 -156
- package/dist/adapter/ember/ezsp/buffalo.d.ts.map +0 -1
- package/dist/adapter/ember/ezsp/buffalo.js +0 -1033
- package/dist/adapter/ember/ezsp/buffalo.js.map +0 -1
- package/dist/adapter/ember/ezsp/consts.d.ts +0 -116
- package/dist/adapter/ember/ezsp/consts.d.ts.map +0 -1
- package/dist/adapter/ember/ezsp/consts.js +0 -128
- package/dist/adapter/ember/ezsp/consts.js.map +0 -1
- package/dist/adapter/ember/ezsp/enums.d.ts +0 -879
- package/dist/adapter/ember/ezsp/enums.d.ts.map +0 -1
- package/dist/adapter/ember/ezsp/enums.js +0 -948
- package/dist/adapter/ember/ezsp/enums.js.map +0 -1
- package/dist/adapter/ember/ezsp/ezsp.d.ts +0 -2662
- package/dist/adapter/ember/ezsp/ezsp.js +0 -6454
- package/dist/adapter/ember/ezsp/ezsp.js.map +0 -1
- package/dist/adapter/ember/types.d.ts +0 -733
- package/dist/adapter/ember/types.d.ts.map +0 -1
- package/dist/adapter/ember/types.js +0 -3
- package/dist/adapter/ember/types.js.map +0 -1
- package/dist/adapter/ember/uart/ash.d.ts +0 -464
- package/dist/adapter/ember/uart/ash.d.ts.map +0 -1
- package/dist/adapter/ember/uart/ash.js +0 -1633
- package/dist/adapter/ember/uart/ash.js.map +0 -1
- package/dist/adapter/ember/uart/consts.d.ts +0 -91
- package/dist/adapter/ember/uart/consts.d.ts.map +0 -1
- package/dist/adapter/ember/uart/consts.js +0 -100
- package/dist/adapter/ember/uart/consts.js.map +0 -1
- package/dist/adapter/ember/uart/enums.d.ts +0 -191
- package/dist/adapter/ember/uart/enums.d.ts.map +0 -1
- package/dist/adapter/ember/uart/enums.js +0 -197
- package/dist/adapter/ember/uart/enums.js.map +0 -1
- package/dist/adapter/ember/uart/parser.d.ts +0 -10
- package/dist/adapter/ember/uart/parser.d.ts.map +0 -1
- package/dist/adapter/ember/uart/parser.js +0 -37
- package/dist/adapter/ember/uart/parser.js.map +0 -1
- package/dist/adapter/ember/uart/queues.d.ts +0 -85
- package/dist/adapter/ember/uart/queues.d.ts.map +0 -1
- package/dist/adapter/ember/uart/queues.js +0 -214
- package/dist/adapter/ember/uart/queues.js.map +0 -1
- package/dist/adapter/ember/uart/writer.d.ts +0 -15
- package/dist/adapter/ember/uart/writer.d.ts.map +0 -1
- package/dist/adapter/ember/uart/writer.js +0 -46
- package/dist/adapter/ember/uart/writer.js.map +0 -1
- package/dist/adapter/ember/utils/initters.d.ts +0 -20
- package/dist/adapter/ember/utils/initters.js +0 -58
- package/dist/adapter/ember/utils/initters.js.map +0 -1
- package/dist/adapter/ember/utils/math.d.ts +0 -51
- package/dist/adapter/ember/utils/math.d.ts.map +0 -1
- package/dist/adapter/ember/utils/math.js +0 -102
- package/dist/adapter/ember/utils/math.js.map +0 -1
- package/dist/adapter/ember/zdo.d.ts +0 -925
- package/dist/adapter/ember/zdo.d.ts.map +0 -1
- package/dist/adapter/ember/zdo.js +0 -723
- package/dist/adapter/ember/zdo.js.map +0 -1
- package/dist/adapter/events.d.ts +0 -42
- package/dist/adapter/events.js +0 -13
- package/dist/adapter/events.js.map +0 -1
- package/dist/adapter/ezsp/adapter/backup.d.ts +0 -13
- package/dist/adapter/ezsp/adapter/backup.js +0 -101
- package/dist/adapter/ezsp/adapter/backup.js.map +0 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +0 -65
- package/dist/adapter/ezsp/adapter/ezspAdapter.js +0 -634
- package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +0 -1
- package/dist/adapter/ezsp/adapter/index.d.ts +0 -3
- package/dist/adapter/ezsp/adapter/index.d.ts.map +0 -1
- package/dist/adapter/ezsp/adapter/index.js +0 -11
- package/dist/adapter/ezsp/adapter/index.js.map +0 -1
- package/dist/adapter/ezsp/driver/commands.d.ts +0 -37
- package/dist/adapter/ezsp/driver/commands.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/commands.js +0 -2387
- package/dist/adapter/ezsp/driver/commands.js.map +0 -1
- package/dist/adapter/ezsp/driver/consts.d.ts +0 -11
- package/dist/adapter/ezsp/driver/consts.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/consts.js +0 -14
- package/dist/adapter/ezsp/driver/consts.js.map +0 -1
- package/dist/adapter/ezsp/driver/driver.d.ts +0 -109
- package/dist/adapter/ezsp/driver/driver.js +0 -796
- package/dist/adapter/ezsp/driver/driver.js.map +0 -1
- package/dist/adapter/ezsp/driver/ezsp.d.ts +0 -106
- package/dist/adapter/ezsp/driver/ezsp.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/ezsp.js +0 -664
- package/dist/adapter/ezsp/driver/ezsp.js.map +0 -1
- package/dist/adapter/ezsp/driver/frame.d.ts +0 -40
- package/dist/adapter/ezsp/driver/frame.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/frame.js +0 -101
- package/dist/adapter/ezsp/driver/frame.js.map +0 -1
- package/dist/adapter/ezsp/driver/index.d.ts +0 -4
- package/dist/adapter/ezsp/driver/index.js +0 -9
- package/dist/adapter/ezsp/driver/index.js.map +0 -1
- package/dist/adapter/ezsp/driver/multicast.d.ts +0 -13
- package/dist/adapter/ezsp/driver/multicast.js +0 -74
- package/dist/adapter/ezsp/driver/multicast.js.map +0 -1
- package/dist/adapter/ezsp/driver/parser.d.ts +0 -12
- package/dist/adapter/ezsp/driver/parser.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/parser.js +0 -105
- package/dist/adapter/ezsp/driver/parser.js.map +0 -1
- package/dist/adapter/ezsp/driver/types/basic.d.ts +0 -63
- package/dist/adapter/ezsp/driver/types/basic.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/types/basic.js +0 -209
- package/dist/adapter/ezsp/driver/types/basic.js.map +0 -1
- package/dist/adapter/ezsp/driver/types/index.d.ts +0 -10
- package/dist/adapter/ezsp/driver/types/index.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/types/index.js +0 -139
- package/dist/adapter/ezsp/driver/types/index.js.map +0 -1
- package/dist/adapter/ezsp/driver/types/named.d.ts +0 -1288
- package/dist/adapter/ezsp/driver/types/named.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/types/named.js +0 -2330
- package/dist/adapter/ezsp/driver/types/named.js.map +0 -1
- package/dist/adapter/ezsp/driver/types/struct.d.ts +0 -271
- package/dist/adapter/ezsp/driver/types/struct.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/types/struct.js +0 -804
- package/dist/adapter/ezsp/driver/types/struct.js.map +0 -1
- package/dist/adapter/ezsp/driver/uart.d.ts +0 -49
- package/dist/adapter/ezsp/driver/uart.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/uart.js +0 -383
- package/dist/adapter/ezsp/driver/uart.js.map +0 -1
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts +0 -3
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.js +0 -56
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.js.map +0 -1
- package/dist/adapter/ezsp/driver/utils/index.d.ts +0 -20
- package/dist/adapter/ezsp/driver/utils/index.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/utils/index.js +0 -73
- package/dist/adapter/ezsp/driver/utils/index.js.map +0 -1
- package/dist/adapter/ezsp/driver/writer.d.ts +0 -14
- package/dist/adapter/ezsp/driver/writer.d.ts.map +0 -1
- package/dist/adapter/ezsp/driver/writer.js +0 -83
- package/dist/adapter/ezsp/driver/writer.js.map +0 -1
- package/dist/adapter/index.d.ts +0 -5
- package/dist/adapter/index.js +0 -36
- package/dist/adapter/index.js.map +0 -1
- package/dist/adapter/serialPort.d.ts +0 -14
- package/dist/adapter/serialPort.d.ts.map +0 -1
- package/dist/adapter/serialPort.js +0 -47
- package/dist/adapter/serialPort.js.map +0 -1
- package/dist/adapter/serialPortUtils.d.ts +0 -13
- package/dist/adapter/serialPortUtils.d.ts.map +0 -1
- package/dist/adapter/serialPortUtils.js +0 -19
- package/dist/adapter/serialPortUtils.js.map +0 -1
- package/dist/adapter/socketPortUtils.d.ts +0 -11
- package/dist/adapter/socketPortUtils.d.ts.map +0 -1
- package/dist/adapter/socketPortUtils.js +0 -17
- package/dist/adapter/socketPortUtils.js.map +0 -1
- package/dist/adapter/tstype.d.ts +0 -86
- package/dist/adapter/tstype.d.ts.map +0 -1
- package/dist/adapter/tstype.js +0 -3
- package/dist/adapter/tstype.js.map +0 -1
- package/dist/adapter/z-stack/adapter/adapter-backup.d.ts +0 -62
- package/dist/adapter/z-stack/adapter/adapter-backup.d.ts.map +0 -1
- package/dist/adapter/z-stack/adapter/adapter-backup.js +0 -459
- package/dist/adapter/z-stack/adapter/adapter-backup.js.map +0 -1
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts +0 -151
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts.map +0 -1
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.js +0 -259
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.js.map +0 -1
- package/dist/adapter/z-stack/adapter/endpoints.d.ts +0 -12
- package/dist/adapter/z-stack/adapter/endpoints.js +0 -74
- package/dist/adapter/z-stack/adapter/endpoints.js.map +0 -1
- package/dist/adapter/z-stack/adapter/index.d.ts +0 -3
- package/dist/adapter/z-stack/adapter/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/adapter/index.js +0 -9
- package/dist/adapter/z-stack/adapter/index.js.map +0 -1
- package/dist/adapter/z-stack/adapter/manager.d.ts +0 -84
- package/dist/adapter/z-stack/adapter/manager.js +0 -474
- package/dist/adapter/z-stack/adapter/manager.js.map +0 -1
- package/dist/adapter/z-stack/adapter/tstype.d.ts +0 -7
- package/dist/adapter/z-stack/adapter/tstype.d.ts.map +0 -1
- package/dist/adapter/z-stack/adapter/tstype.js +0 -10
- package/dist/adapter/z-stack/adapter/tstype.js.map +0 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +0 -86
- package/dist/adapter/z-stack/adapter/zStackAdapter.js +0 -912
- package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +0 -1
- package/dist/adapter/z-stack/constants/af.d.ts +0 -24
- package/dist/adapter/z-stack/constants/af.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/af.js +0 -28
- package/dist/adapter/z-stack/constants/af.js.map +0 -1
- package/dist/adapter/z-stack/constants/common.d.ts +0 -279
- package/dist/adapter/z-stack/constants/common.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/common.js +0 -293
- package/dist/adapter/z-stack/constants/common.js.map +0 -1
- package/dist/adapter/z-stack/constants/dbg.d.ts +0 -23
- package/dist/adapter/z-stack/constants/dbg.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/dbg.js +0 -25
- package/dist/adapter/z-stack/constants/dbg.js.map +0 -1
- package/dist/adapter/z-stack/constants/index.d.ts +0 -11
- package/dist/adapter/z-stack/constants/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/index.js +0 -48
- package/dist/adapter/z-stack/constants/index.js.map +0 -1
- package/dist/adapter/z-stack/constants/mac.d.ts +0 -128
- package/dist/adapter/z-stack/constants/mac.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/mac.js +0 -130
- package/dist/adapter/z-stack/constants/mac.js.map +0 -1
- package/dist/adapter/z-stack/constants/sapi.d.ts +0 -25
- package/dist/adapter/z-stack/constants/sapi.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/sapi.js +0 -27
- package/dist/adapter/z-stack/constants/sapi.js.map +0 -1
- package/dist/adapter/z-stack/constants/sys.d.ts +0 -72
- package/dist/adapter/z-stack/constants/sys.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/sys.js +0 -74
- package/dist/adapter/z-stack/constants/sys.js.map +0 -1
- package/dist/adapter/z-stack/constants/util.d.ts +0 -82
- package/dist/adapter/z-stack/constants/util.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/util.js +0 -84
- package/dist/adapter/z-stack/constants/util.js.map +0 -1
- package/dist/adapter/z-stack/constants/utils.d.ts +0 -5
- package/dist/adapter/z-stack/constants/utils.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/utils.js +0 -15
- package/dist/adapter/z-stack/constants/utils.js.map +0 -1
- package/dist/adapter/z-stack/constants/zdo.d.ts +0 -103
- package/dist/adapter/z-stack/constants/zdo.d.ts.map +0 -1
- package/dist/adapter/z-stack/constants/zdo.js +0 -105
- package/dist/adapter/z-stack/constants/zdo.js.map +0 -1
- package/dist/adapter/z-stack/models/index.d.ts +0 -2
- package/dist/adapter/z-stack/models/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/models/index.js +0 -18
- package/dist/adapter/z-stack/models/index.js.map +0 -1
- package/dist/adapter/z-stack/models/startup-options.d.ts +0 -13
- package/dist/adapter/z-stack/models/startup-options.js +0 -3
- package/dist/adapter/z-stack/models/startup-options.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts +0 -24
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.js +0 -46
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/address-manager-table.js +0 -23
- package/dist/adapter/z-stack/structs/entries/address-manager-table.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js +0 -22
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js +0 -24
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js +0 -25
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js +0 -24
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/channel-list.d.ts +0 -9
- package/dist/adapter/z-stack/structs/entries/channel-list.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/channel-list.js +0 -16
- package/dist/adapter/z-stack/structs/entries/channel-list.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/has-configured.d.ts +0 -9
- package/dist/adapter/z-stack/structs/entries/has-configured.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/has-configured.js +0 -17
- package/dist/adapter/z-stack/structs/entries/has-configured.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/index.d.ts +0 -17
- package/dist/adapter/z-stack/structs/entries/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/index.js +0 -33
- package/dist/adapter/z-stack/structs/entries/index.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nib.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/nib.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nib.js +0 -69
- package/dist/adapter/z-stack/structs/entries/nib.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js +0 -19
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts +0 -9
- package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-key.js +0 -16
- package/dist/adapter/z-stack/structs/entries/nwk-key.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts +0 -9
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js +0 -16
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts +0 -14
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js +0 -24
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js +0 -23
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts +0 -21
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.js +0 -37
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.js.map +0 -1
- package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts +0 -11
- package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/entries/security-manager-table.js +0 -25
- package/dist/adapter/z-stack/structs/entries/security-manager-table.js.map +0 -1
- package/dist/adapter/z-stack/structs/index.d.ts +0 -5
- package/dist/adapter/z-stack/structs/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/index.js +0 -21
- package/dist/adapter/z-stack/structs/index.js.map +0 -1
- package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts +0 -14
- package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/serializable-memory-object.js +0 -3
- package/dist/adapter/z-stack/structs/serializable-memory-object.js.map +0 -1
- package/dist/adapter/z-stack/structs/struct.d.ts +0 -100
- package/dist/adapter/z-stack/structs/struct.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/struct.js +0 -297
- package/dist/adapter/z-stack/structs/struct.js.map +0 -1
- package/dist/adapter/z-stack/structs/table.d.ts +0 -95
- package/dist/adapter/z-stack/structs/table.d.ts.map +0 -1
- package/dist/adapter/z-stack/structs/table.js +0 -164
- package/dist/adapter/z-stack/structs/table.js.map +0 -1
- package/dist/adapter/z-stack/unpi/constants.d.ts +0 -29
- package/dist/adapter/z-stack/unpi/constants.d.ts.map +0 -1
- package/dist/adapter/z-stack/unpi/constants.js +0 -40
- package/dist/adapter/z-stack/unpi/constants.js.map +0 -1
- package/dist/adapter/z-stack/unpi/frame.d.ts +0 -17
- package/dist/adapter/z-stack/unpi/frame.d.ts.map +0 -1
- package/dist/adapter/z-stack/unpi/frame.js +0 -55
- package/dist/adapter/z-stack/unpi/frame.js.map +0 -1
- package/dist/adapter/z-stack/unpi/index.d.ts +0 -6
- package/dist/adapter/z-stack/unpi/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/unpi/index.js +0 -38
- package/dist/adapter/z-stack/unpi/index.js.map +0 -1
- package/dist/adapter/z-stack/unpi/parser.d.ts +0 -13
- package/dist/adapter/z-stack/unpi/parser.d.ts.map +0 -1
- package/dist/adapter/z-stack/unpi/parser.js +0 -86
- package/dist/adapter/z-stack/unpi/parser.js.map +0 -1
- package/dist/adapter/z-stack/unpi/writer.d.ts +0 -12
- package/dist/adapter/z-stack/unpi/writer.d.ts.map +0 -1
- package/dist/adapter/z-stack/unpi/writer.js +0 -55
- package/dist/adapter/z-stack/unpi/writer.js.map +0 -1
- package/dist/adapter/z-stack/utils/channel-list.d.ts +0 -21
- package/dist/adapter/z-stack/utils/channel-list.d.ts.map +0 -1
- package/dist/adapter/z-stack/utils/channel-list.js +0 -41
- package/dist/adapter/z-stack/utils/channel-list.js.map +0 -1
- package/dist/adapter/z-stack/utils/index.d.ts +0 -3
- package/dist/adapter/z-stack/utils/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/utils/index.js +0 -19
- package/dist/adapter/z-stack/utils/index.js.map +0 -1
- package/dist/adapter/z-stack/utils/network-options.d.ts +0 -9
- package/dist/adapter/z-stack/utils/network-options.d.ts.map +0 -1
- package/dist/adapter/z-stack/utils/network-options.js +0 -23
- package/dist/adapter/z-stack/utils/network-options.js.map +0 -1
- package/dist/adapter/z-stack/znp/buffaloZnp.d.ts +0 -14
- package/dist/adapter/z-stack/znp/buffaloZnp.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/buffaloZnp.js +0 -243
- package/dist/adapter/z-stack/znp/buffaloZnp.js.map +0 -1
- package/dist/adapter/z-stack/znp/definition.d.ts +0 -6
- package/dist/adapter/z-stack/znp/definition.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/definition.js +0 -3052
- package/dist/adapter/z-stack/znp/definition.js.map +0 -1
- package/dist/adapter/z-stack/znp/index.d.ts +0 -4
- package/dist/adapter/z-stack/znp/index.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/index.js +0 -11
- package/dist/adapter/z-stack/znp/index.js.map +0 -1
- package/dist/adapter/z-stack/znp/parameterType.d.ts +0 -23
- package/dist/adapter/z-stack/znp/parameterType.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/parameterType.js +0 -26
- package/dist/adapter/z-stack/znp/parameterType.js.map +0 -1
- package/dist/adapter/z-stack/znp/tstype.d.ts +0 -23
- package/dist/adapter/z-stack/znp/tstype.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/tstype.js +0 -3
- package/dist/adapter/z-stack/znp/tstype.js.map +0 -1
- package/dist/adapter/z-stack/znp/znp.d.ts +0 -47
- package/dist/adapter/z-stack/znp/znp.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/znp.js +0 -322
- package/dist/adapter/z-stack/znp/znp.js.map +0 -1
- package/dist/adapter/z-stack/znp/zpiObject.d.ts +0 -20
- package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +0 -1
- package/dist/adapter/z-stack/znp/zpiObject.js +0 -103
- package/dist/adapter/z-stack/znp/zpiObject.js.map +0 -1
- package/dist/adapter/zigate/adapter/index.d.ts +0 -3
- package/dist/adapter/zigate/adapter/index.d.ts.map +0 -1
- package/dist/adapter/zigate/adapter/index.js +0 -11
- package/dist/adapter/zigate/adapter/index.js.map +0 -1
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +0 -72
- package/dist/adapter/zigate/adapter/zigateAdapter.js +0 -681
- package/dist/adapter/zigate/adapter/zigateAdapter.js.map +0 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.d.ts +0 -18
- package/dist/adapter/zigate/driver/commandType.d.ts +0 -43
- package/dist/adapter/zigate/driver/commandType.d.ts.map +0 -1
- package/dist/adapter/zigate/driver/commandType.js +0 -390
- package/dist/adapter/zigate/driver/commandType.js.map +0 -1
- package/dist/adapter/zigate/driver/constants.d.ts +0 -277
- package/dist/adapter/zigate/driver/constants.d.ts.map +0 -1
- package/dist/adapter/zigate/driver/constants.js +0 -372
- package/dist/adapter/zigate/driver/constants.js.map +0 -1
- package/dist/adapter/zigate/driver/frame.d.ts +0 -27
- package/dist/adapter/zigate/driver/frame.d.ts.map +0 -1
- package/dist/adapter/zigate/driver/frame.js +0 -173
- package/dist/adapter/zigate/driver/frame.js.map +0 -1
- package/dist/adapter/zigate/driver/messageType.d.ts +0 -13
- package/dist/adapter/zigate/driver/messageType.d.ts.map +0 -1
- package/dist/adapter/zigate/driver/messageType.js +0 -284
- package/dist/adapter/zigate/driver/messageType.js.map +0 -1
- package/dist/adapter/zigate/driver/parameterType.d.ts +0 -28
- package/dist/adapter/zigate/driver/parameterType.d.ts.map +0 -1
- package/dist/adapter/zigate/driver/parameterType.js +0 -33
- package/dist/adapter/zigate/driver/parameterType.js.map +0 -1
- package/dist/adapter/zigate/driver/ziGateObject.d.ts +0 -24
- package/dist/adapter/zigate/driver/ziGateObject.js +0 -111
- package/dist/adapter/zigate/driver/ziGateObject.js.map +0 -1
- package/dist/adapter/zigate/driver/zigate.d.ts +0 -50
- package/dist/adapter/zigate/driver/zigate.js +0 -289
- package/dist/adapter/zigate/driver/zigate.js.map +0 -1
- package/dist/buffalo/buffalo.d.ts +0 -55
- package/dist/buffalo/buffalo.d.ts.map +0 -1
- package/dist/buffalo/buffalo.js +0 -230
- package/dist/buffalo/buffalo.js.map +0 -1
- package/dist/buffalo/index.d.ts +0 -3
- package/dist/buffalo/index.d.ts.map +0 -1
- package/dist/buffalo/index.js +0 -9
- package/dist/buffalo/index.js.map +0 -1
- package/dist/controller/controller.d.ts +0 -119
- package/dist/controller/database.d.ts +0 -20
- package/dist/controller/database.js +0 -94
- package/dist/controller/database.js.map +0 -1
- package/dist/controller/events.d.ts +0 -59
- package/dist/controller/greenPower.d.ts +0 -14
- package/dist/controller/helpers/index.d.ts +0 -3
- package/dist/controller/helpers/index.js +0 -29
- package/dist/controller/helpers/index.js.map +0 -1
- package/dist/controller/helpers/request.d.ts +0 -22
- package/dist/controller/helpers/request.js +0 -78
- package/dist/controller/helpers/request.js.map +0 -1
- package/dist/controller/helpers/requestQueue.d.ts +0 -13
- package/dist/controller/helpers/requestQueue.js +0 -106
- package/dist/controller/helpers/requestQueue.js.map +0 -1
- package/dist/controller/helpers/zclFrameConverter.d.ts +0 -9
- package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts +0 -6
- package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts.map +0 -1
- package/dist/controller/helpers/zclTransactionSequenceNumber.js +0 -14
- package/dist/controller/helpers/zclTransactionSequenceNumber.js.map +0 -1
- package/dist/controller/index.d.ts +0 -6
- package/dist/controller/index.js +0 -9
- package/dist/controller/index.js.map +0 -1
- package/dist/controller/model/device.d.ts +0 -140
- package/dist/controller/model/endpoint.d.ts +0 -134
- package/dist/controller/model/entity.d.ts +0 -15
- package/dist/controller/model/entity.js +0 -27
- package/dist/controller/model/entity.js.map +0 -1
- package/dist/controller/model/group.d.ts +0 -39
- package/dist/controller/model/index.d.ts +0 -6
- package/dist/controller/model/index.js +0 -15
- package/dist/controller/model/index.js.map +0 -1
- package/dist/controller/model/konnextConfig.d.ts +0 -7
- package/dist/controller/model/konnextConfig.d.ts.map +0 -1
- package/dist/controller/model/konnextConfig.js +0 -3
- package/dist/controller/model/konnextConfig.js.map +0 -1
- package/dist/controller/touchlink.d.ts +0 -20
- package/dist/controller/touchlink.js +0 -157
- package/dist/controller/touchlink.js.map +0 -1
- package/dist/controller/tstype.d.ts +0 -21
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -37
- package/dist/index.js.map +0 -1
- package/dist/models/backup-storage-legacy.d.ts +0 -27
- package/dist/models/backup-storage-legacy.d.ts.map +0 -1
- package/dist/models/backup-storage-legacy.js +0 -3
- package/dist/models/backup-storage-legacy.js.map +0 -1
- package/dist/models/backup-storage-unified.d.ts +0 -50
- package/dist/models/backup-storage-unified.d.ts.map +0 -1
- package/dist/models/backup-storage-unified.js +0 -3
- package/dist/models/backup-storage-unified.js.map +0 -1
- package/dist/models/backup.d.ts +0 -38
- package/dist/models/backup.d.ts.map +0 -1
- package/dist/models/backup.js +0 -3
- package/dist/models/backup.js.map +0 -1
- package/dist/models/index.d.ts +0 -5
- package/dist/models/index.d.ts.map +0 -1
- package/dist/models/index.js +0 -21
- package/dist/models/index.js.map +0 -1
- package/dist/models/network-options.d.ts +0 -13
- package/dist/models/network-options.d.ts.map +0 -1
- package/dist/models/network-options.js +0 -3
- package/dist/models/network-options.js.map +0 -1
- package/dist/utils/aes.d.ts +0 -40
- package/dist/utils/aes.d.ts.map +0 -1
- package/dist/utils/aes.js +0 -198
- package/dist/utils/aes.js.map +0 -1
- package/dist/utils/assertString.d.ts +0 -3
- package/dist/utils/assertString.d.ts.map +0 -1
- package/dist/utils/assertString.js +0 -9
- package/dist/utils/assertString.js.map +0 -1
- package/dist/utils/backup.d.ts +0 -21
- package/dist/utils/backup.d.ts.map +0 -1
- package/dist/utils/backup.js +0 -190
- package/dist/utils/backup.js.map +0 -1
- package/dist/utils/equalsPartial.d.ts +0 -3
- package/dist/utils/equalsPartial.d.ts.map +0 -1
- package/dist/utils/equalsPartial.js +0 -12
- package/dist/utils/equalsPartial.js.map +0 -1
- package/dist/utils/index.d.ts +0 -10
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -46
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/isNumberArray.d.ts +0 -3
- package/dist/utils/isNumberArray.d.ts.map +0 -1
- package/dist/utils/isNumberArray.js +0 -7
- package/dist/utils/isNumberArray.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -9
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -14
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/queue.d.ts +0 -12
- package/dist/utils/queue.d.ts.map +0 -1
- package/dist/utils/queue.js +0 -62
- package/dist/utils/queue.js.map +0 -1
- package/dist/utils/realpathSync.d.ts +0 -3
- package/dist/utils/realpathSync.d.ts.map +0 -1
- package/dist/utils/realpathSync.js +0 -13
- package/dist/utils/realpathSync.js.map +0 -1
- package/dist/utils/wait.d.ts +0 -3
- package/dist/utils/wait.d.ts.map +0 -1
- package/dist/utils/wait.js +0 -9
- package/dist/utils/wait.js.map +0 -1
- package/dist/utils/waitress.d.ts +0 -22
- package/dist/utils/waitress.d.ts.map +0 -1
- package/dist/utils/waitress.js +0 -69
- package/dist/utils/waitress.js.map +0 -1
- package/dist/zspec/consts.d.ts +0 -60
- package/dist/zspec/consts.d.ts.map +0 -1
- package/dist/zspec/consts.js +0 -64
- package/dist/zspec/consts.js.map +0 -1
- package/dist/zspec/enums.d.ts +0 -19
- package/dist/zspec/enums.d.ts.map +0 -1
- package/dist/zspec/enums.js +0 -28
- package/dist/zspec/enums.js.map +0 -1
- package/dist/zspec/index.d.ts +0 -4
- package/dist/zspec/index.d.ts.map +0 -1
- package/dist/zspec/index.js +0 -43
- package/dist/zspec/index.js.map +0 -1
- package/dist/zspec/tstypes.d.ts +0 -19
- package/dist/zspec/tstypes.d.ts.map +0 -1
- package/dist/zspec/tstypes.js +0 -3
- package/dist/zspec/tstypes.js.map +0 -1
- package/dist/zspec/utils.d.ts +0 -14
- package/dist/zspec/utils.d.ts.map +0 -1
- package/dist/zspec/utils.js +0 -29
- package/dist/zspec/utils.js.map +0 -1
- package/dist/zspec/zcl/buffaloZcl.d.ts +0 -55
- package/dist/zspec/zcl/definition/cluster.d.ts +0 -3
- package/dist/zspec/zcl/definition/consts.d.ts +0 -9
- package/dist/zspec/zcl/definition/consts.d.ts.map +0 -1
- package/dist/zspec/zcl/definition/consts.js +0 -27
- package/dist/zspec/zcl/definition/consts.js.map +0 -1
- package/dist/zspec/zcl/definition/enums.d.ts +0 -177
- package/dist/zspec/zcl/definition/enums.d.ts.map +0 -1
- package/dist/zspec/zcl/definition/enums.js +0 -187
- package/dist/zspec/zcl/definition/enums.js.map +0 -1
- package/dist/zspec/zcl/definition/foundation.d.ts +0 -11
- package/dist/zspec/zcl/definition/manufacturerCode.d.ts +0 -727
- package/dist/zspec/zcl/definition/manufacturerCode.d.ts.map +0 -1
- package/dist/zspec/zcl/definition/manufacturerCode.js +0 -733
- package/dist/zspec/zcl/definition/manufacturerCode.js.map +0 -1
- package/dist/zspec/zcl/definition/status.d.ts +0 -69
- package/dist/zspec/zcl/definition/status.d.ts.map +0 -1
- package/dist/zspec/zcl/definition/status.js +0 -74
- package/dist/zspec/zcl/definition/status.js.map +0 -1
- package/dist/zspec/zcl/index.d.ts +0 -11
- package/dist/zspec/zcl/utils.d.ts +0 -7
- package/dist/zspec/zcl/zclFrame.d.ts +0 -36
- package/dist/zspec/zcl/zclHeader.d.ts +0 -17
- package/dist/zspec/zcl/zclStatusError.d.ts +0 -6
- package/dist/zspec/zcl/zclStatusError.d.ts.map +0 -1
- package/dist/zspec/zcl/zclStatusError.js +0 -13
- package/dist/zspec/zcl/zclStatusError.js.map +0 -1
- package/dist/zspec/zdo/buffaloZdo.d.ts +0 -438
- package/dist/zspec/zdo/buffaloZdo.d.ts.map +0 -1
- package/dist/zspec/zdo/buffaloZdo.js +0 -1892
- package/dist/zspec/zdo/buffaloZdo.js.map +0 -1
- package/dist/zspec/zdo/definition/clusters.d.ts +0 -624
- package/dist/zspec/zdo/definition/clusters.d.ts.map +0 -1
- package/dist/zspec/zdo/definition/clusters.js +0 -687
- package/dist/zspec/zdo/definition/clusters.js.map +0 -1
- package/dist/zspec/zdo/definition/consts.d.ts +0 -13
- package/dist/zspec/zdo/definition/consts.d.ts.map +0 -1
- package/dist/zspec/zdo/definition/consts.js +0 -16
- package/dist/zspec/zdo/definition/consts.js.map +0 -1
- package/dist/zspec/zdo/definition/enums.d.ts +0 -75
- package/dist/zspec/zdo/definition/enums.d.ts.map +0 -1
- package/dist/zspec/zdo/definition/enums.js +0 -97
- package/dist/zspec/zdo/definition/enums.js.map +0 -1
- package/dist/zspec/zdo/definition/status.d.ts +0 -99
- package/dist/zspec/zdo/definition/status.d.ts.map +0 -1
- package/dist/zspec/zdo/definition/status.js +0 -109
- package/dist/zspec/zdo/definition/status.js.map +0 -1
- package/dist/zspec/zdo/definition/tstypes.d.ts +0 -787
- package/dist/zspec/zdo/definition/tstypes.d.ts.map +0 -1
- package/dist/zspec/zdo/definition/tstypes.js +0 -3
- package/dist/zspec/zdo/definition/tstypes.js.map +0 -1
- package/dist/zspec/zdo/index.d.ts +0 -7
- package/dist/zspec/zdo/index.d.ts.map +0 -1
- package/dist/zspec/zdo/index.js +0 -39
- package/dist/zspec/zdo/index.js.map +0 -1
- package/dist/zspec/zdo/utils.d.ts +0 -25
- package/dist/zspec/zdo/utils.d.ts.map +0 -1
- package/dist/zspec/zdo/utils.js +0 -75
- package/dist/zspec/zdo/utils.js.map +0 -1
- package/dist/zspec/zdo/zdoStatusError.d.ts +0 -6
- package/dist/zspec/zdo/zdoStatusError.d.ts.map +0 -1
- package/dist/zspec/zdo/zdoStatusError.js +0 -13
- package/dist/zspec/zdo/zdoStatusError.js.map +0 -1
- package/typedoc-tsconfig.json +0 -44
|
@@ -15,178 +15,298 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
37
|
};
|
|
28
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
const entity_1 = __importDefault(require("./entity"));
|
|
39
|
+
exports.Device = exports.InterviewState = void 0;
|
|
40
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
32
41
|
const utils_1 = require("../../utils");
|
|
33
|
-
const Zcl = __importStar(require("../../zspec/zcl"));
|
|
34
|
-
const assert_1 = __importDefault(require("assert"));
|
|
35
|
-
const helpers_1 = require("../helpers");
|
|
36
42
|
const logger_1 = require("../../utils/logger");
|
|
43
|
+
const timeService = __importStar(require("../../utils/timeService"));
|
|
44
|
+
const ZSpec = __importStar(require("../../zspec"));
|
|
37
45
|
const enums_1 = require("../../zspec/enums");
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
46
|
+
const Zcl = __importStar(require("../../zspec/zcl"));
|
|
47
|
+
const Zdo = __importStar(require("../../zspec/zdo"));
|
|
48
|
+
const ota_1 = require("../helpers/ota");
|
|
49
|
+
const zclTransactionSequenceNumber_1 = __importDefault(require("../helpers/zclTransactionSequenceNumber"));
|
|
50
|
+
const endpoint_1 = __importDefault(require("./endpoint"));
|
|
51
|
+
const entity_1 = __importDefault(require("./entity"));
|
|
52
|
+
const NS = "zh:controller:device";
|
|
53
|
+
const INTERVIEW_GENBASIC_ATTRIBUTES = [
|
|
54
|
+
"modelId",
|
|
55
|
+
"manufacturerName",
|
|
56
|
+
"powerSource",
|
|
57
|
+
"zclVersion",
|
|
58
|
+
"appVersion",
|
|
59
|
+
"stackVersion",
|
|
60
|
+
"hwVersion",
|
|
61
|
+
"dateCode",
|
|
62
|
+
"swBuildId",
|
|
63
|
+
];
|
|
64
|
+
var InterviewState;
|
|
65
|
+
(function (InterviewState) {
|
|
66
|
+
InterviewState["Pending"] = "PENDING";
|
|
67
|
+
InterviewState["InProgress"] = "IN_PROGRESS";
|
|
68
|
+
InterviewState["Successful"] = "SUCCESSFUL";
|
|
69
|
+
InterviewState["Failed"] = "FAILED";
|
|
70
|
+
})(InterviewState || (exports.InterviewState = InterviewState = {}));
|
|
43
71
|
class Device extends entity_1.default {
|
|
44
72
|
databaseID;
|
|
73
|
+
// biome-ignore lint/style/useNamingConvention: cross-repo impact
|
|
45
74
|
ID;
|
|
46
|
-
|
|
47
|
-
_dateCode;
|
|
75
|
+
#genBasic = {};
|
|
48
76
|
_endpoints;
|
|
49
|
-
_hardwareVersion;
|
|
50
77
|
_ieeeAddr;
|
|
51
|
-
|
|
52
|
-
_interviewing;
|
|
78
|
+
_interviewState;
|
|
53
79
|
_lastSeen;
|
|
54
80
|
_manufacturerID;
|
|
55
|
-
_manufacturerName;
|
|
56
|
-
_modelID;
|
|
57
81
|
_networkAddress;
|
|
58
|
-
_powerSource;
|
|
59
|
-
_softwareBuildID;
|
|
60
|
-
_stackVersion;
|
|
61
82
|
_type;
|
|
62
|
-
_zclVersion;
|
|
63
83
|
_linkquality;
|
|
64
84
|
_skipDefaultResponse;
|
|
65
85
|
_customReadResponse;
|
|
66
|
-
_deleted;
|
|
67
86
|
_lastDefaultResponseSequenceNumber;
|
|
68
87
|
_checkinInterval;
|
|
69
88
|
_pendingRequestTimeout;
|
|
70
89
|
_customClusters = {};
|
|
90
|
+
_gpSecurityKey;
|
|
91
|
+
#scheduledOta;
|
|
92
|
+
#otaInProgress = false;
|
|
71
93
|
// Getters/setters
|
|
72
|
-
get ieeeAddr() {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
set
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
get
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
get
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
get
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
get ieeeAddr() {
|
|
95
|
+
return this._ieeeAddr;
|
|
96
|
+
}
|
|
97
|
+
set ieeeAddr(ieeeAddr) {
|
|
98
|
+
this._ieeeAddr = ieeeAddr;
|
|
99
|
+
}
|
|
100
|
+
get applicationVersion() {
|
|
101
|
+
return this.#genBasic.appVersion;
|
|
102
|
+
}
|
|
103
|
+
set applicationVersion(version) {
|
|
104
|
+
this.#genBasic.appVersion = version;
|
|
105
|
+
}
|
|
106
|
+
get endpoints() {
|
|
107
|
+
return this._endpoints;
|
|
108
|
+
}
|
|
109
|
+
get interviewState() {
|
|
110
|
+
return this._interviewState;
|
|
111
|
+
}
|
|
112
|
+
get lastSeen() {
|
|
113
|
+
return this._lastSeen;
|
|
114
|
+
}
|
|
115
|
+
get manufacturerID() {
|
|
116
|
+
return this._manufacturerID;
|
|
117
|
+
}
|
|
118
|
+
get isDeleted() {
|
|
119
|
+
return Device.deletedDevices.get(this.databaseID)?.has(this.ieeeAddr) ?? false;
|
|
120
|
+
}
|
|
121
|
+
set type(type) {
|
|
122
|
+
this._type = type;
|
|
123
|
+
}
|
|
124
|
+
get type() {
|
|
125
|
+
return this._type;
|
|
126
|
+
}
|
|
127
|
+
get dateCode() {
|
|
128
|
+
return this.#genBasic.dateCode;
|
|
129
|
+
}
|
|
130
|
+
set dateCode(code) {
|
|
131
|
+
this.#genBasic.dateCode = code;
|
|
132
|
+
}
|
|
133
|
+
set hardwareVersion(version) {
|
|
134
|
+
this.#genBasic.hwVersion = version;
|
|
135
|
+
}
|
|
136
|
+
get hardwareVersion() {
|
|
137
|
+
return this.#genBasic.hwVersion;
|
|
138
|
+
}
|
|
139
|
+
get manufacturerName() {
|
|
140
|
+
return this.#genBasic.manufacturerName;
|
|
141
|
+
}
|
|
142
|
+
set manufacturerName(name) {
|
|
143
|
+
this.#genBasic.manufacturerName = name;
|
|
144
|
+
}
|
|
145
|
+
set modelID(id) {
|
|
146
|
+
this.#genBasic.modelId = id;
|
|
147
|
+
}
|
|
148
|
+
get modelID() {
|
|
149
|
+
return this.#genBasic.modelId;
|
|
150
|
+
}
|
|
151
|
+
get networkAddress() {
|
|
152
|
+
return this._networkAddress;
|
|
153
|
+
}
|
|
93
154
|
set networkAddress(networkAddress) {
|
|
155
|
+
Device.nwkToIeeeCache.get(this.databaseID)?.delete(this._networkAddress);
|
|
94
156
|
this._networkAddress = networkAddress;
|
|
157
|
+
Device.nwkToIeeeCache.get(this.databaseID)?.set(this._networkAddress, this.ieeeAddr);
|
|
95
158
|
for (const endpoint of this._endpoints) {
|
|
96
159
|
endpoint.deviceNetworkAddress = networkAddress;
|
|
97
160
|
}
|
|
98
161
|
}
|
|
99
|
-
get powerSource() {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
162
|
+
get powerSource() {
|
|
163
|
+
return this.#genBasic.powerSource ? Zcl.POWER_SOURCES[this.#genBasic.powerSource] : undefined;
|
|
164
|
+
}
|
|
165
|
+
set powerSource(source) {
|
|
166
|
+
if (typeof source === "number") {
|
|
167
|
+
this.#genBasic.powerSource = source & ~(1 << 7);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
for (const key in Zcl.POWER_SOURCES) {
|
|
171
|
+
const val = Zcl.POWER_SOURCES[key];
|
|
172
|
+
if (val === source) {
|
|
173
|
+
this.#genBasic.powerSource = Number(key);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
get softwareBuildID() {
|
|
180
|
+
return this.#genBasic.swBuildId;
|
|
181
|
+
}
|
|
182
|
+
set softwareBuildID(id) {
|
|
183
|
+
this.#genBasic.swBuildId = id;
|
|
184
|
+
}
|
|
185
|
+
get stackVersion() {
|
|
186
|
+
return this.#genBasic.stackVersion;
|
|
187
|
+
}
|
|
188
|
+
set stackVersion(version) {
|
|
189
|
+
this.#genBasic.stackVersion = version;
|
|
190
|
+
}
|
|
191
|
+
get zclVersion() {
|
|
192
|
+
return this.#genBasic.zclVersion;
|
|
193
|
+
}
|
|
194
|
+
set zclVersion(version) {
|
|
195
|
+
this.#genBasic.zclVersion = version;
|
|
196
|
+
}
|
|
197
|
+
get linkquality() {
|
|
198
|
+
return this._linkquality;
|
|
199
|
+
}
|
|
200
|
+
set linkquality(linkquality) {
|
|
201
|
+
this._linkquality = linkquality;
|
|
202
|
+
}
|
|
203
|
+
get skipDefaultResponse() {
|
|
204
|
+
return this._skipDefaultResponse;
|
|
205
|
+
}
|
|
206
|
+
set skipDefaultResponse(skipDefaultResponse) {
|
|
207
|
+
this._skipDefaultResponse = skipDefaultResponse;
|
|
208
|
+
}
|
|
209
|
+
get customReadResponse() {
|
|
210
|
+
return this._customReadResponse;
|
|
211
|
+
}
|
|
212
|
+
set customReadResponse(customReadResponse) {
|
|
213
|
+
this._customReadResponse = customReadResponse;
|
|
214
|
+
}
|
|
215
|
+
get checkinInterval() {
|
|
216
|
+
return this._checkinInterval;
|
|
217
|
+
}
|
|
116
218
|
set checkinInterval(checkinInterval) {
|
|
117
219
|
this._checkinInterval = checkinInterval;
|
|
118
220
|
this.resetPendingRequestTimeout();
|
|
119
221
|
}
|
|
120
|
-
get pendingRequestTimeout() {
|
|
121
|
-
|
|
122
|
-
|
|
222
|
+
get pendingRequestTimeout() {
|
|
223
|
+
return this._pendingRequestTimeout;
|
|
224
|
+
}
|
|
225
|
+
set pendingRequestTimeout(pendingRequestTimeout) {
|
|
226
|
+
this._pendingRequestTimeout = pendingRequestTimeout;
|
|
227
|
+
}
|
|
228
|
+
get customClusters() {
|
|
229
|
+
return this._customClusters;
|
|
230
|
+
}
|
|
231
|
+
get gpSecurityKey() {
|
|
232
|
+
return this._gpSecurityKey;
|
|
233
|
+
}
|
|
234
|
+
get genBasic() {
|
|
235
|
+
return this.#genBasic;
|
|
236
|
+
}
|
|
237
|
+
get scheduledOta() {
|
|
238
|
+
return this.#scheduledOta;
|
|
239
|
+
}
|
|
240
|
+
get otaInProgress() {
|
|
241
|
+
return this.#otaInProgress;
|
|
242
|
+
}
|
|
123
243
|
meta;
|
|
124
244
|
// This lookup contains all devices that are queried from the database, this is to ensure that always
|
|
125
245
|
// the same instance is returned.
|
|
126
246
|
static devices = new Map();
|
|
127
|
-
static
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
zclVersion: { key: 'zclVersion', set: (v, d) => { d.zclVersion = v; } },
|
|
132
|
-
appVersion: { key: 'applicationVersion', set: (v, d) => { d.applicationVersion = v; } },
|
|
133
|
-
stackVersion: { key: 'stackVersion', set: (v, d) => { d.stackVersion = v; } },
|
|
134
|
-
hwVersion: { key: 'hardwareVersion', set: (v, d) => { d.hardwareVersion = v; } },
|
|
135
|
-
dateCode: { key: 'dateCode', set: (v, d) => { d.dateCode = v; } },
|
|
136
|
-
swBuildId: { key: 'softwareBuildID', set: (v, d) => { d.softwareBuildID = v; } },
|
|
137
|
-
};
|
|
138
|
-
constructor(databaseID, ID, type, ieeeAddr, networkAddress, manufacturerID, endpoints, manufacturerName, powerSource, modelID, applicationVersion, stackVersion, zclVersion, hardwareVersion, dateCode, softwareBuildID, interviewCompleted, meta, lastSeen, checkinInterval, pendingRequestTimeout) {
|
|
247
|
+
static loadedFromDatabase = false;
|
|
248
|
+
static deletedDevices = new Map();
|
|
249
|
+
static nwkToIeeeCache = new Map();
|
|
250
|
+
constructor(databaseID, id, type, ieeeAddr, networkAddress, manufacturerID, endpoints, manufacturerName, powerSource, modelID, applicationVersion, stackVersion, zclVersion, hardwareVersion, dateCode, softwareBuildID, interviewState, meta, lastSeen, checkinInterval, pendingRequestTimeout, gpSecurityKey, scheduledOta) {
|
|
139
251
|
super();
|
|
140
252
|
this.databaseID = databaseID;
|
|
141
|
-
this.ID =
|
|
253
|
+
this.ID = id;
|
|
142
254
|
this._type = type;
|
|
143
|
-
this.
|
|
255
|
+
this._ieeeAddr = ieeeAddr;
|
|
144
256
|
this._networkAddress = networkAddress;
|
|
145
257
|
this._manufacturerID = manufacturerID;
|
|
146
258
|
this._endpoints = endpoints;
|
|
147
|
-
this.
|
|
148
|
-
this.
|
|
149
|
-
this.
|
|
150
|
-
this.
|
|
151
|
-
this.
|
|
152
|
-
this.
|
|
153
|
-
this.
|
|
154
|
-
this.
|
|
155
|
-
this.
|
|
156
|
-
this.
|
|
157
|
-
this._interviewing = false;
|
|
259
|
+
this.#genBasic.manufacturerName = manufacturerName;
|
|
260
|
+
this.powerSource = powerSource ?? Zcl.PowerSource.Unknown;
|
|
261
|
+
this.#genBasic.modelId = modelID;
|
|
262
|
+
this.#genBasic.appVersion = applicationVersion;
|
|
263
|
+
this.#genBasic.stackVersion = stackVersion;
|
|
264
|
+
this.#genBasic.zclVersion = zclVersion;
|
|
265
|
+
this.#genBasic.hwVersion = hardwareVersion;
|
|
266
|
+
this.#genBasic.dateCode = dateCode;
|
|
267
|
+
this.#genBasic.swBuildId = softwareBuildID;
|
|
268
|
+
this._interviewState = interviewState;
|
|
158
269
|
this._skipDefaultResponse = false;
|
|
159
270
|
this.meta = meta;
|
|
160
271
|
this._lastSeen = lastSeen;
|
|
161
272
|
this._checkinInterval = checkinInterval;
|
|
162
273
|
this._pendingRequestTimeout = pendingRequestTimeout;
|
|
274
|
+
this._gpSecurityKey = gpSecurityKey;
|
|
275
|
+
this.#scheduledOta = scheduledOta;
|
|
163
276
|
}
|
|
164
|
-
createEndpoint(
|
|
165
|
-
if (this.getEndpoint(
|
|
166
|
-
throw new Error(`Device '${this.ieeeAddr}' already has an endpoint '${
|
|
277
|
+
createEndpoint(id) {
|
|
278
|
+
if (this.getEndpoint(id)) {
|
|
279
|
+
throw new Error(`Device '${this.ieeeAddr}' already has an endpoint '${id}'`);
|
|
167
280
|
}
|
|
168
|
-
const endpoint = endpoint_1.default.create(this.databaseID,
|
|
281
|
+
const endpoint = endpoint_1.default.create(this.databaseID, id, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr);
|
|
169
282
|
this.endpoints.push(endpoint);
|
|
170
283
|
this.save();
|
|
171
284
|
return endpoint;
|
|
172
285
|
}
|
|
173
286
|
changeIeeeAddress(ieeeAddr) {
|
|
174
|
-
|
|
287
|
+
Device.devices.get(this.databaseID)?.delete(this.ieeeAddr);
|
|
175
288
|
this.ieeeAddr = ieeeAddr;
|
|
176
|
-
Device.devices.get(this.databaseID)
|
|
177
|
-
|
|
289
|
+
Device.devices.get(this.databaseID)?.set(this.ieeeAddr, this);
|
|
290
|
+
Device.nwkToIeeeCache.get(this.databaseID)?.set(this.networkAddress, this.ieeeAddr);
|
|
291
|
+
for (const ep of this.endpoints) {
|
|
292
|
+
ep.deviceIeeeAddress = ieeeAddr;
|
|
293
|
+
}
|
|
178
294
|
this.save();
|
|
179
295
|
}
|
|
180
|
-
getEndpoint(
|
|
181
|
-
return this.endpoints.find((e) => e.ID ===
|
|
296
|
+
getEndpoint(id) {
|
|
297
|
+
return this.endpoints.find((e) => e.ID === id);
|
|
182
298
|
}
|
|
183
299
|
// There might be multiple endpoints with same DeviceId but it is not supported and first endpoint is returned
|
|
184
300
|
getEndpointByDeviceType(deviceType) {
|
|
185
301
|
const deviceID = Zcl.ENDPOINT_DEVICE_TYPE[deviceType];
|
|
186
302
|
return this.endpoints.find((d) => d.deviceID === deviceID);
|
|
187
303
|
}
|
|
304
|
+
updateGenBasic(data) {
|
|
305
|
+
Object.assign(this.#genBasic, data);
|
|
306
|
+
}
|
|
188
307
|
implicitCheckin() {
|
|
189
|
-
|
|
308
|
+
// No need to do anythign in `catch` as `endpoint.sendRequest` already logs failures.
|
|
309
|
+
Promise.allSettled(this.endpoints.map((e) => e.sendPendingRequests(false))).catch(() => { });
|
|
190
310
|
}
|
|
191
311
|
updateLastSeen() {
|
|
192
312
|
this._lastSeen = Date.now();
|
|
@@ -194,147 +314,172 @@ class Device extends entity_1.default {
|
|
|
194
314
|
resetPendingRequestTimeout() {
|
|
195
315
|
// pendingRequestTimeout can be changed dynamically at runtime, and it is not persisted.
|
|
196
316
|
// Default timeout is one checkin interval in milliseconds.
|
|
197
|
-
this._pendingRequestTimeout = this._checkinInterval * 1000;
|
|
317
|
+
this._pendingRequestTimeout = (this._checkinInterval ?? 0) * 1000;
|
|
198
318
|
}
|
|
199
319
|
hasPendingRequests() {
|
|
200
|
-
return this.endpoints.find(e => e.hasPendingRequests()) !== undefined;
|
|
320
|
+
return this.endpoints.find((e) => e.hasPendingRequests()) !== undefined;
|
|
201
321
|
}
|
|
202
322
|
async onZclData(dataPayload, frame, endpoint) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
timeZone: ((new Date()).getTimezoneOffset() * -1) * 60,
|
|
225
|
-
localTime: time - (new Date()).getTimezoneOffset() * 60,
|
|
226
|
-
lastSetTime: time,
|
|
227
|
-
validUntilTime: time + (24 * 60 * 60), // valid for 24 hours
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
};
|
|
231
|
-
if (frame.cluster.name in attributes) {
|
|
232
|
-
const response = {};
|
|
233
|
-
for (const entry of frame.payload) {
|
|
234
|
-
if (frame.cluster.hasAttribute(entry.attrId)) {
|
|
235
|
-
const name = frame.cluster.getAttribute(entry.attrId).name;
|
|
236
|
-
if (name in attributes[frame.cluster.name].attributes) {
|
|
323
|
+
if (!Device.devices.get(this.databaseID)?.has(this.ieeeAddr)) {
|
|
324
|
+
// prevent race conditions where device gets deleted during processing
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (frame.header.isGlobal) {
|
|
328
|
+
// Response to read requests
|
|
329
|
+
if (frame.command.name === "read" && !this._customReadResponse?.(frame, endpoint)) {
|
|
330
|
+
const attributes = {
|
|
331
|
+
...endpoint.clusters,
|
|
332
|
+
};
|
|
333
|
+
const isTimeReadRequest = dataPayload.clusterID === Zcl.Clusters.genTime.ID;
|
|
334
|
+
if (isTimeReadRequest) {
|
|
335
|
+
attributes.genTime = {
|
|
336
|
+
attributes: timeService.getTimeClusterAttributes(),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
if (frame.cluster.name in attributes) {
|
|
340
|
+
const response = {};
|
|
341
|
+
for (const entry of frame.payload) {
|
|
342
|
+
const name = frame.cluster.getAttribute(entry.attrId)?.name;
|
|
343
|
+
if (name && name in attributes[frame.cluster.name].attributes) {
|
|
237
344
|
response[name] = attributes[frame.cluster.name].attributes[name];
|
|
238
345
|
}
|
|
239
346
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
347
|
+
try {
|
|
348
|
+
await endpoint.readResponse(frame.cluster.ID, frame.header.transactionSequenceNumber, response, {
|
|
349
|
+
srcEndpoint: dataPayload.destinationEndpoint,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
logger_1.logger.error(`Read response to ${this.ieeeAddr} failed (${error.message})`, NS);
|
|
354
|
+
}
|
|
246
355
|
}
|
|
247
356
|
}
|
|
248
357
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
};
|
|
257
|
-
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: accepting fast-poll`, NS);
|
|
258
|
-
await endpoint.command(frame.cluster.ID, 'checkinRsp', payload, { sendPolicy: 'immediate' });
|
|
259
|
-
// This is a good time to read the checkin interval if we haven't stored it previously
|
|
260
|
-
if (this._checkinInterval === undefined) {
|
|
261
|
-
const pollPeriod = await endpoint.read('genPollCtrl', ['checkinInterval'], { sendPolicy: 'immediate' });
|
|
262
|
-
this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds
|
|
263
|
-
this.resetPendingRequestTimeout();
|
|
264
|
-
logger_1.logger.debug(`Request Queue (${this.ieeeAddr}): default expiration timeout set to ${this.pendingRequestTimeout}`, NS);
|
|
358
|
+
else if (frame.header.isSpecific) {
|
|
359
|
+
switch (frame.cluster.name) {
|
|
360
|
+
case "ssIasZone": {
|
|
361
|
+
if (frame.command.name === "enrollReq") {
|
|
362
|
+
// Respond to enroll requests
|
|
363
|
+
logger_1.logger.debug(`IAS - '${this.ieeeAddr}' responding to enroll response`, NS);
|
|
364
|
+
await endpoint.command("ssIasZone", "enrollRsp", { enrollrspcode: 0, zoneid: 23 }, { disableDefaultResponse: true });
|
|
265
365
|
}
|
|
266
|
-
|
|
267
|
-
// We *must* end fast-poll when we're done sending things. Otherwise
|
|
268
|
-
// we cause undue power-drain.
|
|
269
|
-
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: stopping fast-poll`, NS);
|
|
270
|
-
await endpoint.command(frame.cluster.ID, 'fastPollStop', {}, { sendPolicy: 'immediate' });
|
|
366
|
+
break;
|
|
271
367
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
368
|
+
case "genPollCtrl": {
|
|
369
|
+
if (frame.command.name === "checkin") {
|
|
370
|
+
// Handle check-in from sleeping end devices
|
|
371
|
+
try {
|
|
372
|
+
if (this.hasPendingRequests() || this._checkinInterval === undefined) {
|
|
373
|
+
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: accepting fast-poll`, NS);
|
|
374
|
+
await endpoint.command(frame.cluster.name, "checkinRsp", {
|
|
375
|
+
startFastPolling: 1,
|
|
376
|
+
fastPollTimeout: 0,
|
|
377
|
+
}, { sendPolicy: "immediate" });
|
|
378
|
+
// This is a good time to read the checkin interval if we haven't stored it previously
|
|
379
|
+
if (this._checkinInterval === undefined) {
|
|
380
|
+
const pollPeriod = await endpoint.read("genPollCtrl", ["checkinInterval"], { sendPolicy: "immediate" });
|
|
381
|
+
this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds
|
|
382
|
+
this.resetPendingRequestTimeout();
|
|
383
|
+
logger_1.logger.debug(`Request Queue (${this.ieeeAddr}): default expiration timeout set to ${this.pendingRequestTimeout}`, NS);
|
|
384
|
+
}
|
|
385
|
+
await Promise.all(this.endpoints.map(async (e) => await e.sendPendingRequests(true)));
|
|
386
|
+
// We *must* end fast-poll when we're done sending things. Otherwise
|
|
387
|
+
// we cause undue power-drain.
|
|
388
|
+
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: stopping fast-poll`, NS);
|
|
389
|
+
await endpoint.command(frame.cluster.name, "fastPollStop", {}, { sendPolicy: "immediate" });
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: declining fast-poll`, NS);
|
|
393
|
+
await endpoint.command(frame.cluster.name, "checkinRsp", {
|
|
394
|
+
startFastPolling: 0,
|
|
395
|
+
fastPollTimeout: 0,
|
|
396
|
+
}, { sendPolicy: "immediate" });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
logger_1.logger.error(`Handling of poll check-in from ${this.ieeeAddr} failed (${error.message})`, NS);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
279
404
|
}
|
|
280
405
|
}
|
|
281
|
-
catch (error) {
|
|
282
|
-
/* istanbul ignore next */
|
|
283
|
-
logger_1.logger.error(`Handling of poll check-in from ${this.ieeeAddr} failed`, NS);
|
|
284
|
-
}
|
|
285
406
|
}
|
|
286
407
|
// Send a default response if necessary.
|
|
287
|
-
const isDefaultResponse = frame.header.isGlobal && frame.command.name ===
|
|
288
|
-
const commandHasResponse = frame.command.
|
|
408
|
+
const isDefaultResponse = frame.header.isGlobal && frame.command.name === "defaultRsp";
|
|
409
|
+
const commandHasResponse = frame.command.response !== undefined;
|
|
289
410
|
const disableDefaultResponse = frame.header.frameControl.disableDefaultResponse;
|
|
290
|
-
/*
|
|
291
|
-
const disableTuyaDefaultResponse =
|
|
411
|
+
/* v8 ignore next */
|
|
412
|
+
const disableTuyaDefaultResponse = this.manufacturerName?.startsWith("_TZ") && process.env.DISABLE_TUYA_DEFAULT_RESPONSE;
|
|
292
413
|
// Sometimes messages are received twice, prevent responding twice
|
|
293
414
|
const alreadyResponded = this._lastDefaultResponseSequenceNumber === frame.header.transactionSequenceNumber;
|
|
294
|
-
if (this.type !==
|
|
295
|
-
!
|
|
415
|
+
if (this.type !== "GreenPower" &&
|
|
416
|
+
!dataPayload.wasBroadcast &&
|
|
417
|
+
!disableDefaultResponse &&
|
|
418
|
+
!isDefaultResponse &&
|
|
419
|
+
!commandHasResponse &&
|
|
420
|
+
!this._skipDefaultResponse &&
|
|
421
|
+
!alreadyResponded &&
|
|
422
|
+
!disableTuyaDefaultResponse) {
|
|
296
423
|
try {
|
|
297
424
|
this._lastDefaultResponseSequenceNumber = frame.header.transactionSequenceNumber;
|
|
298
425
|
// In the ZCL it is not documented what the direction of the default response should be
|
|
299
426
|
// In https://github.com/Koenkk/zigbee2mqtt/issues/18096 a commandResponse (SERVER_TO_CLIENT)
|
|
300
427
|
// is send and the device expects a CLIENT_TO_SERVER back.
|
|
301
428
|
// Previously SERVER_TO_CLIENT was always used.
|
|
302
|
-
// Therefore for non-global commands we inverse the direction.
|
|
303
|
-
const direction = frame.header.isGlobal
|
|
304
|
-
? Zcl.Direction.SERVER_TO_CLIENT
|
|
429
|
+
// Therefore for non-global commands we inverse the direction.
|
|
430
|
+
const direction = frame.header.isGlobal
|
|
431
|
+
? Zcl.Direction.SERVER_TO_CLIENT
|
|
432
|
+
: frame.header.frameControl.direction === Zcl.Direction.CLIENT_TO_SERVER
|
|
433
|
+
? Zcl.Direction.SERVER_TO_CLIENT
|
|
434
|
+
: Zcl.Direction.CLIENT_TO_SERVER;
|
|
305
435
|
await endpoint.defaultResponse(frame.command.ID, 0, frame.cluster.ID, frame.header.transactionSequenceNumber, { direction });
|
|
306
436
|
}
|
|
307
437
|
catch (error) {
|
|
308
|
-
logger_1.logger.
|
|
438
|
+
logger_1.logger.debug(`Default response to ${this.ieeeAddr} failed (${error})`, NS);
|
|
309
439
|
}
|
|
310
440
|
}
|
|
311
441
|
}
|
|
312
442
|
/*
|
|
313
443
|
* CRUD
|
|
314
444
|
*/
|
|
445
|
+
/**
|
|
446
|
+
* Reset runtime lookups.
|
|
447
|
+
*/
|
|
448
|
+
static resetCache() {
|
|
449
|
+
Device.devices.clear();
|
|
450
|
+
Device.loadedFromDatabase = false;
|
|
451
|
+
Device.deletedDevices.clear();
|
|
452
|
+
Device.nwkToIeeeCache.clear();
|
|
453
|
+
}
|
|
315
454
|
static fromDatabaseEntry(entry, databaseID) {
|
|
316
455
|
const networkAddress = entry.nwkAddr;
|
|
317
456
|
const ieeeAddr = entry.ieeeAddr;
|
|
318
|
-
const endpoints =
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
457
|
+
const endpoints = [];
|
|
458
|
+
for (const id in entry.endpoints) {
|
|
459
|
+
endpoints.push(endpoint_1.default.fromDatabaseRecord(entry.endpoints[id], networkAddress, ieeeAddr, databaseID));
|
|
460
|
+
}
|
|
461
|
+
const meta = entry.meta ?? {};
|
|
462
|
+
if (entry.type === "Group") {
|
|
463
|
+
throw new Error("Cannot load device from group");
|
|
324
464
|
}
|
|
325
465
|
// default: no timeout (messages expire immediately after first send attempt)
|
|
326
466
|
let pendingRequestTimeout = 0;
|
|
327
|
-
if (
|
|
467
|
+
if (endpoints.filter((e) => e.inputClusters.includes(Zcl.Clusters.genPollCtrl.ID)).length > 0) {
|
|
328
468
|
// default for devices that support genPollCtrl cluster (RX off when idle): 1 day
|
|
329
469
|
pendingRequestTimeout = 86400000;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
470
|
+
}
|
|
471
|
+
// always load value from database available (modernExtend.quirkCheckinInterval() exists for devices without genPollCtl)
|
|
472
|
+
if (entry.checkinInterval !== undefined) {
|
|
473
|
+
// if the checkin interval is known, messages expire by default after one checkin interval
|
|
474
|
+
pendingRequestTimeout = entry.checkinInterval * 1000; // milliseconds
|
|
335
475
|
}
|
|
336
476
|
logger_1.logger.debug(`Request Queue (${ieeeAddr}): default expiration timeout set to ${pendingRequestTimeout}`, NS);
|
|
337
|
-
|
|
477
|
+
// Migrate interviewCompleted to interviewState
|
|
478
|
+
if (!entry.interviewState) {
|
|
479
|
+
entry.interviewState = entry.interviewCompleted ? InterviewState.Successful : InterviewState.Failed;
|
|
480
|
+
logger_1.logger.debug(`Migrated interviewState for '${ieeeAddr}': ${entry.interviewCompleted} -> ${entry.interviewState}`, NS);
|
|
481
|
+
}
|
|
482
|
+
return new Device(databaseID, entry.id, entry.type, ieeeAddr, networkAddress, entry.manufId, endpoints, entry.manufName, entry.powerSource, entry.modelId, entry.appVersion, entry.stackVersion, entry.zclVersion, entry.hwVersion, entry.dateCode, entry.swBuildId, entry.interviewState, meta, entry.lastSeen, entry.checkinInterval, pendingRequestTimeout, entry.gpSecurityKey, entry.scheduledOta);
|
|
338
483
|
}
|
|
339
484
|
toDatabaseEntry() {
|
|
340
485
|
const epList = this.endpoints.map((e) => e.ID);
|
|
@@ -343,115 +488,161 @@ class Device extends entity_1.default {
|
|
|
343
488
|
endpoints[endpoint.ID] = endpoint.toDatabaseRecord();
|
|
344
489
|
}
|
|
345
490
|
return {
|
|
346
|
-
id: this.ID,
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
491
|
+
id: this.ID,
|
|
492
|
+
type: this.type,
|
|
493
|
+
ieeeAddr: this.ieeeAddr,
|
|
494
|
+
nwkAddr: this.networkAddress,
|
|
495
|
+
manufId: this.manufacturerID,
|
|
496
|
+
manufName: this.manufacturerName,
|
|
497
|
+
powerSource: this.powerSource,
|
|
498
|
+
modelId: this.modelID,
|
|
499
|
+
epList,
|
|
500
|
+
endpoints,
|
|
501
|
+
appVersion: this.applicationVersion,
|
|
502
|
+
stackVersion: this.stackVersion,
|
|
503
|
+
hwVersion: this.hardwareVersion,
|
|
504
|
+
dateCode: this.dateCode,
|
|
505
|
+
swBuildId: this.softwareBuildID,
|
|
506
|
+
zclVersion: this.zclVersion,
|
|
507
|
+
/** @deprecated Keep interviewCompleted for backwards compatibility (in case zh gets downgraded) */
|
|
508
|
+
interviewCompleted: this.interviewState === InterviewState.Successful,
|
|
509
|
+
interviewState: this.interviewState === InterviewState.InProgress ? InterviewState.Pending : this.interviewState,
|
|
510
|
+
meta: this.meta,
|
|
511
|
+
lastSeen: this.lastSeen,
|
|
512
|
+
checkinInterval: this.checkinInterval,
|
|
513
|
+
gpSecurityKey: this.gpSecurityKey,
|
|
514
|
+
scheduledOta: this.scheduledOta,
|
|
352
515
|
};
|
|
353
516
|
}
|
|
354
517
|
save(writeDatabase = true) {
|
|
355
|
-
entity_1.default.getDatabaseByID(this.databaseID)
|
|
518
|
+
entity_1.default.getDatabaseByID(this.databaseID)?.update(this.toDatabaseEntry(), writeDatabase);
|
|
356
519
|
}
|
|
357
520
|
static loadFromDatabaseIfNecessary() {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
Device.devices.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
521
|
+
if (!Device.loadedFromDatabase) {
|
|
522
|
+
entity_1.default.databases.forEach(database => {
|
|
523
|
+
if (!Device.devices.has(database.id)) {
|
|
524
|
+
Device.devices.set(database.id, new Map());
|
|
525
|
+
Device.deletedDevices.set(database.id, new Map());
|
|
526
|
+
Device.nwkToIeeeCache.set(database.id, new Map());
|
|
527
|
+
const entries = database.getEntriesIterator(['Coordinator', 'EndDevice', 'Router', 'GreenPower', 'Unknown']);
|
|
528
|
+
for (const entry of entries) {
|
|
529
|
+
const device = Device.fromDatabaseEntry(entry, database.id);
|
|
530
|
+
Device.devices.get(database.id).set(device.ieeeAddr, device);
|
|
531
|
+
Device.nwkToIeeeCache.get(database.id).set(device.networkAddress, device.ieeeAddr);
|
|
532
|
+
}
|
|
365
533
|
}
|
|
366
|
-
}
|
|
367
|
-
|
|
534
|
+
});
|
|
535
|
+
Device.loadedFromDatabase = true;
|
|
536
|
+
}
|
|
368
537
|
}
|
|
369
538
|
static find(databaseID, ieeeOrNwkAddress, includeDeleted = false) {
|
|
370
|
-
return typeof ieeeOrNwkAddress ===
|
|
371
|
-
|
|
539
|
+
return typeof ieeeOrNwkAddress === "string"
|
|
540
|
+
? Device.byIeeeAddr(databaseID, ieeeOrNwkAddress, includeDeleted)
|
|
541
|
+
: Device.byNetworkAddress(databaseID, ieeeOrNwkAddress, includeDeleted);
|
|
372
542
|
}
|
|
373
543
|
static byIeeeAddr(databaseID, ieeeAddr, includeDeleted = false) {
|
|
374
544
|
Device.loadFromDatabaseIfNecessary();
|
|
375
|
-
const device = Device.devices.get(databaseID)
|
|
376
|
-
return
|
|
545
|
+
const device = Device.devices.get(databaseID)?.get(ieeeAddr);
|
|
546
|
+
return includeDeleted ? (Device.deletedDevices.get(databaseID)?.get(ieeeAddr) ?? device) : device;
|
|
377
547
|
}
|
|
378
|
-
static byNetworkAddress(
|
|
548
|
+
static byNetworkAddress(databaseID, networkAddress, includeDeleted = false) {
|
|
379
549
|
Device.loadFromDatabaseIfNecessary();
|
|
380
|
-
|
|
550
|
+
const ieeeAddr = Device.nwkToIeeeCache.get(databaseID)?.get(networkAddress);
|
|
551
|
+
return ieeeAddr ? Device.byIeeeAddr(databaseID, ieeeAddr, includeDeleted) : undefined;
|
|
381
552
|
}
|
|
382
|
-
static byType(
|
|
553
|
+
static byType(databaseID, type) {
|
|
383
554
|
return Device.allByDatabaseID(databaseID).filter(d => d.type === type);
|
|
384
555
|
}
|
|
385
|
-
static
|
|
556
|
+
static allByDatabaseID(databaseID) {
|
|
386
557
|
Device.loadFromDatabaseIfNecessary();
|
|
387
|
-
|
|
388
|
-
Device.devices.forEach(deviceDB => {
|
|
389
|
-
devices.push(...Object.values(deviceDB).filter(d => !d._deleted));
|
|
390
|
-
});
|
|
391
|
-
return devices;
|
|
558
|
+
return Array.from(Device.devices.get(databaseID)?.values() ?? []);
|
|
392
559
|
}
|
|
393
|
-
|
|
560
|
+
/** Check if a device is explicitly deleted */
|
|
561
|
+
static isDeletedByIeeeAddr(databaseID, ieeeAddr) {
|
|
394
562
|
Device.loadFromDatabaseIfNecessary();
|
|
395
|
-
return
|
|
563
|
+
return Device.deletedDevices.get(databaseID)?.has(ieeeAddr) ?? false;
|
|
396
564
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
565
|
+
/** Check if a device is explicitly deleted */
|
|
566
|
+
static isDeletedByNetworkAddress(databaseID, networkAddress) {
|
|
567
|
+
Device.loadFromDatabaseIfNecessary();
|
|
568
|
+
const ieeeAddr = Device.nwkToIeeeCache.get(databaseID)?.get(networkAddress);
|
|
569
|
+
return ieeeAddr ? Device.deletedDevices.get(databaseID)?.has(ieeeAddr) ?? false : false;
|
|
402
570
|
}
|
|
403
|
-
static
|
|
571
|
+
// public static all(): Device[] {
|
|
572
|
+
// Device.loadFromDatabaseIfNecessary();
|
|
573
|
+
// return Array.from(Device.devices.values());
|
|
574
|
+
// }
|
|
575
|
+
static *allIterator(databaseID, predicate) {
|
|
404
576
|
Device.loadFromDatabaseIfNecessary();
|
|
577
|
+
for (const device of Device.allByDatabaseID(databaseID)) {
|
|
578
|
+
if (!predicate || predicate(device)) {
|
|
579
|
+
yield device;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
undelete() {
|
|
584
|
+
if (Device.deletedDevices.get(this.databaseID)?.delete(this.ieeeAddr)) {
|
|
585
|
+
Device.devices.get(this.databaseID)?.set(this.ieeeAddr, this);
|
|
586
|
+
entity_1.default.getDatabaseByID(this.databaseID)?.insert(this.toDatabaseEntry());
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
throw new Error(`Device '${this.ieeeAddr}' is not deleted`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
static create(type, ieeeAddr, networkAddress, manufacturerID, manufacturerName, powerSource, modelID, interviewState, gpSecurityKey, databaseID) {
|
|
593
|
+
Device.loadFromDatabaseIfNecessary();
|
|
594
|
+
if (Device.devices.get(databaseID)?.has(ieeeAddr)) {
|
|
595
|
+
throw new Error(`Device with IEEE address '${ieeeAddr}' already exists`);
|
|
596
|
+
}
|
|
405
597
|
const database = entity_1.default.getDatabaseByID(databaseID);
|
|
406
|
-
if (
|
|
407
|
-
throw new Error(`
|
|
598
|
+
if (!database) {
|
|
599
|
+
throw new Error(`Database with ID '${databaseID}' not found`);
|
|
408
600
|
}
|
|
409
|
-
const endpointsMapped = endpoints.map((e) => {
|
|
410
|
-
return endpoint_1.default.create(databaseID, e.ID, e.profileID, e.deviceID, e.inputClusters, e.outputClusters, networkAddress, ieeeAddr);
|
|
411
|
-
});
|
|
412
601
|
const ID = database.newID();
|
|
413
|
-
const device = new Device(databaseID, ID, type, ieeeAddr, networkAddress, manufacturerID,
|
|
602
|
+
const device = new Device(databaseID, ID, type, ieeeAddr, networkAddress, manufacturerID, [], manufacturerName, powerSource, modelID, undefined, undefined, undefined, undefined, undefined, undefined, interviewState, {}, undefined, undefined, 0, gpSecurityKey, undefined);
|
|
414
603
|
database.insert(device.toDatabaseEntry());
|
|
415
|
-
Device.devices.get(databaseID)
|
|
604
|
+
Device.devices.get(databaseID)?.set(device.ieeeAddr, device);
|
|
605
|
+
Device.nwkToIeeeCache.get(databaseID)?.set(device.networkAddress, device.ieeeAddr);
|
|
416
606
|
return device;
|
|
417
607
|
}
|
|
418
608
|
/*
|
|
419
609
|
* Zigbee functions
|
|
420
610
|
*/
|
|
421
|
-
async interview() {
|
|
422
|
-
if (this.
|
|
611
|
+
async interview(ignoreCache = false) {
|
|
612
|
+
if (this.interviewState === InterviewState.InProgress) {
|
|
423
613
|
const message = `Interview - interview already in progress for '${this.ieeeAddr}'`;
|
|
424
614
|
logger_1.logger.debug(message, NS);
|
|
425
615
|
throw new Error(message);
|
|
426
616
|
}
|
|
427
|
-
let
|
|
428
|
-
this.
|
|
617
|
+
let err;
|
|
618
|
+
this._interviewState = InterviewState.InProgress;
|
|
429
619
|
logger_1.logger.debug(`Interview - start device '${this.ieeeAddr}'`, NS);
|
|
430
620
|
try {
|
|
431
|
-
await this.interviewInternal();
|
|
621
|
+
await this.interviewInternal(ignoreCache);
|
|
432
622
|
logger_1.logger.debug(`Interview - completed for device '${this.ieeeAddr}'`, NS);
|
|
433
|
-
this.
|
|
623
|
+
this._interviewState = InterviewState.Successful;
|
|
434
624
|
}
|
|
435
|
-
catch (
|
|
625
|
+
catch (error) {
|
|
436
626
|
if (this.interviewQuirks()) {
|
|
437
|
-
|
|
627
|
+
this._interviewState = InterviewState.Successful;
|
|
628
|
+
logger_1.logger.debug(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${error}')`, NS);
|
|
438
629
|
}
|
|
439
630
|
else {
|
|
440
|
-
|
|
441
|
-
error
|
|
631
|
+
this._interviewState = InterviewState.Failed;
|
|
632
|
+
logger_1.logger.debug(`Interview - failed for device '${this.ieeeAddr}' with error '${error}'`, NS);
|
|
633
|
+
err = error;
|
|
442
634
|
}
|
|
443
635
|
}
|
|
444
636
|
finally {
|
|
445
|
-
this._interviewing = false;
|
|
446
637
|
this.save();
|
|
447
638
|
}
|
|
448
|
-
if (
|
|
449
|
-
throw
|
|
639
|
+
if (err) {
|
|
640
|
+
throw err;
|
|
450
641
|
}
|
|
451
642
|
}
|
|
452
643
|
interviewQuirks() {
|
|
453
644
|
logger_1.logger.debug(`Interview - quirks check for '${this.modelID}'-'${this.manufacturerName}'-'${this.type}'`, NS);
|
|
454
|
-
//
|
|
645
|
+
// Tuya devices are typically hard to interview. They also don't require a full interview to work correctly
|
|
455
646
|
// e.g. no ias enrolling is required for the devices to work.
|
|
456
647
|
// Assume that in case we got both the manufacturerName and modelID the device works correctly.
|
|
457
648
|
// https://github.com/Koenkk/zigbee2mqtt/issues/7564:
|
|
@@ -459,61 +650,66 @@ class Device extends entity_1.default {
|
|
|
459
650
|
// https://github.com/Koenkk/zigbee2mqtt/issues/4655
|
|
460
651
|
// Device does not change zoneState after enroll (event with original gateway)
|
|
461
652
|
// modelID is mostly in the form of e.g. TS0202 and manufacturerName like e.g. _TYZB01_xph99wvr
|
|
462
|
-
if (this.
|
|
463
|
-
(this.manufacturerName?.match(
|
|
464
|
-
this.
|
|
465
|
-
|
|
466
|
-
this._interviewCompleted = true;
|
|
467
|
-
logger_1.logger.debug(`Interview - quirks matched for TuYa end device`, NS);
|
|
653
|
+
if (this.manufacturerName === "HOBEIAN" ||
|
|
654
|
+
(this.modelID?.match("^TS\\d*$") && (this.manufacturerName?.match("^_TZ.*_.*$") || this.manufacturerName?.match("^_TYZB01_.*$")))) {
|
|
655
|
+
this.#genBasic.powerSource = this.#genBasic.powerSource || Zcl.PowerSource.Battery;
|
|
656
|
+
logger_1.logger.debug("Interview - quirks matched for Tuya end device", NS);
|
|
468
657
|
return true;
|
|
469
658
|
}
|
|
470
659
|
// Some devices, e.g. Xiaomi end devices have a different interview procedure, after pairing they
|
|
471
660
|
// report it's modelID trough a readResponse. The readResponse is received by the controller and set
|
|
472
661
|
// on the device.
|
|
473
662
|
const lookup = {
|
|
474
|
-
|
|
475
|
-
type:
|
|
663
|
+
"^3R.*?Z": {
|
|
664
|
+
type: "EndDevice",
|
|
665
|
+
powerSource: Zcl.PowerSource.Battery,
|
|
476
666
|
},
|
|
477
|
-
|
|
478
|
-
type:
|
|
667
|
+
"lumi..*": {
|
|
668
|
+
type: "EndDevice",
|
|
669
|
+
manufacturerID: 4151,
|
|
670
|
+
manufacturerName: "LUMI",
|
|
671
|
+
powerSource: Zcl.PowerSource.Battery,
|
|
479
672
|
},
|
|
480
|
-
|
|
481
|
-
type:
|
|
673
|
+
"TERNCY-PP01": {
|
|
674
|
+
type: "EndDevice",
|
|
675
|
+
manufacturerID: 4648,
|
|
676
|
+
manufacturerName: "TERNCY",
|
|
677
|
+
powerSource: Zcl.PowerSource.Battery,
|
|
482
678
|
},
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
679
|
+
"3RWS18BZ": {}, // https://github.com/Koenkk/zigbee-herdsman-converters/pull/2710
|
|
680
|
+
"MULTI-MECI--EA01": {},
|
|
681
|
+
MOT003: {}, // https://github.com/Koenkk/zigbee2mqtt/issues/12471
|
|
682
|
+
"C-ZB-SEDC": {}, //candeo device that doesn't follow IAS enrollment process correctly and therefore fails to complete interview
|
|
683
|
+
"C-ZB-SEMO": {}, //candeo device that doesn't follow IAS enrollment process correctly and therefore fails to complete interview
|
|
684
|
+
"CS-T9C-A0-BG": {}, // iAS enroll fails: https://github.com/Koenkk/zigbee2mqtt/issues/27822
|
|
685
|
+
"SNZB-01": {}, // iAS enroll fails: https://github.com/Koenkk/zigbee2mqtt/issues/29474
|
|
486
686
|
};
|
|
487
|
-
|
|
687
|
+
let match;
|
|
688
|
+
for (const key in lookup) {
|
|
689
|
+
if (this.modelID?.match(key)) {
|
|
690
|
+
match = key;
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
488
694
|
if (match) {
|
|
489
695
|
const info = lookup[match];
|
|
490
696
|
logger_1.logger.debug(`Interview procedure failed but got modelID matching '${match}', assuming interview succeeded`, NS);
|
|
491
|
-
this._type = this._type ===
|
|
697
|
+
this._type = this._type === "Unknown" && info.type ? info.type : this._type;
|
|
492
698
|
this._manufacturerID = this._manufacturerID || info.manufacturerID;
|
|
493
|
-
this.
|
|
494
|
-
this.
|
|
495
|
-
this._interviewing = false;
|
|
496
|
-
this._interviewCompleted = true;
|
|
699
|
+
this.#genBasic.manufacturerName = this.#genBasic.manufacturerName || info.manufacturerName;
|
|
700
|
+
this.#genBasic.powerSource = (this.#genBasic.powerSource || info.powerSource) /* v8 ignore next */ ?? Zcl.PowerSource.Unknown;
|
|
497
701
|
logger_1.logger.debug(`Interview - quirks matched on '${match}'`, NS);
|
|
498
702
|
return true;
|
|
499
703
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
return false;
|
|
503
|
-
}
|
|
704
|
+
logger_1.logger.debug("Interview - quirks did not match", NS);
|
|
705
|
+
return false;
|
|
504
706
|
}
|
|
505
|
-
async interviewInternal() {
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
this._manufacturerID = nodeDescriptor.manufacturerCode;
|
|
509
|
-
this._type = nodeDescriptor.type;
|
|
510
|
-
logger_1.logger.debug(`Interview - got node descriptor for device '${this.ieeeAddr}'`, NS);
|
|
511
|
-
};
|
|
512
|
-
const hasNodeDescriptor = () => this._manufacturerID != null && this._type != null;
|
|
513
|
-
if (!hasNodeDescriptor()) {
|
|
707
|
+
async interviewInternal(ignoreCache) {
|
|
708
|
+
const hasNodeDescriptor = () => this._manufacturerID !== undefined && this._type !== "Unknown";
|
|
709
|
+
if (ignoreCache || !hasNodeDescriptor()) {
|
|
514
710
|
for (let attempt = 0; attempt < 6; attempt++) {
|
|
515
711
|
try {
|
|
516
|
-
await
|
|
712
|
+
await this.updateNodeDescriptor();
|
|
517
713
|
break;
|
|
518
714
|
}
|
|
519
715
|
catch (error) {
|
|
@@ -521,10 +717,8 @@ class Device extends entity_1.default {
|
|
|
521
717
|
logger_1.logger.debug(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${error}')`, NS);
|
|
522
718
|
return;
|
|
523
719
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
logger_1.logger.debug(`Interview - node descriptor request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`, NS);
|
|
527
|
-
}
|
|
720
|
+
// Most of the times the first node descriptor query fails and the seconds one succeeds.
|
|
721
|
+
logger_1.logger.debug(`Interview - node descriptor request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`, NS);
|
|
528
722
|
}
|
|
529
723
|
}
|
|
530
724
|
}
|
|
@@ -534,203 +728,389 @@ class Device extends entity_1.default {
|
|
|
534
728
|
if (!hasNodeDescriptor()) {
|
|
535
729
|
throw new Error(`Interview failed because can not get node descriptor ('${this.ieeeAddr}')`);
|
|
536
730
|
}
|
|
537
|
-
if (this.manufacturerID === 4619 && this._type ===
|
|
538
|
-
// Give
|
|
731
|
+
if (this.manufacturerID === 4619 && this._type === "EndDevice") {
|
|
732
|
+
// Give Tuya end device some time to pair. Otherwise they leave immediately.
|
|
539
733
|
// https://github.com/Koenkk/zigbee2mqtt/issues/5814
|
|
540
|
-
logger_1.logger.debug("Interview - Detected
|
|
541
|
-
await (0, utils_1.
|
|
734
|
+
logger_1.logger.debug("Interview - Detected Tuya end device, waiting 10 seconds...", NS);
|
|
735
|
+
await (0, utils_1.wait)(10000);
|
|
542
736
|
}
|
|
543
|
-
else if (
|
|
544
|
-
// Potentially a
|
|
737
|
+
else if (this.manufacturerID === 0 || this.manufacturerID === 4098) {
|
|
738
|
+
// Potentially a Tuya device, some sleep fast so make sure to read the modelId and manufacturerName quickly.
|
|
545
739
|
// In case the device responds, the endoint and modelID/manufacturerName are set
|
|
546
740
|
// in controller.onZclOrRawData()
|
|
547
741
|
// https://github.com/Koenkk/zigbee2mqtt/issues/7553
|
|
548
|
-
logger_1.logger.debug("Interview - Detected potential
|
|
742
|
+
logger_1.logger.debug("Interview - Detected potential Tuya end device, reading modelID and manufacturerName...", NS);
|
|
549
743
|
try {
|
|
550
744
|
const endpoint = endpoint_1.default.create(this.databaseID, 1, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr);
|
|
551
|
-
const result = await endpoint.read(
|
|
552
|
-
|
|
553
|
-
.forEach((entry) => Device.ReportablePropertiesMapping[entry[0]].set(entry[1], this));
|
|
745
|
+
const result = await endpoint.read("genBasic", ["modelId", "manufacturerName"], { sendPolicy: "immediate" });
|
|
746
|
+
this.updateGenBasic(result);
|
|
554
747
|
}
|
|
555
748
|
catch (error) {
|
|
556
|
-
|
|
557
|
-
logger_1.logger.debug(`Interview - TuYa read modelID and manufacturerName failed (${error})`, NS);
|
|
749
|
+
logger_1.logger.debug(`Interview - Tuya read modelID and manufacturerName failed (${error})`, NS);
|
|
558
750
|
}
|
|
559
751
|
}
|
|
560
752
|
// e.g. Xiaomi Aqara Opple devices fail to respond to the first active endpoints request, therefore try 2 times
|
|
561
753
|
// https://github.com/Koenkk/zigbee-herdsman/pull/103
|
|
562
|
-
|
|
563
|
-
let activeEndpoints;
|
|
754
|
+
let gotActiveEndpoints = false;
|
|
564
755
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
565
756
|
try {
|
|
566
|
-
|
|
757
|
+
await this.updateActiveEndpoints();
|
|
758
|
+
gotActiveEndpoints = true;
|
|
567
759
|
break;
|
|
568
760
|
}
|
|
569
761
|
catch (error) {
|
|
570
|
-
logger_1.logger.debug(`Interview - active endpoints request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`, NS);
|
|
762
|
+
logger_1.logger.debug(`Interview - active endpoints request failed for '${this.ieeeAddr}', attempt ${attempt + 1} (${error})`, NS);
|
|
571
763
|
}
|
|
572
764
|
}
|
|
573
|
-
if (!
|
|
765
|
+
if (!gotActiveEndpoints) {
|
|
574
766
|
throw new Error(`Interview failed because can not get active endpoints ('${this.ieeeAddr}')`);
|
|
575
767
|
}
|
|
576
|
-
// Make sure that the endpoint are sorted.
|
|
577
|
-
activeEndpoints.endpoints.sort((a, b) => a - b);
|
|
578
|
-
// Some devices, e.g. TERNCY return endpoint 0 in the active endpoints request.
|
|
579
|
-
// This is not a valid endpoint number according to the ZCL, requesting a simple descriptor will result
|
|
580
|
-
// into an error. Therefore we filter it, more info: https://github.com/Koenkk/zigbee-herdsman/issues/82
|
|
581
|
-
activeEndpoints.endpoints.filter((e) => e !== 0 && !this.getEndpoint(e)).forEach((e) => this._endpoints.push(endpoint_1.default.create(this.databaseID, e, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr)));
|
|
582
768
|
logger_1.logger.debug(`Interview - got active endpoints for device '${this.ieeeAddr}'`, NS);
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
endpoint.profileID = simpleDescriptor.profileID;
|
|
587
|
-
endpoint.deviceID = simpleDescriptor.deviceID;
|
|
588
|
-
endpoint.inputClusters = simpleDescriptor.inputClusters;
|
|
589
|
-
endpoint.outputClusters = simpleDescriptor.outputClusters;
|
|
769
|
+
const coordinator = Device.byType(this.databaseID, "Coordinator")[0];
|
|
770
|
+
for (const endpoint of this._endpoints) {
|
|
771
|
+
await endpoint.updateSimpleDescriptor();
|
|
590
772
|
logger_1.logger.debug(`Interview - got simple descriptor for endpoint '${endpoint.ID}' device '${this.ieeeAddr}'`, NS);
|
|
591
|
-
// Read attributes
|
|
592
|
-
// are not mandatory in ZCL specification
|
|
593
|
-
if (endpoint.supportsInputCluster(
|
|
594
|
-
for (const
|
|
595
|
-
if (!this[
|
|
773
|
+
// Read attributes
|
|
774
|
+
// nice to have but not required for successful pairing as most of the attributes are not mandatory in ZCL specification
|
|
775
|
+
if (endpoint.supportsInputCluster("genBasic")) {
|
|
776
|
+
for (const key of INTERVIEW_GENBASIC_ATTRIBUTES) {
|
|
777
|
+
if (ignoreCache || !this.#genBasic[key]) {
|
|
596
778
|
try {
|
|
597
779
|
let result;
|
|
598
780
|
try {
|
|
599
|
-
result = await endpoint.read(
|
|
781
|
+
result = await endpoint.read("genBasic", [key], { sendPolicy: "immediate" });
|
|
600
782
|
}
|
|
601
783
|
catch (error) {
|
|
602
784
|
// Reading attributes can fail for many reason, e.g. it could be that device rejoins
|
|
603
785
|
// while joining like in:
|
|
604
786
|
// https://github.com/Koenkk/zigbee-herdsman-converters/issues/2485.
|
|
605
787
|
// The modelID and manufacturerName are crucial for device identification, so retry.
|
|
606
|
-
if (
|
|
607
|
-
logger_1.logger.debug(`Interview - first ${
|
|
608
|
-
await (0, utils_1.
|
|
609
|
-
result = await endpoint.read(
|
|
788
|
+
if (key === "modelId" || key === "manufacturerName") {
|
|
789
|
+
logger_1.logger.debug(`Interview - first ${key} retrieval attempt failed, retrying after 10 seconds...`, NS);
|
|
790
|
+
await (0, utils_1.wait)(10000);
|
|
791
|
+
result = await endpoint.read("genBasic", [key], { sendPolicy: "immediate" });
|
|
610
792
|
}
|
|
611
793
|
else {
|
|
612
794
|
throw error;
|
|
613
795
|
}
|
|
614
796
|
}
|
|
615
|
-
|
|
616
|
-
logger_1.logger.debug(`Interview - got '${
|
|
797
|
+
this.updateGenBasic(result);
|
|
798
|
+
logger_1.logger.debug(`Interview - got '${key}' for device '${this.ieeeAddr}'`, NS);
|
|
617
799
|
}
|
|
618
800
|
catch (error) {
|
|
619
|
-
logger_1.logger.debug(`Interview - failed to read attribute '${
|
|
801
|
+
logger_1.logger.debug(`Interview - failed to read attribute '${key}' from endpoint '${endpoint.ID}' (${error})`, NS);
|
|
620
802
|
}
|
|
621
803
|
}
|
|
622
804
|
}
|
|
623
805
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
806
|
+
// Enroll IAS device
|
|
807
|
+
if (endpoint.supportsInputCluster("ssIasZone")) {
|
|
808
|
+
logger_1.logger.debug(`Interview - IAS - enrolling '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
|
|
809
|
+
const stateBefore = await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState"], { sendPolicy: "immediate" });
|
|
810
|
+
logger_1.logger.debug(() => `Interview - IAS - before enrolling state: '${JSON.stringify(stateBefore)}'`, NS);
|
|
811
|
+
// Do not enroll when device has already been enrolled
|
|
812
|
+
if (stateBefore.zoneState !== 1 || stateBefore.iasCieAddr !== coordinator.ieeeAddr) {
|
|
813
|
+
logger_1.logger.debug("Interview - IAS - not enrolled, enrolling", NS);
|
|
814
|
+
await endpoint.write("ssIasZone", { iasCieAddr: coordinator.ieeeAddr }, { disableDefaultResponse: true, sendPolicy: "immediate" });
|
|
815
|
+
logger_1.logger.debug("Interview - IAS - wrote iasCieAddr", NS);
|
|
816
|
+
// There are 2 enrollment procedures:
|
|
817
|
+
// - Auto enroll: coordinator has to send enrollResponse without receiving an enroll request
|
|
818
|
+
// this case is handled below.
|
|
819
|
+
// - Manual enroll: coordinator replies to enroll request with an enroll response.
|
|
820
|
+
// this case in hanled in onZclData().
|
|
821
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/4569#issuecomment-706075676
|
|
822
|
+
await (0, utils_1.wait)(500);
|
|
823
|
+
logger_1.logger.debug(`IAS - '${this.ieeeAddr}' sending enroll response (auto enroll)`, NS);
|
|
824
|
+
const payload = { enrollrspcode: 0, zoneid: 23 };
|
|
825
|
+
await endpoint.command("ssIasZone", "enrollRsp", payload, { disableDefaultResponse: true, sendPolicy: "immediate" });
|
|
826
|
+
let enrolled = false;
|
|
827
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
828
|
+
await (0, utils_1.wait)(500);
|
|
829
|
+
const stateAfter = await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState"], { sendPolicy: "immediate" });
|
|
830
|
+
logger_1.logger.debug(() => `Interview - IAS - after enrolling state (${attempt}): '${JSON.stringify(stateAfter)}'`, NS);
|
|
831
|
+
if (stateAfter.zoneState === 1) {
|
|
832
|
+
enrolled = true;
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (enrolled) {
|
|
837
|
+
logger_1.logger.debug(`Interview - IAS successfully enrolled '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
throw new Error(`Interview failed because of failed IAS enroll (zoneState didn't change ('${this.ieeeAddr}')`);
|
|
654
841
|
}
|
|
655
|
-
}
|
|
656
|
-
if (enrolled) {
|
|
657
|
-
logger_1.logger.debug(`Interview - IAS successfully enrolled '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
|
|
658
842
|
}
|
|
659
843
|
else {
|
|
660
|
-
|
|
844
|
+
logger_1.logger.debug("Interview - IAS - already enrolled, skipping enroll", NS);
|
|
661
845
|
}
|
|
662
846
|
}
|
|
663
|
-
else {
|
|
664
|
-
logger_1.logger.debug(`Interview - IAS - already enrolled, skipping enroll`, NS);
|
|
665
|
-
}
|
|
666
847
|
}
|
|
667
848
|
// Bind poll control
|
|
668
849
|
try {
|
|
669
|
-
for (const endpoint of this.endpoints.filter((e) => e.supportsInputCluster(
|
|
850
|
+
for (const endpoint of this.endpoints.filter((e) => e.supportsInputCluster("genPollCtrl"))) {
|
|
670
851
|
logger_1.logger.debug(`Interview - Poll control - binding '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS);
|
|
671
|
-
await endpoint.bind(
|
|
672
|
-
const pollPeriod = await endpoint.read(
|
|
852
|
+
await endpoint.bind("genPollCtrl", coordinator.endpoints[0]);
|
|
853
|
+
const pollPeriod = await endpoint.read("genPollCtrl", ["checkinInterval"], { sendPolicy: "immediate" });
|
|
673
854
|
this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds
|
|
674
855
|
this.resetPendingRequestTimeout();
|
|
675
856
|
}
|
|
857
|
+
/* v8 ignore start */
|
|
676
858
|
}
|
|
677
859
|
catch (error) {
|
|
678
|
-
/* istanbul ignore next */
|
|
679
860
|
logger_1.logger.debug(`Interview - failed to bind genPollCtrl (${error})`, NS);
|
|
680
861
|
}
|
|
862
|
+
/* v8 ignore stop */
|
|
863
|
+
}
|
|
864
|
+
async updateNodeDescriptor() {
|
|
865
|
+
const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
|
|
866
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
867
|
+
if (!adapter) {
|
|
868
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
869
|
+
}
|
|
870
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.networkAddress);
|
|
871
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
872
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
873
|
+
throw new Zdo.StatusError(response[0]);
|
|
874
|
+
}
|
|
875
|
+
// TODO: make use of: capabilities.rxOnWhenIdle, maxIncTxSize, maxOutTxSize, serverMask.stackComplianceRevision
|
|
876
|
+
const nodeDescriptor = response[1];
|
|
877
|
+
this._manufacturerID = nodeDescriptor.manufacturerCode;
|
|
878
|
+
switch (nodeDescriptor.logicalType) {
|
|
879
|
+
case 0x0:
|
|
880
|
+
this._type = "Coordinator";
|
|
881
|
+
break;
|
|
882
|
+
case 0x1:
|
|
883
|
+
this._type = "Router";
|
|
884
|
+
break;
|
|
885
|
+
case 0x2:
|
|
886
|
+
this._type = "EndDevice";
|
|
887
|
+
break;
|
|
888
|
+
}
|
|
889
|
+
logger_1.logger.debug(`Interview - got node descriptor for device '${this.ieeeAddr}'`, NS);
|
|
890
|
+
// TODO: define a property on Device for this value (would be good to have it displayed)
|
|
891
|
+
// log for devices older than 1 from current revision
|
|
892
|
+
if (nodeDescriptor.serverMask.stackComplianceRevision < ZSpec.ZIGBEE_REVISION - 1) {
|
|
893
|
+
// always 0 before revision 21 where field was added
|
|
894
|
+
const rev = nodeDescriptor.serverMask.stackComplianceRevision < 21 ? "pre-21" : nodeDescriptor.serverMask.stackComplianceRevision;
|
|
895
|
+
logger_1.logger.info(`Device '${this.ieeeAddr}' is only compliant to revision '${rev}' of the Zigbee specification (current revision: ${ZSpec.ZIGBEE_REVISION}).`, NS);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
async updateActiveEndpoints() {
|
|
899
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
900
|
+
if (!adapter) {
|
|
901
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
902
|
+
}
|
|
903
|
+
const clusterId = Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST;
|
|
904
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.networkAddress);
|
|
905
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
906
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
907
|
+
throw new Zdo.StatusError(response[0]);
|
|
908
|
+
}
|
|
909
|
+
const activeEndpoints = response[1];
|
|
910
|
+
// Make sure that the endpoint are sorted.
|
|
911
|
+
activeEndpoints.endpointList.sort((a, b) => a - b);
|
|
912
|
+
for (const endpoint of activeEndpoints.endpointList) {
|
|
913
|
+
// Some devices, e.g. TERNCY return endpoint 0 in the active endpoints request.
|
|
914
|
+
// This is not a valid endpoint number according to the ZCL, requesting a simple descriptor will result
|
|
915
|
+
// into an error. Therefore we filter it, more info: https://github.com/Koenkk/zigbee-herdsman/issues/82
|
|
916
|
+
if (endpoint !== 0 && !this.getEndpoint(endpoint)) {
|
|
917
|
+
this._endpoints.push(endpoint_1.default.create(this.databaseID, endpoint, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr));
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
// Remove disappeared endpoints (can happen with e.g. custom devices).
|
|
921
|
+
this._endpoints = this._endpoints.filter((e) => activeEndpoints.endpointList.includes(e.ID));
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Request device to advertise its network address.
|
|
925
|
+
* Note: This does not actually update the device property (if needed), as this is already done with `zdoResponse` event in Controller.
|
|
926
|
+
*/
|
|
927
|
+
async requestNetworkAddress() {
|
|
928
|
+
const clusterId = Zdo.ClusterId.NETWORK_ADDRESS_REQUEST;
|
|
929
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
930
|
+
if (!adapter) {
|
|
931
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
932
|
+
}
|
|
933
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.ieeeAddr, false, 0);
|
|
934
|
+
await adapter.sendZdo(this.ieeeAddr, ZSpec.BroadcastAddress.RX_ON_WHEN_IDLE, clusterId, zdoPayload, true);
|
|
681
935
|
}
|
|
682
936
|
async removeFromNetwork() {
|
|
683
|
-
|
|
937
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
938
|
+
if (!adapter) {
|
|
939
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
940
|
+
}
|
|
941
|
+
if (this._type === "GreenPower") {
|
|
684
942
|
const payload = {
|
|
685
943
|
options: 0x002550,
|
|
686
944
|
srcID: Number(this.ieeeAddr),
|
|
687
945
|
};
|
|
688
|
-
const frame = Zcl.Frame.create(Zcl.FrameType.SPECIFIC, Zcl.Direction.SERVER_TO_CLIENT, true,
|
|
689
|
-
await
|
|
946
|
+
const frame = Zcl.Frame.create(Zcl.FrameType.SPECIFIC, Zcl.Direction.SERVER_TO_CLIENT, true, undefined, zclTransactionSequenceNumber_1.default.next(), "pairing", 33, payload, this.customClusters);
|
|
947
|
+
await adapter.sendZclFrameToAll(242, frame, 242, enums_1.BroadcastAddress.RX_ON_WHEN_IDLE);
|
|
948
|
+
}
|
|
949
|
+
else {
|
|
950
|
+
const clusterId = Zdo.ClusterId.LEAVE_REQUEST;
|
|
951
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, this.ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
|
|
952
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
953
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
954
|
+
throw new Zdo.StatusError(response[0]);
|
|
955
|
+
}
|
|
690
956
|
}
|
|
691
|
-
else
|
|
692
|
-
await entity_1.default.getAdapterByID(this.databaseID).removeDevice(this.networkAddress, this.ieeeAddr);
|
|
693
957
|
this.removeFromDatabase();
|
|
694
958
|
}
|
|
695
959
|
removeFromDatabase() {
|
|
696
960
|
Device.loadFromDatabaseIfNecessary();
|
|
697
|
-
const database = entity_1.default.getDatabaseByID(this.databaseID);
|
|
698
961
|
for (const endpoint of this.endpoints) {
|
|
699
962
|
endpoint.removeFromAllGroupsDatabase();
|
|
700
963
|
}
|
|
701
|
-
|
|
964
|
+
const database = entity_1.default.getDatabaseByID(this.databaseID);
|
|
965
|
+
if (database?.has(this.ID)) {
|
|
702
966
|
database.remove(this.ID);
|
|
703
967
|
}
|
|
704
|
-
this.
|
|
968
|
+
Device.deletedDevices.get(this.databaseID)?.set(this.ieeeAddr, this);
|
|
969
|
+
Device.devices.get(this.databaseID)?.delete(this.ieeeAddr);
|
|
705
970
|
// Clear all data in case device joins again
|
|
706
|
-
|
|
707
|
-
this.
|
|
971
|
+
// Green power devices are never interviewed, keep existing interview state.
|
|
972
|
+
this._interviewState = this.type === "GreenPower" ? this._interviewState : InterviewState.Pending;
|
|
708
973
|
this.meta = {};
|
|
709
974
|
const newEndpoints = [];
|
|
710
975
|
for (const endpoint of this.endpoints) {
|
|
711
|
-
newEndpoints.push(endpoint_1.default.create(
|
|
976
|
+
newEndpoints.push(endpoint_1.default.create(this.databaseID, endpoint.ID, endpoint.profileID, endpoint.deviceID, endpoint.inputClusters, endpoint.outputClusters, this.networkAddress, this.ieeeAddr));
|
|
712
977
|
}
|
|
713
978
|
this._endpoints = newEndpoints;
|
|
714
979
|
}
|
|
715
980
|
async lqi() {
|
|
716
|
-
|
|
981
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
982
|
+
if (!adapter) {
|
|
983
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
984
|
+
}
|
|
985
|
+
const clusterId = Zdo.ClusterId.LQI_TABLE_REQUEST;
|
|
986
|
+
const table = [];
|
|
987
|
+
const request = async (startIndex) => {
|
|
988
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, startIndex);
|
|
989
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
990
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
991
|
+
throw new Zdo.StatusError(response[0]);
|
|
992
|
+
}
|
|
993
|
+
const result = response[1];
|
|
994
|
+
table.push(...result.entryList);
|
|
995
|
+
return [result.neighborTableEntries, result.entryList.length];
|
|
996
|
+
};
|
|
997
|
+
let [tableEntries, entryCount] = await request(0);
|
|
998
|
+
const size = tableEntries;
|
|
999
|
+
let nextStartIndex = entryCount;
|
|
1000
|
+
while (table.length < size) {
|
|
1001
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
1002
|
+
nextStartIndex += entryCount;
|
|
1003
|
+
}
|
|
1004
|
+
return table;
|
|
717
1005
|
}
|
|
718
1006
|
async routingTable() {
|
|
719
|
-
|
|
1007
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
1008
|
+
if (!adapter) {
|
|
1009
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
1010
|
+
}
|
|
1011
|
+
const clusterId = Zdo.ClusterId.ROUTING_TABLE_REQUEST;
|
|
1012
|
+
const table = [];
|
|
1013
|
+
const request = async (startIndex) => {
|
|
1014
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, startIndex);
|
|
1015
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
1016
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
1017
|
+
throw new Zdo.StatusError(response[0]);
|
|
1018
|
+
}
|
|
1019
|
+
const result = response[1];
|
|
1020
|
+
table.push(...result.entryList);
|
|
1021
|
+
return [result.routingTableEntries, result.entryList.length];
|
|
1022
|
+
};
|
|
1023
|
+
let [tableEntries, entryCount] = await request(0);
|
|
1024
|
+
const size = tableEntries;
|
|
1025
|
+
let nextStartIndex = entryCount;
|
|
1026
|
+
while (table.length < size) {
|
|
1027
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
1028
|
+
nextStartIndex += entryCount;
|
|
1029
|
+
}
|
|
1030
|
+
return table;
|
|
1031
|
+
}
|
|
1032
|
+
async bindingTable() {
|
|
1033
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
1034
|
+
if (!adapter) {
|
|
1035
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
1036
|
+
}
|
|
1037
|
+
const clusterId = Zdo.ClusterId.BINDING_TABLE_REQUEST;
|
|
1038
|
+
const table = [];
|
|
1039
|
+
const request = async (startIndex) => {
|
|
1040
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, startIndex);
|
|
1041
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
1042
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
1043
|
+
throw new Zdo.StatusError(response[0]);
|
|
1044
|
+
}
|
|
1045
|
+
const result = response[1];
|
|
1046
|
+
table.push(...result.entryList);
|
|
1047
|
+
return [result.bindingTableEntries, result.entryList.length];
|
|
1048
|
+
};
|
|
1049
|
+
let [tableEntries, entryCount] = await request(0);
|
|
1050
|
+
const size = tableEntries;
|
|
1051
|
+
let nextStartIndex = entryCount;
|
|
1052
|
+
while (table.length < size) {
|
|
1053
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
1054
|
+
nextStartIndex += entryCount;
|
|
1055
|
+
}
|
|
1056
|
+
for (const ep of this._endpoints) {
|
|
1057
|
+
const newBinds = [];
|
|
1058
|
+
for (const entry of table) {
|
|
1059
|
+
if (entry.sourceEui64 !== this.ieeeAddr || entry.sourceEndpoint !== ep.ID) {
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
1062
|
+
if (entry.destAddrMode === 0x01) {
|
|
1063
|
+
newBinds.push({ type: "group", cluster: entry.clusterId, groupID: entry.dest });
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
newBinds.push({
|
|
1067
|
+
type: "endpoint",
|
|
1068
|
+
cluster: entry.clusterId,
|
|
1069
|
+
deviceIeeeAddress: entry.dest,
|
|
1070
|
+
endpointID: entry.destEndpoint,
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
ep.saveBindings(newBinds);
|
|
1075
|
+
}
|
|
1076
|
+
return table;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Clear all the bindings of a device.
|
|
1080
|
+
* Support of this command is optional (only mandatory if device has a binding table).
|
|
1081
|
+
* @param eui64List list of bind entries to match and clear. Send `["0xffffffffffffffff"]` to clear all.
|
|
1082
|
+
*/
|
|
1083
|
+
async clearAllBindings(eui64List) {
|
|
1084
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
1085
|
+
if (!adapter) {
|
|
1086
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
1087
|
+
}
|
|
1088
|
+
const clusterId = Zdo.ClusterId.CLEAR_ALL_BINDINGS_REQUEST;
|
|
1089
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(adapter.hasZdoMessageOverhead, clusterId, { eui64List });
|
|
1090
|
+
const response = await adapter.sendZdo(this.ieeeAddr, this.networkAddress, clusterId, zdoPayload, false);
|
|
1091
|
+
if (!Zdo.Buffalo.checkStatus(response)) {
|
|
1092
|
+
throw new Zdo.StatusError(response[0]);
|
|
1093
|
+
}
|
|
1094
|
+
if ((eui64List.length === 1 && eui64List[0].toLowerCase() === ZSpec.BLANK_EUI64) ||
|
|
1095
|
+
eui64List.some((eui64) => eui64.toLowerCase() === this.ieeeAddr)) {
|
|
1096
|
+
for (const ep of this._endpoints) {
|
|
1097
|
+
ep.clearBindings();
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
720
1100
|
}
|
|
721
1101
|
async ping(disableRecovery = true) {
|
|
722
|
-
// Zigbee does not have an official
|
|
1102
|
+
// Zigbee does not have an official pinging mechanism. Use a read request
|
|
723
1103
|
// of a mandatory basic cluster attribute to keep it as lightweight as
|
|
724
1104
|
// possible.
|
|
725
1105
|
const endpoint = this.endpoints.find((ep) => ep.inputClusters.includes(0)) ?? this.endpoints[0];
|
|
726
|
-
await endpoint.read(
|
|
1106
|
+
await endpoint.read("genBasic", ["zclVersion"], { disableRecovery, sendPolicy: "immediate" });
|
|
727
1107
|
}
|
|
728
1108
|
addCustomCluster(name, cluster) {
|
|
729
|
-
(0,
|
|
1109
|
+
(0, node_assert_1.default)(![Zcl.Clusters.touchlink.ID, Zcl.Clusters.greenPower.ID].includes(cluster.ID), "Overriding of greenPower or touchlink cluster is not supported");
|
|
730
1110
|
if (Zcl.Utils.isClusterName(name)) {
|
|
731
|
-
const existingCluster = Zcl.Clusters[name];
|
|
1111
|
+
const existingCluster = this._customClusters[name] ?? Zcl.Clusters[name];
|
|
732
1112
|
// Extend existing cluster
|
|
733
|
-
(0,
|
|
1113
|
+
(0, node_assert_1.default)(existingCluster.ID === cluster.ID, `Custom cluster ID (${cluster.ID}) should match existing cluster ID (${existingCluster.ID})`);
|
|
734
1114
|
cluster = {
|
|
735
1115
|
ID: cluster.ID,
|
|
736
1116
|
manufacturerCode: cluster.manufacturerCode,
|
|
@@ -741,6 +1121,276 @@ class Device extends entity_1.default {
|
|
|
741
1121
|
}
|
|
742
1122
|
this._customClusters[name] = cluster;
|
|
743
1123
|
}
|
|
1124
|
+
#waitForOtaCommand(endpointId, commandId, transactionSequenceNumber, timeout) {
|
|
1125
|
+
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
1126
|
+
if (!adapter) {
|
|
1127
|
+
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
1128
|
+
}
|
|
1129
|
+
const waiter = adapter.waitFor(this.networkAddress, endpointId, Zcl.FrameType.SPECIFIC, Zcl.Direction.CLIENT_TO_SERVER, transactionSequenceNumber, Zcl.Clusters.genOta.ID, commandId, timeout);
|
|
1130
|
+
const promise = new Promise((resolve, reject) => {
|
|
1131
|
+
waiter.promise.then((payload) => {
|
|
1132
|
+
try {
|
|
1133
|
+
const frame = Zcl.Frame.fromBuffer(payload.clusterID, payload.header, payload.data, this.customClusters);
|
|
1134
|
+
resolve(frame);
|
|
1135
|
+
}
|
|
1136
|
+
catch (error) {
|
|
1137
|
+
reject(error);
|
|
1138
|
+
}
|
|
1139
|
+
}, (error) => reject(error));
|
|
1140
|
+
});
|
|
1141
|
+
return { promise, cancel: waiter.cancel };
|
|
1142
|
+
}
|
|
1143
|
+
async findMatchingOtaImage(source, current, extraMetas) {
|
|
1144
|
+
logger_1.logger.debug(() => `Getting image metadata for ${this.ieeeAddr}...`, NS);
|
|
1145
|
+
const images = await (0, ota_1.getOtaIndex)(source);
|
|
1146
|
+
// NOTE: Officially an image can be determined with a combination of manufacturerCode and imageType.
|
|
1147
|
+
// However several manufacturers do not follow the spec properly.
|
|
1148
|
+
// The index provides the needed extra metadata to prevent mismatches.
|
|
1149
|
+
// e.g. Tuya must match on manufacturerName, Gledopto on modelId...
|
|
1150
|
+
return images.find((i) => i.imageType === current.imageType &&
|
|
1151
|
+
i.manufacturerCode === current.manufacturerCode &&
|
|
1152
|
+
(i.minFileVersion === undefined || current.fileVersion >= i.minFileVersion) &&
|
|
1153
|
+
(i.maxFileVersion === undefined || current.fileVersion <= i.maxFileVersion) &&
|
|
1154
|
+
// let extra metas override the match from this.modelID, same for manufacturerName
|
|
1155
|
+
(!i.modelId || i.modelId === this.modelID || i.modelId === extraMetas.modelId) &&
|
|
1156
|
+
(!i.manufacturerName ||
|
|
1157
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
1158
|
+
i.manufacturerName.includes(this.manufacturerName) ||
|
|
1159
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
1160
|
+
i.manufacturerName.includes(extraMetas.manufacturerName)) &&
|
|
1161
|
+
(!extraMetas.otaHeaderString || i.otaHeaderString === extraMetas.otaHeaderString) &&
|
|
1162
|
+
(i.hardwareVersionMin === undefined ||
|
|
1163
|
+
(current.hardwareVersion !== undefined && current.hardwareVersion >= i.hardwareVersionMin) ||
|
|
1164
|
+
(extraMetas.hardwareVersionMin !== undefined && extraMetas.hardwareVersionMin >= i.hardwareVersionMin)) &&
|
|
1165
|
+
(i.hardwareVersionMax === undefined ||
|
|
1166
|
+
(current.hardwareVersion !== undefined && current.hardwareVersion <= i.hardwareVersionMax) ||
|
|
1167
|
+
(extraMetas.hardwareVersionMax !== undefined && extraMetas.hardwareVersionMax <= i.hardwareVersionMax)));
|
|
1168
|
+
}
|
|
1169
|
+
async #notifyOta(endpoint) {
|
|
1170
|
+
// Some devices (e.g. Insta) take a very long trying to discover the correct coordinator EP for OTA
|
|
1171
|
+
const queryNextImageRequest = this.#waitForOtaCommand(endpoint.ID, Zcl.Clusters.genOta.commands.queryNextImageRequest.ID, undefined, 60000);
|
|
1172
|
+
try {
|
|
1173
|
+
await endpoint.commandResponse("genOta", "imageNotify", { payloadType: 0, queryJitter: 100 }, { sendPolicy: "immediate" });
|
|
1174
|
+
const response = await queryNextImageRequest.promise;
|
|
1175
|
+
return [response.payload, response.header.transactionSequenceNumber];
|
|
1176
|
+
}
|
|
1177
|
+
catch {
|
|
1178
|
+
queryNextImageRequest.cancel();
|
|
1179
|
+
throw new Error(`Device didn't respond to OTA request`);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* If `current` is undefined, will automatically notify and reply to query with `NO_IMAGE_AVAILABLE` (stops device from doing further requests).
|
|
1184
|
+
*/
|
|
1185
|
+
async checkOta(source, current, extraMetas, endpoint = this.endpoints.find((e) => e.supportsOutputCluster("genOta"))) {
|
|
1186
|
+
(0, node_assert_1.default)(endpoint !== undefined, `No endpoint found with OTA cluster support for ${this.ieeeAddr}`);
|
|
1187
|
+
if (this.modelID === "PP-WHT-US") {
|
|
1188
|
+
// see https://github.com/Koenkk/zigbee-OTA/pull/14
|
|
1189
|
+
const scenesEndpoint = this.endpoints.find((e) => e.supportsOutputCluster("genScenes"));
|
|
1190
|
+
if (scenesEndpoint !== undefined) {
|
|
1191
|
+
await scenesEndpoint.write("genScenes", { currentGroup: 49502 }, { disableDefaultResponse: true, sendPolicy: "immediate" });
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
if (current === undefined) {
|
|
1195
|
+
let queryTsn;
|
|
1196
|
+
[current, queryTsn] = await this.#notifyOta(endpoint);
|
|
1197
|
+
await endpoint.commandResponse("genOta", "queryNextImageResponse", { status: Zcl.Status.NO_IMAGE_AVAILABLE }, undefined, queryTsn);
|
|
1198
|
+
}
|
|
1199
|
+
logger_1.logger.debug(() => `Checking OTA ${this.ieeeAddr} ${source.downgrade ? "downgrade" : "upgrade"} image availability, current=${JSON.stringify(current)}`, NS);
|
|
1200
|
+
if (this.meta.lumiFileVersion &&
|
|
1201
|
+
(this.modelID === "lumi.airrtc.agl001" || this.modelID === "lumi.curtain.acn003" || this.modelID === "lumi.curtain.agl001")) {
|
|
1202
|
+
// The current.fileVersion which comes from the device is wrong.
|
|
1203
|
+
// Use the `lumiFileVersion` which comes from the manuSpecificLumi.attributeReport instead.
|
|
1204
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/16345#issuecomment-1454835056
|
|
1205
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/16345 doesn't seem to be needed for all
|
|
1206
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/15745
|
|
1207
|
+
current = { ...current, fileVersion: this.meta.lumiFileVersion };
|
|
1208
|
+
}
|
|
1209
|
+
const meta = await this.findMatchingOtaImage(source, current, extraMetas);
|
|
1210
|
+
if (!meta) {
|
|
1211
|
+
// no image in repo/URL for specified device
|
|
1212
|
+
return {
|
|
1213
|
+
available: false,
|
|
1214
|
+
current,
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
logger_1.logger.debug(() => `OTA ${source.downgrade ? "downgrade" : "upgrade"} image availability for ${this.ieeeAddr}, available=${JSON.stringify(meta)}`, NS);
|
|
1218
|
+
return {
|
|
1219
|
+
available: meta.force ? true : source.downgrade ? current.fileVersion > meta.fileVersion : current.fileVersion < meta.fileVersion,
|
|
1220
|
+
current,
|
|
1221
|
+
availableMeta: meta,
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
async updateOta(source, requestPayload, requestTsn, extraMetas, onProgress, dataSettings, endpoint = this.endpoints.find((e) => e.supportsOutputCluster("genOta"))) {
|
|
1225
|
+
(0, node_assert_1.default)(this.#otaInProgress === false, `OTA already in progress for ${this.ieeeAddr}`);
|
|
1226
|
+
(0, node_assert_1.default)(endpoint !== undefined, `No endpoint found with OTA cluster support for ${this.ieeeAddr}`);
|
|
1227
|
+
if (source === undefined) {
|
|
1228
|
+
(0, node_assert_1.default)(this.#scheduledOta !== undefined, `No currently scheduled OTA for ${this.ieeeAddr}`);
|
|
1229
|
+
source = this.#scheduledOta;
|
|
1230
|
+
}
|
|
1231
|
+
this.#otaInProgress = true;
|
|
1232
|
+
// always expected both undefined if one is, but just in case
|
|
1233
|
+
if (requestPayload === undefined || requestTsn === undefined) {
|
|
1234
|
+
try {
|
|
1235
|
+
[requestPayload, requestTsn] = await this.#notifyOta(endpoint);
|
|
1236
|
+
}
|
|
1237
|
+
finally {
|
|
1238
|
+
this.#otaInProgress = false;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
let available = false;
|
|
1242
|
+
let image;
|
|
1243
|
+
if (source.url && !source.url.endsWith(".json")) {
|
|
1244
|
+
// firmware file at `source.url`
|
|
1245
|
+
try {
|
|
1246
|
+
const downloadedFile = await (0, ota_1.getOtaFirmware)(source.url, undefined);
|
|
1247
|
+
image = (0, ota_1.parseOtaImage)(downloadedFile);
|
|
1248
|
+
available = source.downgrade
|
|
1249
|
+
? requestPayload.fileVersion > image.header.fileVersion
|
|
1250
|
+
: requestPayload.fileVersion < image.header.fileVersion;
|
|
1251
|
+
logger_1.logger.debug(() =>
|
|
1252
|
+
// biome-ignore lint/style/noNonNullAssertion: valid from above, won't change after assignment
|
|
1253
|
+
`Parsed image from '${source.url}' for ${this.ieeeAddr}, header=${JSON.stringify(image.header)}`, NS);
|
|
1254
|
+
}
|
|
1255
|
+
catch (error) {
|
|
1256
|
+
logger_1.logger.error(`Failed to parse OTA image from '${source.url}' for ${this.ieeeAddr}, aborting (${error.message})`, NS);
|
|
1257
|
+
// biome-ignore lint/style/noNonNullAssertion: expected valid
|
|
1258
|
+
logger_1.logger.debug(error.stack, NS);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
else {
|
|
1262
|
+
let availableMeta;
|
|
1263
|
+
try {
|
|
1264
|
+
// index file at `source.url` (or undefined to use defaults)
|
|
1265
|
+
({ available, availableMeta } = await this.checkOta(source, requestPayload, extraMetas, endpoint));
|
|
1266
|
+
}
|
|
1267
|
+
finally {
|
|
1268
|
+
this.#otaInProgress = false;
|
|
1269
|
+
}
|
|
1270
|
+
if (available && availableMeta) {
|
|
1271
|
+
try {
|
|
1272
|
+
const downloadedFile = await (0, ota_1.getOtaFirmware)(availableMeta.url, availableMeta.sha512);
|
|
1273
|
+
image = (0, ota_1.parseOtaImage)(downloadedFile);
|
|
1274
|
+
logger_1.logger.debug(() =>
|
|
1275
|
+
// biome-ignore lint/style/noNonNullAssertion: valid from above, won't change after assignment
|
|
1276
|
+
`Parsed image from '${availableMeta.url}' for ${this.ieeeAddr}, header=${JSON.stringify(image.header)}`, NS);
|
|
1277
|
+
}
|
|
1278
|
+
catch (error) {
|
|
1279
|
+
logger_1.logger.error(`Failed to parse OTA image for ${this.ieeeAddr}, aborting (${error.message})`, NS);
|
|
1280
|
+
// biome-ignore lint/style/noNonNullAssertion: expected valid
|
|
1281
|
+
logger_1.logger.debug(error.stack, NS);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
logger_1.logger.info(() => `No OTA ${source.downgrade ? "downgrade" : "upgrade"} image currently available for ${this.ieeeAddr}`, NS);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
// reply to `queryNextImageRequest` now that we have the data for it, should trigger image block/page request from device
|
|
1289
|
+
// NOTE: previous code had try/catch wrapping with ignored error, but that doesn't look good (would fail to start OTA from device side)
|
|
1290
|
+
try {
|
|
1291
|
+
await endpoint.commandResponse("genOta", "queryNextImageResponse", image && available
|
|
1292
|
+
? {
|
|
1293
|
+
status: Zcl.Status.SUCCESS,
|
|
1294
|
+
manufacturerCode: image.header.manufacturerCode,
|
|
1295
|
+
imageType: image.header.imageType,
|
|
1296
|
+
fileVersion: image.header.fileVersion,
|
|
1297
|
+
imageSize: image.header.totalImageSize,
|
|
1298
|
+
}
|
|
1299
|
+
: { status: Zcl.Status.NO_IMAGE_AVAILABLE }, undefined, requestTsn);
|
|
1300
|
+
}
|
|
1301
|
+
finally {
|
|
1302
|
+
this.#otaInProgress = false;
|
|
1303
|
+
}
|
|
1304
|
+
if (!image || !available) {
|
|
1305
|
+
this.#otaInProgress = false;
|
|
1306
|
+
return [requestPayload, undefined];
|
|
1307
|
+
}
|
|
1308
|
+
logger_1.logger.debug(() => `Starting OTA update for ${this.ieeeAddr}`, NS);
|
|
1309
|
+
const session = new ota_1.OtaSession(this.ieeeAddr, endpoint, image, onProgress, dataSettings, this.#waitForOtaCommand.bind(this));
|
|
1310
|
+
let endResult;
|
|
1311
|
+
try {
|
|
1312
|
+
endResult = await session.run();
|
|
1313
|
+
}
|
|
1314
|
+
finally {
|
|
1315
|
+
this.#otaInProgress = false;
|
|
1316
|
+
}
|
|
1317
|
+
logger_1.logger.debug(() => `Received upgrade end request for ${this.ieeeAddr}: ${JSON.stringify(endResult.payload)}`, NS);
|
|
1318
|
+
if (endResult.payload.status === Zcl.Status.SUCCESS) {
|
|
1319
|
+
try {
|
|
1320
|
+
const currentTime = timeService.timestampToZigbeeUtcTime(Date.now());
|
|
1321
|
+
await endpoint.commandResponse("genOta", "upgradeEndResponse", {
|
|
1322
|
+
manufacturerCode: image.header.manufacturerCode,
|
|
1323
|
+
imageType: image.header.imageType,
|
|
1324
|
+
fileVersion: image.header.fileVersion,
|
|
1325
|
+
currentTime,
|
|
1326
|
+
upgradeTime: currentTime + 1, // TODO: could this tiny offset be a problem for some stacks?
|
|
1327
|
+
}, undefined, endResult.header.transactionSequenceNumber);
|
|
1328
|
+
onProgress(100, 0);
|
|
1329
|
+
logger_1.logger.info(() => `Update of ${this.ieeeAddr} successful (${Math.round((performance.now() - session.startTime) / 1000)} seconds). Waiting for device announce...`, NS);
|
|
1330
|
+
let timer;
|
|
1331
|
+
await new Promise((resolve) => {
|
|
1332
|
+
const onDeviceAnnounce = () => {
|
|
1333
|
+
clearTimeout(timer);
|
|
1334
|
+
logger_1.logger.debug(() => `Received device announce for ${this.ieeeAddr}, OTA update finished.`, NS);
|
|
1335
|
+
resolve();
|
|
1336
|
+
};
|
|
1337
|
+
// force "finished" after given time
|
|
1338
|
+
timer = setTimeout(() => {
|
|
1339
|
+
this.removeListener("deviceAnnounce", onDeviceAnnounce);
|
|
1340
|
+
logger_1.logger.debug(() => `Timed out waiting for device announce for ${this.ieeeAddr}, OTA update considered finished.`, NS);
|
|
1341
|
+
resolve();
|
|
1342
|
+
}, 120000 /** consider "done" after timeout even if no announce seen */);
|
|
1343
|
+
this.once("deviceAnnounce", onDeviceAnnounce);
|
|
1344
|
+
});
|
|
1345
|
+
// only "cancel" possible scheduled OTA when successful
|
|
1346
|
+
this.#scheduledOta = undefined;
|
|
1347
|
+
this.#otaInProgress = false;
|
|
1348
|
+
return [
|
|
1349
|
+
requestPayload,
|
|
1350
|
+
{
|
|
1351
|
+
fieldControl: 0,
|
|
1352
|
+
manufacturerCode: image.header.manufacturerCode,
|
|
1353
|
+
imageType: image.header.imageType,
|
|
1354
|
+
fileVersion: image.header.fileVersion,
|
|
1355
|
+
},
|
|
1356
|
+
];
|
|
1357
|
+
}
|
|
1358
|
+
catch (error) {
|
|
1359
|
+
this.#otaInProgress = false;
|
|
1360
|
+
throw new Error(`OTA upgrade end response failed: ${error.message}`);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
else {
|
|
1364
|
+
/**
|
|
1365
|
+
* For other status value received such as INVALID_IMAGE, REQUIRE_MORE_IMAGE, or ABORT,
|
|
1366
|
+
* the upgrade server SHALL not send Upgrade End Response command but it SHALL send default
|
|
1367
|
+
* response command with status of success and it SHALL wait for the client to reinitiate the upgrade process.
|
|
1368
|
+
*/
|
|
1369
|
+
try {
|
|
1370
|
+
await endpoint.defaultResponse(Zcl.Clusters.genOta.commands.upgradeEndRequest.ID, Zcl.Status.SUCCESS, Zcl.Clusters.genOta.ID, endResult.header.transactionSequenceNumber);
|
|
1371
|
+
}
|
|
1372
|
+
catch (error) {
|
|
1373
|
+
logger_1.logger.debug(() => `OTA upgrade end request default response for ${this.ieeeAddr} failed: ${error.message}`, NS);
|
|
1374
|
+
}
|
|
1375
|
+
this.#otaInProgress = false;
|
|
1376
|
+
throw new Error(`OTA update of ${this.ieeeAddr} failed with reason: ${Zcl.Status[endResult.payload.status]}`);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
scheduleOta(source) {
|
|
1380
|
+
(0, node_assert_1.default)(this.endpoints.some((e) => e.supportsOutputCluster("genOta")), `No endpoint found with OTA cluster support for ${this.ieeeAddr}`);
|
|
1381
|
+
if (this.#scheduledOta) {
|
|
1382
|
+
logger_1.logger.info(`Previously scheduled OTA update for '${this.ieeeAddr}' was cancelled in favor of new schedule request`, NS);
|
|
1383
|
+
}
|
|
1384
|
+
this.#scheduledOta = source;
|
|
1385
|
+
logger_1.logger.info(`Scheduled OTA update for '${this.ieeeAddr}' on next request from device`, NS);
|
|
1386
|
+
}
|
|
1387
|
+
unscheduleOta() {
|
|
1388
|
+
if (this.#scheduledOta !== undefined) {
|
|
1389
|
+
this.#scheduledOta = undefined;
|
|
1390
|
+
logger_1.logger.info(`Previously scheduled OTA update for '${this.ieeeAddr}' was cancelled`, NS);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
744
1393
|
}
|
|
1394
|
+
exports.Device = Device;
|
|
745
1395
|
exports.default = Device;
|
|
746
1396
|
//# sourceMappingURL=device.js.map
|