@willieee802/zigbee-herdsman 0.49.1 → 0.49.2
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/dist/adapter/adapter.d.ts +66 -0
- package/dist/adapter/adapter.js +110 -0
- package/dist/adapter/adapter.js.map +1 -0
- package/dist/adapter/adapterDiscovery.d.ts +34 -0
- package/dist/adapter/adapterDiscovery.js +646 -0
- package/dist/adapter/adapterDiscovery.js.map +1 -0
- package/dist/adapter/const.d.ts +9 -0
- package/dist/adapter/const.js +48 -0
- package/dist/adapter/const.js.map +1 -0
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +61 -0
- package/dist/adapter/deconz/adapter/deconzAdapter.js +719 -0
- package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -0
- package/dist/adapter/deconz/driver/constants.d.ts +210 -0
- package/dist/adapter/deconz/driver/constants.d.ts.map +1 -0
- package/dist/adapter/deconz/driver/constants.js +139 -0
- package/dist/adapter/deconz/driver/constants.js.map +1 -0
- package/dist/adapter/deconz/driver/driver.d.ts +111 -0
- package/dist/adapter/deconz/driver/driver.d.ts.map +1 -0
- package/dist/adapter/deconz/driver/driver.js +1362 -0
- package/dist/adapter/deconz/driver/driver.js.map +1 -0
- package/dist/adapter/deconz/driver/frame.d.ts +6 -0
- package/dist/adapter/deconz/driver/frame.d.ts.map +1 -0
- package/dist/adapter/deconz/driver/frame.js +13 -0
- package/dist/adapter/deconz/driver/frame.js.map +1 -0
- package/dist/adapter/deconz/driver/frameParser.d.ts +5 -0
- package/dist/adapter/deconz/driver/frameParser.d.ts.map +1 -0
- package/dist/adapter/deconz/driver/frameParser.js +700 -0
- package/dist/adapter/deconz/driver/frameParser.js.map +1 -0
- package/dist/adapter/deconz/driver/parser.d.ts +10 -0
- package/dist/adapter/deconz/driver/parser.d.ts.map +1 -0
- package/dist/adapter/deconz/driver/parser.js +39 -0
- package/dist/adapter/deconz/driver/parser.js.map +1 -0
- package/dist/adapter/deconz/driver/writer.d.ts +8 -0
- package/dist/adapter/deconz/driver/writer.d.ts.map +1 -0
- package/dist/adapter/deconz/driver/writer.js +53 -0
- package/dist/adapter/deconz/driver/writer.js.map +1 -0
- package/dist/adapter/ember/adapter/emberAdapter.d.ts +338 -0
- package/dist/adapter/ember/adapter/emberAdapter.js +1663 -0
- package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -0
- package/dist/adapter/ember/adapter/endpoints.d.ts +27 -0
- package/dist/adapter/ember/adapter/endpoints.js +69 -0
- package/dist/adapter/ember/adapter/endpoints.js.map +1 -0
- package/dist/adapter/ember/adapter/oneWaitress.d.ts +112 -0
- package/dist/adapter/ember/adapter/oneWaitress.js +233 -0
- package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -0
- package/dist/adapter/ember/adapter/tokensManager.d.ts +69 -0
- package/dist/adapter/ember/adapter/tokensManager.js +684 -0
- package/dist/adapter/ember/adapter/tokensManager.js.map +1 -0
- package/dist/adapter/ember/consts.d.ts +107 -0
- package/dist/adapter/ember/consts.d.ts.map +1 -0
- package/dist/adapter/ember/consts.js +155 -0
- package/dist/adapter/ember/consts.js.map +1 -0
- package/dist/adapter/ember/enums.d.ts +1568 -0
- package/dist/adapter/ember/enums.d.ts.map +1 -0
- package/dist/adapter/ember/enums.js +1697 -0
- package/dist/adapter/ember/enums.js.map +1 -0
- package/dist/adapter/ember/ezsp/buffalo.d.ts +166 -0
- package/dist/adapter/ember/ezsp/buffalo.d.ts.map +1 -0
- package/dist/adapter/ember/ezsp/buffalo.js +1133 -0
- package/dist/adapter/ember/ezsp/buffalo.js.map +1 -0
- package/dist/adapter/ember/ezsp/consts.d.ts +117 -0
- package/dist/adapter/ember/ezsp/consts.d.ts.map +1 -0
- package/dist/adapter/ember/ezsp/consts.js +129 -0
- package/dist/adapter/ember/ezsp/consts.js.map +1 -0
- package/dist/adapter/ember/ezsp/enums.d.ts +1016 -0
- package/dist/adapter/ember/ezsp/enums.d.ts.map +1 -0
- package/dist/adapter/ember/ezsp/enums.js +1103 -0
- package/dist/adapter/ember/ezsp/enums.js.map +1 -0
- package/dist/adapter/ember/ezsp/ezsp.d.ts +2951 -0
- package/dist/adapter/ember/ezsp/ezsp.js +7119 -0
- package/dist/adapter/ember/ezsp/ezsp.js.map +1 -0
- package/dist/adapter/ember/ezspError.d.ts +6 -0
- package/dist/adapter/ember/ezspError.d.ts.map +1 -0
- package/dist/adapter/ember/ezspError.js +13 -0
- package/dist/adapter/ember/ezspError.js.map +1 -0
- package/dist/adapter/ember/types.d.ts +787 -0
- package/dist/adapter/ember/types.d.ts.map +1 -0
- package/dist/adapter/ember/types.js +3 -0
- package/dist/adapter/ember/types.js.map +1 -0
- package/dist/adapter/ember/uart/ash.d.ts +434 -0
- package/dist/adapter/ember/uart/ash.d.ts.map +1 -0
- package/dist/adapter/ember/uart/ash.js +1561 -0
- package/dist/adapter/ember/uart/ash.js.map +1 -0
- package/dist/adapter/ember/uart/consts.d.ts +91 -0
- package/dist/adapter/ember/uart/consts.d.ts.map +1 -0
- package/dist/adapter/ember/uart/consts.js +100 -0
- package/dist/adapter/ember/uart/consts.js.map +1 -0
- package/dist/adapter/ember/uart/enums.d.ts +191 -0
- package/dist/adapter/ember/uart/enums.d.ts.map +1 -0
- package/dist/adapter/ember/uart/enums.js +156 -0
- package/dist/adapter/ember/uart/enums.js.map +1 -0
- package/dist/adapter/ember/uart/parser.d.ts +7 -0
- package/dist/adapter/ember/uart/parser.d.ts.map +1 -0
- package/dist/adapter/ember/uart/parser.js +32 -0
- package/dist/adapter/ember/uart/parser.js.map +1 -0
- package/dist/adapter/ember/uart/queues.d.ts +84 -0
- package/dist/adapter/ember/uart/queues.d.ts.map +1 -0
- package/dist/adapter/ember/uart/queues.js +213 -0
- package/dist/adapter/ember/uart/queues.js.map +1 -0
- package/dist/adapter/ember/uart/writer.d.ts +13 -0
- package/dist/adapter/ember/uart/writer.d.ts.map +1 -0
- package/dist/adapter/ember/uart/writer.js +42 -0
- package/dist/adapter/ember/uart/writer.js.map +1 -0
- package/dist/adapter/ember/utils/initters.d.ts +20 -0
- package/dist/adapter/ember/utils/initters.js +92 -0
- package/dist/adapter/ember/utils/initters.js.map +1 -0
- package/dist/adapter/ember/utils/math.d.ts +41 -0
- package/dist/adapter/ember/utils/math.d.ts.map +1 -0
- package/dist/adapter/ember/utils/math.js +80 -0
- package/dist/adapter/ember/utils/math.js.map +1 -0
- package/dist/adapter/events.d.ts +24 -0
- package/dist/adapter/events.js +3 -0
- package/dist/adapter/events.js.map +1 -0
- package/dist/adapter/ezsp/adapter/backup.d.ts +13 -0
- package/dist/adapter/ezsp/adapter/backup.js +89 -0
- package/dist/adapter/ezsp/adapter/backup.js.map +1 -0
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +53 -0
- package/dist/adapter/ezsp/adapter/ezspAdapter.js +464 -0
- package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -0
- package/dist/adapter/ezsp/driver/commands.d.ts +37 -0
- package/dist/adapter/ezsp/driver/commands.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/commands.js +2387 -0
- package/dist/adapter/ezsp/driver/commands.js.map +1 -0
- package/dist/adapter/ezsp/driver/consts.d.ts +11 -0
- package/dist/adapter/ezsp/driver/consts.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/consts.js +14 -0
- package/dist/adapter/ezsp/driver/consts.js.map +1 -0
- package/dist/adapter/ezsp/driver/driver.d.ts +96 -0
- package/dist/adapter/ezsp/driver/driver.js +852 -0
- package/dist/adapter/ezsp/driver/driver.js.map +1 -0
- package/dist/adapter/ezsp/driver/ezsp.d.ts +104 -0
- package/dist/adapter/ezsp/driver/ezsp.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/ezsp.js +678 -0
- package/dist/adapter/ezsp/driver/ezsp.js.map +1 -0
- package/dist/adapter/ezsp/driver/frame.d.ts +39 -0
- package/dist/adapter/ezsp/driver/frame.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/frame.js +101 -0
- package/dist/adapter/ezsp/driver/frame.js.map +1 -0
- package/dist/adapter/ezsp/driver/index.d.ts +4 -0
- package/dist/adapter/ezsp/driver/index.js +8 -0
- package/dist/adapter/ezsp/driver/index.js.map +1 -0
- package/dist/adapter/ezsp/driver/multicast.d.ts +16 -0
- package/dist/adapter/ezsp/driver/multicast.js +74 -0
- package/dist/adapter/ezsp/driver/multicast.js.map +1 -0
- package/dist/adapter/ezsp/driver/parser.d.ts +9 -0
- package/dist/adapter/ezsp/driver/parser.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/parser.js +109 -0
- package/dist/adapter/ezsp/driver/parser.js.map +1 -0
- package/dist/adapter/ezsp/driver/types/basic.d.ts +62 -0
- package/dist/adapter/ezsp/driver/types/basic.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/types/basic.js +187 -0
- package/dist/adapter/ezsp/driver/types/basic.js.map +1 -0
- package/dist/adapter/ezsp/driver/types/index.d.ts +9 -0
- package/dist/adapter/ezsp/driver/types/index.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/types/index.js +137 -0
- package/dist/adapter/ezsp/driver/types/index.js.map +1 -0
- package/dist/adapter/ezsp/driver/types/named.d.ts +1287 -0
- package/dist/adapter/ezsp/driver/types/named.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/types/named.js +2337 -0
- package/dist/adapter/ezsp/driver/types/named.js.map +1 -0
- package/dist/adapter/ezsp/driver/types/struct.d.ts +270 -0
- package/dist/adapter/ezsp/driver/types/struct.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/types/struct.js +869 -0
- package/dist/adapter/ezsp/driver/types/struct.js.map +1 -0
- package/dist/adapter/ezsp/driver/uart.d.ts +46 -0
- package/dist/adapter/ezsp/driver/uart.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/uart.js +390 -0
- package/dist/adapter/ezsp/driver/uart.js.map +1 -0
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts +5 -0
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.js +37 -0
- package/dist/adapter/ezsp/driver/utils/crc16ccitt.js.map +1 -0
- package/dist/adapter/ezsp/driver/utils/index.d.ts +5 -0
- package/dist/adapter/ezsp/driver/utils/index.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/utils/index.js +35 -0
- package/dist/adapter/ezsp/driver/utils/index.js.map +1 -0
- package/dist/adapter/ezsp/driver/writer.d.ts +12 -0
- package/dist/adapter/ezsp/driver/writer.d.ts.map +1 -0
- package/dist/adapter/ezsp/driver/writer.js +92 -0
- package/dist/adapter/ezsp/driver/writer.js.map +1 -0
- package/dist/adapter/index.d.ts +4 -0
- package/dist/adapter/index.js +41 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/adapter/serialPort.d.ts +19 -0
- package/dist/adapter/serialPort.d.ts.map +1 -0
- package/dist/adapter/serialPort.js +51 -0
- package/dist/adapter/serialPort.js.map +1 -0
- package/dist/adapter/tstype.d.ts +52 -0
- package/dist/adapter/tstype.d.ts.map +1 -0
- package/dist/adapter/tstype.js +3 -0
- package/dist/adapter/tstype.js.map +1 -0
- package/dist/adapter/utils.d.ts +8 -0
- package/dist/adapter/utils.d.ts.map +1 -0
- package/dist/adapter/utils.js +42 -0
- package/dist/adapter/utils.js.map +1 -0
- package/dist/adapter/z-stack/adapter/adapter-backup.d.ts +62 -0
- package/dist/adapter/z-stack/adapter/adapter-backup.d.ts.map +1 -0
- package/dist/adapter/z-stack/adapter/adapter-backup.js +469 -0
- package/dist/adapter/z-stack/adapter/adapter-backup.js.map +1 -0
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts +150 -0
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.d.ts.map +1 -0
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.js +279 -0
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.js.map +1 -0
- package/dist/adapter/z-stack/adapter/endpoints.d.ts +12 -0
- package/dist/adapter/z-stack/adapter/endpoints.js +87 -0
- package/dist/adapter/z-stack/adapter/endpoints.js.map +1 -0
- package/dist/adapter/z-stack/adapter/manager.d.ts +86 -0
- package/dist/adapter/z-stack/adapter/manager.js +493 -0
- package/dist/adapter/z-stack/adapter/manager.js.map +1 -0
- package/dist/adapter/z-stack/adapter/tstype.d.ts +7 -0
- package/dist/adapter/z-stack/adapter/tstype.d.ts.map +1 -0
- package/dist/adapter/z-stack/adapter/tstype.js +10 -0
- package/dist/adapter/z-stack/adapter/tstype.js.map +1 -0
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +85 -0
- package/dist/adapter/z-stack/adapter/zStackAdapter.js +924 -0
- package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -0
- package/dist/adapter/z-stack/constants/af.d.ts +24 -0
- package/dist/adapter/z-stack/constants/af.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/af.js +28 -0
- package/dist/adapter/z-stack/constants/af.js.map +1 -0
- package/dist/adapter/z-stack/constants/common.d.ts +279 -0
- package/dist/adapter/z-stack/constants/common.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/common.js +290 -0
- package/dist/adapter/z-stack/constants/common.js.map +1 -0
- package/dist/adapter/z-stack/constants/dbg.d.ts +23 -0
- package/dist/adapter/z-stack/constants/dbg.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/dbg.js +25 -0
- package/dist/adapter/z-stack/constants/dbg.js.map +1 -0
- package/dist/adapter/z-stack/constants/index.d.ts +11 -0
- package/dist/adapter/z-stack/constants/index.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/index.js +58 -0
- package/dist/adapter/z-stack/constants/index.js.map +1 -0
- package/dist/adapter/z-stack/constants/mac.d.ts +128 -0
- package/dist/adapter/z-stack/constants/mac.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/mac.js +130 -0
- package/dist/adapter/z-stack/constants/mac.js.map +1 -0
- package/dist/adapter/z-stack/constants/sapi.d.ts +25 -0
- package/dist/adapter/z-stack/constants/sapi.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/sapi.js +27 -0
- package/dist/adapter/z-stack/constants/sapi.js.map +1 -0
- package/dist/adapter/z-stack/constants/sys.d.ts +72 -0
- package/dist/adapter/z-stack/constants/sys.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/sys.js +74 -0
- package/dist/adapter/z-stack/constants/sys.js.map +1 -0
- package/dist/adapter/z-stack/constants/util.d.ts +82 -0
- package/dist/adapter/z-stack/constants/util.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/util.js +84 -0
- package/dist/adapter/z-stack/constants/util.js.map +1 -0
- package/dist/adapter/z-stack/constants/utils.d.ts +5 -0
- package/dist/adapter/z-stack/constants/utils.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/utils.js +14 -0
- package/dist/adapter/z-stack/constants/utils.js.map +1 -0
- package/dist/adapter/z-stack/constants/zdo.d.ts +103 -0
- package/dist/adapter/z-stack/constants/zdo.d.ts.map +1 -0
- package/dist/adapter/z-stack/constants/zdo.js +105 -0
- package/dist/adapter/z-stack/constants/zdo.js.map +1 -0
- package/dist/adapter/z-stack/models/startup-options.d.ts +13 -0
- package/dist/adapter/z-stack/models/startup-options.js +3 -0
- package/dist/adapter/z-stack/models/startup-options.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts +23 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.js +43 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-entry.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-table.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-table.js +24 -0
- package/dist/adapter/z-stack/structs/entries/address-manager-table.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js +16 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-entry.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js +25 -0
- package/dist/adapter/z-stack/structs/entries/aps-link-key-data-table.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js +23 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-entry.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js +25 -0
- package/dist/adapter/z-stack/structs/entries/aps-tc-link-key-table.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/channel-list.d.ts +8 -0
- package/dist/adapter/z-stack/structs/entries/channel-list.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/channel-list.js +12 -0
- package/dist/adapter/z-stack/structs/entries/channel-list.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/has-configured.d.ts +8 -0
- package/dist/adapter/z-stack/structs/entries/has-configured.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/has-configured.js +22 -0
- package/dist/adapter/z-stack/structs/entries/has-configured.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/index.d.ts +17 -0
- package/dist/adapter/z-stack/structs/entries/index.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/index.js +33 -0
- package/dist/adapter/z-stack/structs/entries/index.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nib.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/nib.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nib.js +72 -0
- package/dist/adapter/z-stack/structs/entries/nib.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js +21 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key-descriptor.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts +8 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key.js +19 -0
- package/dist/adapter/z-stack/structs/entries/nwk-key.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts +8 -0
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js +12 -0
- package/dist/adapter/z-stack/structs/entries/nwk-pan-id.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts +13 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js +22 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js +24 -0
- package/dist/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts +20 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.js +35 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-entry.js.map +1 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts +10 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-table.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-table.js +25 -0
- package/dist/adapter/z-stack/structs/entries/security-manager-table.js.map +1 -0
- package/dist/adapter/z-stack/structs/index.d.ts +5 -0
- package/dist/adapter/z-stack/structs/index.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/index.js +21 -0
- package/dist/adapter/z-stack/structs/index.js.map +1 -0
- package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts +13 -0
- package/dist/adapter/z-stack/structs/serializable-memory-object.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/serializable-memory-object.js +3 -0
- package/dist/adapter/z-stack/structs/serializable-memory-object.js.map +1 -0
- package/dist/adapter/z-stack/structs/struct.d.ts +99 -0
- package/dist/adapter/z-stack/structs/struct.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/struct.js +308 -0
- package/dist/adapter/z-stack/structs/struct.js.map +1 -0
- package/dist/adapter/z-stack/structs/table.d.ts +94 -0
- package/dist/adapter/z-stack/structs/table.d.ts.map +1 -0
- package/dist/adapter/z-stack/structs/table.js +167 -0
- package/dist/adapter/z-stack/structs/table.js.map +1 -0
- package/dist/adapter/z-stack/unpi/constants.d.ts +29 -0
- package/dist/adapter/z-stack/unpi/constants.d.ts.map +1 -0
- package/dist/adapter/z-stack/unpi/constants.js +40 -0
- package/dist/adapter/z-stack/unpi/constants.js.map +1 -0
- package/dist/adapter/z-stack/unpi/frame.d.ts +15 -0
- package/dist/adapter/z-stack/unpi/frame.d.ts.map +1 -0
- package/dist/adapter/z-stack/unpi/frame.js +53 -0
- package/dist/adapter/z-stack/unpi/frame.js.map +1 -0
- package/dist/adapter/z-stack/unpi/index.d.ts +5 -0
- package/dist/adapter/z-stack/unpi/index.d.ts.map +1 -0
- package/dist/adapter/z-stack/unpi/index.js +44 -0
- package/dist/adapter/z-stack/unpi/index.js.map +1 -0
- package/dist/adapter/z-stack/unpi/parser.d.ts +10 -0
- package/dist/adapter/z-stack/unpi/parser.d.ts.map +1 -0
- package/dist/adapter/z-stack/unpi/parser.js +94 -0
- package/dist/adapter/z-stack/unpi/parser.js.map +1 -0
- package/dist/adapter/z-stack/unpi/writer.d.ts +9 -0
- package/dist/adapter/z-stack/unpi/writer.d.ts.map +1 -0
- package/dist/adapter/z-stack/unpi/writer.js +66 -0
- package/dist/adapter/z-stack/unpi/writer.js.map +1 -0
- package/dist/adapter/z-stack/utils/channel-list.d.ts +21 -0
- package/dist/adapter/z-stack/utils/channel-list.d.ts.map +1 -0
- package/dist/adapter/z-stack/utils/channel-list.js +45 -0
- package/dist/adapter/z-stack/utils/channel-list.js.map +1 -0
- package/dist/adapter/z-stack/utils/index.d.ts +3 -0
- package/dist/adapter/z-stack/utils/index.d.ts.map +1 -0
- package/dist/adapter/z-stack/utils/index.js +19 -0
- package/dist/adapter/z-stack/utils/index.js.map +1 -0
- package/dist/adapter/z-stack/utils/network-options.d.ts +9 -0
- package/dist/adapter/z-stack/utils/network-options.d.ts.map +1 -0
- package/dist/adapter/z-stack/utils/network-options.js +22 -0
- package/dist/adapter/z-stack/utils/network-options.js.map +1 -0
- package/dist/adapter/z-stack/znp/buffaloZnp.d.ts +10 -0
- package/dist/adapter/z-stack/znp/buffaloZnp.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/buffaloZnp.js +162 -0
- package/dist/adapter/z-stack/znp/buffaloZnp.js.map +1 -0
- package/dist/adapter/z-stack/znp/definition.d.ts +18 -0
- package/dist/adapter/z-stack/znp/definition.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/definition.js +2703 -0
- package/dist/adapter/z-stack/znp/definition.js.map +1 -0
- package/dist/adapter/z-stack/znp/index.d.ts +3 -0
- package/dist/adapter/z-stack/znp/index.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/index.js +8 -0
- package/dist/adapter/z-stack/znp/index.js.map +1 -0
- package/dist/adapter/z-stack/znp/parameterType.d.ts +19 -0
- package/dist/adapter/z-stack/znp/parameterType.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/parameterType.js +22 -0
- package/dist/adapter/z-stack/znp/parameterType.js.map +1 -0
- package/dist/adapter/z-stack/znp/tstype.d.ts +40 -0
- package/dist/adapter/z-stack/znp/tstype.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/tstype.js +3 -0
- package/dist/adapter/z-stack/znp/tstype.js.map +1 -0
- package/dist/adapter/z-stack/znp/utils.d.ts +4 -0
- package/dist/adapter/z-stack/znp/utils.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/utils.js +12 -0
- package/dist/adapter/z-stack/znp/utils.js.map +1 -0
- package/dist/adapter/z-stack/znp/znp.d.ts +43 -0
- package/dist/adapter/z-stack/znp/znp.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/znp.js +295 -0
- package/dist/adapter/z-stack/znp/znp.js.map +1 -0
- package/dist/adapter/z-stack/znp/zpiObject.d.ts +19 -0
- package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +1 -0
- package/dist/adapter/z-stack/znp/zpiObject.js +121 -0
- package/dist/adapter/z-stack/znp/zpiObject.js.map +1 -0
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts +44 -0
- package/dist/adapter/zboss/adapter/zbossAdapter.js +365 -0
- package/dist/adapter/zboss/adapter/zbossAdapter.js.map +1 -0
- package/dist/adapter/zboss/commands.d.ts +20 -0
- package/dist/adapter/zboss/commands.d.ts.map +1 -0
- package/dist/adapter/zboss/commands.js +1141 -0
- package/dist/adapter/zboss/commands.js.map +1 -0
- package/dist/adapter/zboss/consts.d.ts +9 -0
- package/dist/adapter/zboss/consts.d.ts.map +1 -0
- package/dist/adapter/zboss/consts.js +12 -0
- package/dist/adapter/zboss/consts.js.map +1 -0
- package/dist/adapter/zboss/driver.d.ts +55 -0
- package/dist/adapter/zboss/driver.js +358 -0
- package/dist/adapter/zboss/driver.js.map +1 -0
- package/dist/adapter/zboss/enums.d.ts +301 -0
- package/dist/adapter/zboss/enums.d.ts.map +1 -0
- package/dist/adapter/zboss/enums.js +359 -0
- package/dist/adapter/zboss/enums.js.map +1 -0
- package/dist/adapter/zboss/frame.d.ts +34 -0
- package/dist/adapter/zboss/reader.d.ts +8 -0
- package/dist/adapter/zboss/reader.d.ts.map +1 -0
- package/dist/adapter/zboss/reader.js +59 -0
- package/dist/adapter/zboss/reader.js.map +1 -0
- package/dist/adapter/zboss/types.d.ts +2 -0
- package/dist/adapter/zboss/types.d.ts.map +1 -0
- package/dist/adapter/zboss/types.js +3 -0
- package/dist/adapter/zboss/types.js.map +1 -0
- package/dist/adapter/zboss/uart.d.ts +38 -0
- package/dist/adapter/zboss/uart.js +373 -0
- package/dist/adapter/zboss/uart.js.map +1 -0
- package/dist/adapter/zboss/utils.d.ts +9 -0
- package/dist/adapter/zboss/utils.d.ts.map +1 -0
- package/dist/adapter/zboss/utils.js +56 -0
- package/dist/adapter/zboss/utils.js.map +1 -0
- package/dist/adapter/zboss/writer.d.ts +14 -0
- package/dist/adapter/zboss/writer.d.ts.map +1 -0
- package/dist/adapter/zboss/writer.js +41 -0
- package/dist/adapter/zboss/writer.js.map +1 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts +5 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts.map +1 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js +26 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js.map +1 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +63 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.js +462 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -0
- package/dist/adapter/zigate/driver/buffaloZiGate.d.ts +22 -0
- package/dist/adapter/zigate/driver/commandType.d.ts +42 -0
- package/dist/adapter/zigate/driver/commandType.d.ts.map +1 -0
- package/dist/adapter/zigate/driver/commandType.js +381 -0
- package/dist/adapter/zigate/driver/commandType.js.map +1 -0
- package/dist/adapter/zigate/driver/constants.d.ts +116 -0
- package/dist/adapter/zigate/driver/constants.d.ts.map +1 -0
- package/dist/adapter/zigate/driver/constants.js +147 -0
- package/dist/adapter/zigate/driver/constants.js.map +1 -0
- package/dist/adapter/zigate/driver/frame.d.ts +26 -0
- package/dist/adapter/zigate/driver/frame.d.ts.map +1 -0
- package/dist/adapter/zigate/driver/frame.js +161 -0
- package/dist/adapter/zigate/driver/frame.js.map +1 -0
- package/dist/adapter/zigate/driver/messageType.d.ts +13 -0
- package/dist/adapter/zigate/driver/messageType.d.ts.map +1 -0
- package/dist/adapter/zigate/driver/messageType.js +281 -0
- package/dist/adapter/zigate/driver/messageType.js.map +1 -0
- package/dist/adapter/zigate/driver/parameterType.d.ts +25 -0
- package/dist/adapter/zigate/driver/parameterType.d.ts.map +1 -0
- package/dist/adapter/zigate/driver/parameterType.js +31 -0
- package/dist/adapter/zigate/driver/parameterType.js.map +1 -0
- package/dist/adapter/zigate/driver/ziGateObject.d.ts +23 -0
- package/dist/adapter/zigate/driver/ziGateObject.js +117 -0
- package/dist/adapter/zigate/driver/ziGateObject.js.map +1 -0
- package/dist/adapter/zigate/driver/zigate.d.ts +47 -0
- package/dist/adapter/zigate/driver/zigate.js +364 -0
- package/dist/adapter/zigate/driver/zigate.js.map +1 -0
- package/dist/adapter/zoh/adapter/utils.d.ts +16 -0
- package/dist/adapter/zoh/adapter/utils.d.ts.map +1 -0
- package/dist/adapter/zoh/adapter/utils.js +31 -0
- package/dist/adapter/zoh/adapter/utils.js.map +1 -0
- package/dist/adapter/zoh/adapter/zohAdapter.d.ts +100 -0
- package/dist/adapter/zoh/adapter/zohAdapter.js +715 -0
- package/dist/adapter/zoh/adapter/zohAdapter.js.map +1 -0
- package/dist/buffalo/buffalo.d.ts +67 -0
- package/dist/buffalo/buffalo.d.ts.map +1 -0
- package/dist/buffalo/buffalo.js +275 -0
- package/dist/buffalo/buffalo.js.map +1 -0
- package/dist/buffalo/index.d.ts +2 -0
- package/dist/buffalo/index.d.ts.map +1 -0
- package/dist/buffalo/index.js +6 -0
- package/dist/buffalo/index.js.map +1 -0
- package/dist/controller/controller.d.ts +155 -0
- package/dist/controller/database.d.ts +21 -0
- package/dist/controller/database.js +128 -0
- package/dist/controller/database.js.map +1 -0
- package/dist/controller/events.d.ts +44 -0
- package/dist/controller/greenPower.d.ts +78 -0
- package/dist/controller/helpers/index.d.ts +2 -0
- package/dist/controller/helpers/index.js +38 -0
- package/dist/controller/helpers/index.js.map +1 -0
- package/dist/controller/helpers/installCodes.d.ts +27 -0
- package/dist/controller/helpers/installCodes.d.ts.map +1 -0
- package/dist/controller/helpers/installCodes.js +90 -0
- package/dist/controller/helpers/installCodes.js.map +1 -0
- package/dist/controller/helpers/ota.d.ts +53 -0
- package/dist/controller/helpers/request.d.ts +22 -0
- package/dist/controller/helpers/request.js +82 -0
- package/dist/controller/helpers/request.js.map +1 -0
- package/dist/controller/helpers/requestQueue.d.ts +13 -0
- package/dist/controller/helpers/requestQueue.js +109 -0
- package/dist/controller/helpers/requestQueue.js.map +1 -0
- package/dist/controller/helpers/zclFrameConverter.d.ts +7 -0
- package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts +8 -0
- package/dist/controller/helpers/zclTransactionSequenceNumber.d.ts.map +1 -0
- package/dist/controller/helpers/zclTransactionSequenceNumber.js +14 -0
- package/dist/controller/helpers/zclTransactionSequenceNumber.js.map +1 -0
- package/dist/controller/index.d.ts +6 -0
- package/dist/controller/index.js +9 -0
- package/dist/controller/index.js.map +1 -0
- package/dist/controller/model/device.d.ts +150 -0
- package/dist/controller/model/endpoint.d.ts +150 -0
- package/dist/controller/model/entity.d.ts +18 -0
- package/dist/controller/model/entity.js +35 -0
- package/dist/controller/model/entity.js.map +1 -0
- package/dist/controller/model/group.d.ts +50 -0
- package/dist/controller/model/index.d.ts +6 -0
- package/dist/controller/model/index.js +14 -0
- package/dist/controller/model/index.js.map +1 -0
- package/dist/controller/model/konnextConfig.d.ts +7 -0
- package/dist/controller/model/konnextConfig.d.ts.map +1 -0
- package/dist/controller/model/konnextConfig.js +3 -0
- package/dist/controller/model/konnextConfig.js.map +1 -0
- package/dist/controller/model/zigbeeEntity.d.ts +8 -0
- package/dist/controller/model/zigbeeEntity.js +11 -0
- package/dist/controller/model/zigbeeEntity.js.map +1 -0
- package/dist/controller/touchlink.d.ts +20 -0
- package/dist/controller/touchlink.js +169 -0
- package/dist/controller/touchlink.js.map +1 -0
- package/dist/controller/tstype.d.ts +152 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/models/backup-storage-legacy.d.ts +25 -0
- package/dist/models/backup-storage-legacy.d.ts.map +1 -0
- package/dist/models/backup-storage-legacy.js +3 -0
- package/dist/models/backup-storage-legacy.js.map +1 -0
- package/dist/models/backup-storage-unified.d.ts +50 -0
- package/dist/models/backup-storage-unified.d.ts.map +1 -0
- package/dist/models/backup-storage-unified.js +3 -0
- package/dist/models/backup-storage-unified.js.map +1 -0
- package/dist/models/backup.d.ts +37 -0
- package/dist/models/backup.d.ts.map +1 -0
- package/dist/models/backup.js +3 -0
- package/dist/models/backup.js.map +1 -0
- package/dist/models/index.d.ts +5 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +22 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/network-options.d.ts +12 -0
- package/dist/models/network-options.d.ts.map +1 -0
- package/dist/models/network-options.js +3 -0
- package/dist/models/network-options.js.map +1 -0
- package/dist/utils/aes.d.ts +40 -0
- package/dist/utils/aes.d.ts.map +1 -0
- package/dist/utils/aes.js +207 -0
- package/dist/utils/aes.js.map +1 -0
- package/dist/utils/async-mutex.d.ts +7 -0
- package/dist/utils/async-mutex.d.ts.map +1 -0
- package/dist/utils/async-mutex.js +31 -0
- package/dist/utils/async-mutex.js.map +1 -0
- package/dist/utils/backup.d.ts +21 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +179 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +45 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +14 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/patchBigIntSerialization.d.ts +2 -0
- package/dist/utils/patchBigIntSerialization.d.ts.map +1 -0
- package/dist/utils/patchBigIntSerialization.js +9 -0
- package/dist/utils/patchBigIntSerialization.js.map +1 -0
- package/dist/utils/queue.d.ts +8 -0
- package/dist/utils/queue.d.ts.map +1 -0
- package/dist/utils/queue.js +67 -0
- package/dist/utils/queue.js.map +1 -0
- package/dist/utils/timeService.d.ts +6 -0
- package/dist/utils/utils.d.ts +5 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +24 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/utils/wait.d.ts +2 -0
- package/dist/utils/wait.d.ts.map +1 -0
- package/dist/utils/wait.js +9 -0
- package/dist/utils/wait.js.map +1 -0
- package/dist/utils/waitress.d.ts +23 -0
- package/dist/utils/waitress.d.ts.map +1 -0
- package/dist/utils/waitress.js +76 -0
- package/dist/utils/waitress.js.map +1 -0
- package/dist/zspec/consts.d.ts +75 -0
- package/dist/zspec/consts.d.ts.map +1 -0
- package/dist/zspec/consts.js +79 -0
- package/dist/zspec/consts.js.map +1 -0
- package/dist/zspec/enums.d.ts +19 -0
- package/dist/zspec/enums.d.ts.map +1 -0
- package/dist/zspec/enums.js +27 -0
- package/dist/zspec/enums.js.map +1 -0
- package/dist/zspec/index.d.ts +4 -0
- package/dist/zspec/index.d.ts.map +1 -0
- package/dist/zspec/index.js +43 -0
- package/dist/zspec/index.js.map +1 -0
- package/dist/zspec/tstypes.d.ts +19 -0
- package/dist/zspec/tstypes.d.ts.map +1 -0
- package/dist/zspec/tstypes.js +3 -0
- package/dist/zspec/tstypes.js.map +1 -0
- package/dist/zspec/utils.d.ts +77 -0
- package/dist/zspec/utils.d.ts.map +1 -0
- package/dist/zspec/utils.js +217 -0
- package/dist/zspec/utils.js.map +1 -0
- package/dist/zspec/zcl/buffaloZcl.d.ts +43 -0
- package/dist/zspec/zcl/definition/cluster.d.ts +3 -0
- package/dist/zspec/zcl/definition/consts.d.ts +9 -0
- package/dist/zspec/zcl/definition/consts.d.ts.map +1 -0
- package/dist/zspec/zcl/definition/consts.js +27 -0
- package/dist/zspec/zcl/definition/consts.js.map +1 -0
- package/dist/zspec/zcl/definition/datatypes.d.ts +2173 -0
- package/dist/zspec/zcl/definition/datatypes.d.ts.map +1 -0
- package/dist/zspec/zcl/definition/datatypes.js +2315 -0
- package/dist/zspec/zcl/definition/datatypes.js.map +1 -0
- package/dist/zspec/zcl/definition/enums.d.ts +205 -0
- package/dist/zspec/zcl/definition/enums.d.ts.map +1 -0
- package/dist/zspec/zcl/definition/enums.js +218 -0
- package/dist/zspec/zcl/definition/enums.js.map +1 -0
- package/dist/zspec/zcl/definition/foundation.d.ts +10 -0
- package/dist/zspec/zcl/definition/manufacturerCode.d.ts +729 -0
- package/dist/zspec/zcl/definition/manufacturerCode.d.ts.map +1 -0
- package/dist/zspec/zcl/definition/manufacturerCode.js +734 -0
- package/dist/zspec/zcl/definition/manufacturerCode.js.map +1 -0
- package/dist/zspec/zcl/definition/status.d.ts +69 -0
- package/dist/zspec/zcl/definition/status.d.ts.map +1 -0
- package/dist/zspec/zcl/definition/status.js +74 -0
- package/dist/zspec/zcl/definition/status.js.map +1 -0
- package/dist/zspec/zcl/index.d.ts +12 -0
- package/dist/zspec/zcl/utils.d.ts +15 -0
- package/dist/zspec/zcl/zclFrame.d.ts +49 -0
- package/dist/zspec/zcl/zclHeader.d.ts +16 -0
- package/dist/zspec/zcl/zclStatusError.d.ts +6 -0
- package/dist/zspec/zcl/zclStatusError.d.ts.map +1 -0
- package/dist/zspec/zcl/zclStatusError.js +13 -0
- package/dist/zspec/zcl/zclStatusError.js.map +1 -0
- package/dist/zspec/zdo/buffaloZdo.d.ts +407 -0
- package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -0
- package/dist/zspec/zdo/buffaloZdo.js +1919 -0
- package/dist/zspec/zdo/buffaloZdo.js.map +1 -0
- package/dist/zspec/zdo/definition/clusters.d.ts +624 -0
- package/dist/zspec/zdo/definition/clusters.d.ts.map +1 -0
- package/dist/zspec/zdo/definition/clusters.js +686 -0
- package/dist/zspec/zdo/definition/clusters.js.map +1 -0
- package/dist/zspec/zdo/definition/consts.d.ts +13 -0
- package/dist/zspec/zdo/definition/consts.d.ts.map +1 -0
- package/dist/zspec/zdo/definition/consts.js +16 -0
- package/dist/zspec/zdo/definition/consts.js.map +1 -0
- package/dist/zspec/zdo/definition/enums.d.ts +85 -0
- package/dist/zspec/zdo/definition/enums.d.ts.map +1 -0
- package/dist/zspec/zdo/definition/enums.js +103 -0
- package/dist/zspec/zdo/definition/enums.js.map +1 -0
- package/dist/zspec/zdo/definition/status.d.ts +99 -0
- package/dist/zspec/zdo/definition/status.d.ts.map +1 -0
- package/dist/zspec/zdo/definition/status.js +108 -0
- package/dist/zspec/zdo/definition/status.js.map +1 -0
- package/dist/zspec/zdo/definition/tstypes.d.ts +955 -0
- package/dist/zspec/zdo/definition/tstypes.d.ts.map +1 -0
- package/dist/zspec/zdo/definition/tstypes.js +4 -0
- package/dist/zspec/zdo/definition/tstypes.js.map +1 -0
- package/dist/zspec/zdo/index.d.ts +8 -0
- package/dist/zspec/zdo/index.d.ts.map +1 -0
- package/dist/zspec/zdo/index.js +51 -0
- package/dist/zspec/zdo/index.js.map +1 -0
- package/dist/zspec/zdo/utils.d.ts +24 -0
- package/dist/zspec/zdo/utils.d.ts.map +1 -0
- package/dist/zspec/zdo/utils.js +74 -0
- package/dist/zspec/zdo/utils.js.map +1 -0
- package/dist/zspec/zdo/zdoStatusError.d.ts +6 -0
- package/dist/zspec/zdo/zdoStatusError.d.ts.map +1 -0
- package/dist/zspec/zdo/zdoStatusError.js +13 -0
- package/dist/zspec/zdo/zdoStatusError.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1663 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
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
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.EmberAdapter = exports.DEFAULT_APS_OPTIONS = exports.DEFAULT_STACK_CONFIG = void 0;
|
|
40
|
+
const node_crypto_1 = require("node:crypto");
|
|
41
|
+
const node_fs_1 = require("node:fs");
|
|
42
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
43
|
+
const es6_1 = __importDefault(require("fast-deep-equal/es6"));
|
|
44
|
+
const utils_1 = require("../../../utils");
|
|
45
|
+
const logger_1 = require("../../../utils/logger");
|
|
46
|
+
const ZSpec = __importStar(require("../../../zspec"));
|
|
47
|
+
const Zcl = __importStar(require("../../../zspec/zcl"));
|
|
48
|
+
const Zdo = __importStar(require("../../../zspec/zdo"));
|
|
49
|
+
const __1 = require("../..");
|
|
50
|
+
const const_1 = require("../../const");
|
|
51
|
+
const utils_2 = require("../../utils");
|
|
52
|
+
const consts_1 = require("../consts");
|
|
53
|
+
const enums_1 = require("../enums");
|
|
54
|
+
const buffalo_1 = require("../ezsp/buffalo");
|
|
55
|
+
const consts_2 = require("../ezsp/consts");
|
|
56
|
+
const enums_2 = require("../ezsp/enums");
|
|
57
|
+
const ezsp_1 = require("../ezsp/ezsp");
|
|
58
|
+
const ezspError_1 = require("../ezspError");
|
|
59
|
+
const initters_1 = require("../utils/initters");
|
|
60
|
+
const math_1 = require("../utils/math");
|
|
61
|
+
const endpoints_1 = require("./endpoints");
|
|
62
|
+
const oneWaitress_1 = require("./oneWaitress");
|
|
63
|
+
const NS = "zh:ember";
|
|
64
|
+
var NetworkInitAction;
|
|
65
|
+
(function (NetworkInitAction) {
|
|
66
|
+
/** Ain't that nice! */
|
|
67
|
+
NetworkInitAction[NetworkInitAction["DONE"] = 0] = "DONE";
|
|
68
|
+
/** Config mismatch, must leave network. */
|
|
69
|
+
NetworkInitAction[NetworkInitAction["LEAVE"] = 1] = "LEAVE";
|
|
70
|
+
/** Config mismatched, left network. Will evaluate forming from backup or config next. */
|
|
71
|
+
NetworkInitAction[NetworkInitAction["LEFT"] = 2] = "LEFT";
|
|
72
|
+
/** Form the network using config. No backup, or backup mismatch. */
|
|
73
|
+
NetworkInitAction[NetworkInitAction["FORM_CONFIG"] = 3] = "FORM_CONFIG";
|
|
74
|
+
/** Re-form the network using full backed-up data. */
|
|
75
|
+
NetworkInitAction[NetworkInitAction["FORM_BACKUP"] = 4] = "FORM_BACKUP";
|
|
76
|
+
})(NetworkInitAction || (NetworkInitAction = {}));
|
|
77
|
+
/**
|
|
78
|
+
* Application generated ZDO messages use sequence numbers 0-127, and the stack
|
|
79
|
+
* uses sequence numbers 128-255. This simplifies life by eliminating the need
|
|
80
|
+
* for coordination between the two entities, and allows both to send ZDO
|
|
81
|
+
* messages with non-conflicting sequence numbers.
|
|
82
|
+
*/
|
|
83
|
+
const APPLICATION_ZDO_SEQUENCE_MASK = 0x7f;
|
|
84
|
+
/* Default radius used for broadcast ZDO requests. uint8_t */
|
|
85
|
+
const ZDO_REQUEST_RADIUS = 0xff;
|
|
86
|
+
/** Oldest supported EZSP version for backups. Don't take the risk to restore a broken network until older backup versions can be investigated. */
|
|
87
|
+
const BACKUP_OLDEST_SUPPORTED_EZSP_VERSION = 12;
|
|
88
|
+
/**
|
|
89
|
+
* 9sec is minimum recommended for `ezspBroadcastNextNetworkKey` to have propagated throughout network.
|
|
90
|
+
* NOTE: This is blocking the request queue, so we shouldn't go crazy high.
|
|
91
|
+
*/
|
|
92
|
+
const BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME = 15000;
|
|
93
|
+
const QUEUE_MAX_SEND_ATTEMPTS = 3;
|
|
94
|
+
const QUEUE_BUSY_DEFER_MSEC = 500;
|
|
95
|
+
const QUEUE_NETWORK_DOWN_DEFER_MSEC = 1500;
|
|
96
|
+
/**
|
|
97
|
+
* Default stack configuration values.
|
|
98
|
+
* @see https://www.silabs.com/documents/public/user-guides/ug100-ezsp-reference-guide.pdf 2.3.1 for descriptions/RAM costs
|
|
99
|
+
*
|
|
100
|
+
* https://github.com/darkxst/silabs-firmware-builder/tree/main/manifests
|
|
101
|
+
* https://github.com/NabuCasa/silabs-firmware/wiki/Zigbee-EmberZNet-NCP-firmware-configuration#skyconnect
|
|
102
|
+
* https://github.com/SiliconLabs/UnifySDK/blob/main/applications/zigbeed/project_files/zigbeed.slcp
|
|
103
|
+
*/
|
|
104
|
+
exports.DEFAULT_STACK_CONFIG = {
|
|
105
|
+
CONCENTRATOR_RAM_TYPE: "high",
|
|
106
|
+
CONCENTRATOR_MIN_TIME: 5, // zigpc: 10
|
|
107
|
+
CONCENTRATOR_MAX_TIME: 60, // zigpc: 60
|
|
108
|
+
CONCENTRATOR_ROUTE_ERROR_THRESHOLD: 3, // zigpc: 3
|
|
109
|
+
CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD: 1, // zigpc: 1, ZigbeeMinimalHost: 3
|
|
110
|
+
CONCENTRATOR_MAX_HOPS: 0, // zigpc: 0
|
|
111
|
+
MAX_END_DEVICE_CHILDREN: 32, // zigpc: 6, nabucasa: 32, Dongle-E (Sonoff firmware): 32
|
|
112
|
+
TRANSIENT_DEVICE_TIMEOUT: 10000,
|
|
113
|
+
END_DEVICE_POLL_TIMEOUT: 8, // zigpc: 8
|
|
114
|
+
TRANSIENT_KEY_TIMEOUT_S: 300, // zigpc: 65535
|
|
115
|
+
CCA_MODE: undefined, // not set by default
|
|
116
|
+
};
|
|
117
|
+
/** Default behavior is to disable app key requests */
|
|
118
|
+
const ALLOW_APP_KEY_REQUESTS = false;
|
|
119
|
+
/** @see EzspConfigId.TRUST_CENTER_ADDRESS_CACHE_SIZE */
|
|
120
|
+
const TRUST_CENTER_ADDRESS_CACHE_SIZE = 2;
|
|
121
|
+
/**
|
|
122
|
+
* NOTE: This from SDK is currently ignored here because of issues in below links:
|
|
123
|
+
* - BUGZID 12261: Concentrators use MTORRs for route discovery and should not enable route discovery in the APS options.
|
|
124
|
+
* - https://community.silabs.com/s/question/0D58Y00008DRfDCSA1/coordinator-cant-send-unicast-to-sleepy-node-after-reboot
|
|
125
|
+
* - https://community.silabs.com/s/question/0D58Y0000B4nTb7SQE/largedense-network-communication-problem-source-route-table-not-big-enough
|
|
126
|
+
*
|
|
127
|
+
* Removing `ENABLE_ROUTE_DISCOVERY` leads to devices that won't reconnect/go offline, and various other issues. Keeping it for now.
|
|
128
|
+
*/
|
|
129
|
+
exports.DEFAULT_APS_OPTIONS = enums_1.EmberApsOption.RETRY | enums_1.EmberApsOption.ENABLE_ROUTE_DISCOVERY | enums_1.EmberApsOption.ENABLE_ADDRESS_DISCOVERY;
|
|
130
|
+
/** Time for a request to get a callback response. ASH is 2400*6 for ACK timeout. */
|
|
131
|
+
const DEFAULT_REQUEST_TIMEOUT = 15000; // msec
|
|
132
|
+
/** Time for a network-related request to get a response (usually via event). */
|
|
133
|
+
const DEFAULT_NETWORK_REQUEST_TIMEOUT = 10000; // nothing on the network to bother requests, should be much faster than this
|
|
134
|
+
/** Time between watchdog counters reading/clearing */
|
|
135
|
+
const WATCHDOG_COUNTERS_FEED_INTERVAL = 3600000; // every hour...
|
|
136
|
+
/** Default manufacturer code reported by coordinator. */
|
|
137
|
+
const DEFAULT_MANUFACTURER_CODE = Zcl.ManufacturerCode.SILICON_LABORATORIES;
|
|
138
|
+
/**
|
|
139
|
+
* Relay calls between Z2M and EZSP-layer and handle any error that might occur via queue & waitress.
|
|
140
|
+
*
|
|
141
|
+
* Anything post `start` that requests anything from the EZSP layer must run through the request queue for proper execution flow.
|
|
142
|
+
*/
|
|
143
|
+
class EmberAdapter extends __1.Adapter {
|
|
144
|
+
/** Current manufacturer code assigned to the coordinator. Used for join workarounds... */
|
|
145
|
+
manufacturerCode;
|
|
146
|
+
stackConfig;
|
|
147
|
+
ezsp;
|
|
148
|
+
version;
|
|
149
|
+
queue;
|
|
150
|
+
oneWaitress;
|
|
151
|
+
/** Periodically retrieve counters then clear them. */
|
|
152
|
+
watchdogCountersHandle;
|
|
153
|
+
/** Sequence number used for ZDO requests. static uint8_t */
|
|
154
|
+
zdoRequestSequence;
|
|
155
|
+
interpanLock;
|
|
156
|
+
/**
|
|
157
|
+
* Cached network params to avoid NCP calls. Prevents frequent EZSP transactions.
|
|
158
|
+
* NOTE: Do not use directly, use getter functions for it that check if valid or need retrieval from NCP.
|
|
159
|
+
*/
|
|
160
|
+
networkCache;
|
|
161
|
+
multicastTable;
|
|
162
|
+
constructor(networkOptions, serialPortOptions, backupPath, adapterOptions) {
|
|
163
|
+
super(networkOptions, serialPortOptions, backupPath, adapterOptions);
|
|
164
|
+
this.hasZdoMessageOverhead = true;
|
|
165
|
+
this.manufacturerID = Zcl.ManufacturerCode.SILICON_LABORATORIES;
|
|
166
|
+
this.version = {
|
|
167
|
+
ezsp: 0,
|
|
168
|
+
revision: "unknown",
|
|
169
|
+
build: 0,
|
|
170
|
+
major: 0,
|
|
171
|
+
minor: 0,
|
|
172
|
+
patch: 0,
|
|
173
|
+
special: 0,
|
|
174
|
+
type: enums_1.EmberVersionType.GA,
|
|
175
|
+
};
|
|
176
|
+
this.zdoRequestSequence = 0; // start at 1
|
|
177
|
+
this.interpanLock = false;
|
|
178
|
+
this.networkCache = (0, initters_1.initNetworkCache)();
|
|
179
|
+
this.manufacturerCode = DEFAULT_MANUFACTURER_CODE; // will be set in NCP in initEzsp
|
|
180
|
+
this.multicastTable = [];
|
|
181
|
+
this.stackConfig = this.loadStackConfig();
|
|
182
|
+
this.queue = new utils_1.Queue(this.adapterOptions.concurrent || 16); // ORed to avoid 0 (not checked in settings/queue constructor)
|
|
183
|
+
this.oneWaitress = new oneWaitress_1.EmberOneWaitress();
|
|
184
|
+
this.ezsp = new ezsp_1.Ezsp(serialPortOptions);
|
|
185
|
+
this.ezsp.on("zdoResponse", this.onZDOResponse.bind(this));
|
|
186
|
+
this.ezsp.on("incomingMessage", this.onIncomingMessage.bind(this));
|
|
187
|
+
this.ezsp.on("touchlinkMessage", this.onTouchlinkMessage.bind(this));
|
|
188
|
+
this.ezsp.on("stackStatus", this.onStackStatus.bind(this));
|
|
189
|
+
this.ezsp.on("trustCenterJoin", this.onTrustCenterJoin.bind(this));
|
|
190
|
+
this.ezsp.on("messageSent", this.onMessageSent.bind(this));
|
|
191
|
+
this.ezsp.once("ncpNeedsResetAndInit", this.onNcpNeedsResetAndInit.bind(this));
|
|
192
|
+
}
|
|
193
|
+
loadStackConfig() {
|
|
194
|
+
// store stack config in same dir as backup
|
|
195
|
+
const configPath = node_path_1.default.join(node_path_1.default.dirname(this.backupPath), "stack_config.json");
|
|
196
|
+
try {
|
|
197
|
+
const customConfig = JSON.parse((0, node_fs_1.readFileSync)(configPath, "utf8"));
|
|
198
|
+
// set any undefined config to default
|
|
199
|
+
const config = { ...exports.DEFAULT_STACK_CONFIG, ...customConfig };
|
|
200
|
+
const inRange = (value, min, max) => !(value == null || value < min || value > max);
|
|
201
|
+
if (!["high", "low"].includes(config.CONCENTRATOR_RAM_TYPE)) {
|
|
202
|
+
config.CONCENTRATOR_RAM_TYPE = exports.DEFAULT_STACK_CONFIG.CONCENTRATOR_RAM_TYPE;
|
|
203
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CONCENTRATOR_RAM_TYPE, using default.", NS);
|
|
204
|
+
}
|
|
205
|
+
if (!inRange(config.CONCENTRATOR_MIN_TIME, 1, 60) || config.CONCENTRATOR_MIN_TIME >= config.CONCENTRATOR_MAX_TIME) {
|
|
206
|
+
config.CONCENTRATOR_MIN_TIME = exports.DEFAULT_STACK_CONFIG.CONCENTRATOR_MIN_TIME;
|
|
207
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CONCENTRATOR_MIN_TIME, using default.", NS);
|
|
208
|
+
}
|
|
209
|
+
if (!inRange(config.CONCENTRATOR_MAX_TIME, 30, 300) || config.CONCENTRATOR_MAX_TIME <= config.CONCENTRATOR_MIN_TIME) {
|
|
210
|
+
config.CONCENTRATOR_MAX_TIME = exports.DEFAULT_STACK_CONFIG.CONCENTRATOR_MAX_TIME;
|
|
211
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CONCENTRATOR_MAX_TIME, using default.", NS);
|
|
212
|
+
}
|
|
213
|
+
if (!inRange(config.CONCENTRATOR_ROUTE_ERROR_THRESHOLD, 1, 100)) {
|
|
214
|
+
config.CONCENTRATOR_ROUTE_ERROR_THRESHOLD = exports.DEFAULT_STACK_CONFIG.CONCENTRATOR_ROUTE_ERROR_THRESHOLD;
|
|
215
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CONCENTRATOR_ROUTE_ERROR_THRESHOLD, using default.", NS);
|
|
216
|
+
}
|
|
217
|
+
if (!inRange(config.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, 1, 100)) {
|
|
218
|
+
config.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD = exports.DEFAULT_STACK_CONFIG.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD;
|
|
219
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, using default.", NS);
|
|
220
|
+
}
|
|
221
|
+
if (!inRange(config.CONCENTRATOR_MAX_HOPS, 0, 30)) {
|
|
222
|
+
config.CONCENTRATOR_MAX_HOPS = exports.DEFAULT_STACK_CONFIG.CONCENTRATOR_MAX_HOPS;
|
|
223
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CONCENTRATOR_MAX_HOPS, using default.", NS);
|
|
224
|
+
}
|
|
225
|
+
if (!inRange(config.MAX_END_DEVICE_CHILDREN, 6, 64)) {
|
|
226
|
+
config.MAX_END_DEVICE_CHILDREN = exports.DEFAULT_STACK_CONFIG.MAX_END_DEVICE_CHILDREN;
|
|
227
|
+
logger_1.logger.error("[STACK CONFIG] Invalid MAX_END_DEVICE_CHILDREN, using default.", NS);
|
|
228
|
+
}
|
|
229
|
+
if (!inRange(config.TRANSIENT_DEVICE_TIMEOUT, 0, 65535)) {
|
|
230
|
+
config.TRANSIENT_DEVICE_TIMEOUT = exports.DEFAULT_STACK_CONFIG.TRANSIENT_DEVICE_TIMEOUT;
|
|
231
|
+
logger_1.logger.error("[STACK CONFIG] Invalid TRANSIENT_DEVICE_TIMEOUT, using default.", NS);
|
|
232
|
+
}
|
|
233
|
+
if (!inRange(config.END_DEVICE_POLL_TIMEOUT, 0, 14)) {
|
|
234
|
+
config.END_DEVICE_POLL_TIMEOUT = exports.DEFAULT_STACK_CONFIG.END_DEVICE_POLL_TIMEOUT;
|
|
235
|
+
logger_1.logger.error("[STACK CONFIG] Invalid END_DEVICE_POLL_TIMEOUT, using default.", NS);
|
|
236
|
+
}
|
|
237
|
+
if (!inRange(config.TRANSIENT_KEY_TIMEOUT_S, 0, 65535)) {
|
|
238
|
+
config.TRANSIENT_KEY_TIMEOUT_S = exports.DEFAULT_STACK_CONFIG.TRANSIENT_KEY_TIMEOUT_S;
|
|
239
|
+
logger_1.logger.error("[STACK CONFIG] Invalid TRANSIENT_KEY_TIMEOUT_S, using default.", NS);
|
|
240
|
+
}
|
|
241
|
+
config.CCA_MODE = config.CCA_MODE ?? undefined; // always default to undefined
|
|
242
|
+
if (config.CCA_MODE && enums_1.IEEE802154CcaMode[config.CCA_MODE] === undefined) {
|
|
243
|
+
config.CCA_MODE = undefined;
|
|
244
|
+
logger_1.logger.error("[STACK CONFIG] Invalid CCA_MODE, ignoring.", NS);
|
|
245
|
+
}
|
|
246
|
+
logger_1.logger.info(`Using stack config ${JSON.stringify(config)}.`, NS);
|
|
247
|
+
return config;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
/* empty */
|
|
251
|
+
}
|
|
252
|
+
logger_1.logger.info("Using default stack config.", NS);
|
|
253
|
+
return exports.DEFAULT_STACK_CONFIG;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Emitted from @see Ezsp.ezspStackStatusHandler
|
|
257
|
+
* @param status
|
|
258
|
+
*/
|
|
259
|
+
async onStackStatus(status) {
|
|
260
|
+
// to be extra careful, should clear network cache upon receiving this.
|
|
261
|
+
this.clearNetworkCache();
|
|
262
|
+
switch (status) {
|
|
263
|
+
case enums_1.SLStatus.NETWORK_UP: {
|
|
264
|
+
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP);
|
|
265
|
+
logger_1.logger.info("[STACK STATUS] Network up.", NS);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case enums_1.SLStatus.NETWORK_DOWN: {
|
|
269
|
+
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_DOWN);
|
|
270
|
+
logger_1.logger.info("[STACK STATUS] Network down.", NS);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case enums_1.SLStatus.ZIGBEE_NETWORK_OPENED: {
|
|
274
|
+
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_OPENED);
|
|
275
|
+
logger_1.logger.info("[STACK STATUS] Network opened.", NS);
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case enums_1.SLStatus.ZIGBEE_NETWORK_CLOSED: {
|
|
279
|
+
this.oneWaitress.resolveEvent(oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_CLOSED);
|
|
280
|
+
logger_1.logger.info("[STACK STATUS] Network closed.", NS);
|
|
281
|
+
if (this.manufacturerCode !== DEFAULT_MANUFACTURER_CODE) {
|
|
282
|
+
await this.queue.execute(async () => {
|
|
283
|
+
logger_1.logger.debug("[WORKAROUND] Reverting coordinator manufacturer code to default.", NS);
|
|
284
|
+
await this.ezsp.ezspSetManufacturerCode(DEFAULT_MANUFACTURER_CODE);
|
|
285
|
+
this.manufacturerCode = DEFAULT_MANUFACTURER_CODE;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case enums_1.SLStatus.ZIGBEE_CHANNEL_CHANGED: {
|
|
291
|
+
// invalidate cache
|
|
292
|
+
this.networkCache.parameters.radioChannel = consts_1.INVALID_RADIO_CHANNEL;
|
|
293
|
+
logger_1.logger.info("[STACK STATUS] Channel changed.", NS);
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
default: {
|
|
297
|
+
logger_1.logger.debug(`[STACK STATUS] ${enums_1.SLStatus[status]}.`, NS);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Emitted from @see Ezsp.ezspMessageSentHandler
|
|
304
|
+
* WARNING: Cannot rely on `ezspMessageSentHandler` > `ezspIncomingMessageHandler` order, some devices mix it up!
|
|
305
|
+
*
|
|
306
|
+
* @param type
|
|
307
|
+
* @param indexOrDestination
|
|
308
|
+
* @param apsFrame
|
|
309
|
+
* @param messageTag
|
|
310
|
+
* @param status
|
|
311
|
+
*/
|
|
312
|
+
async onMessageSent(status, type, indexOrDestination, apsFrame, messageTag) {
|
|
313
|
+
switch (status) {
|
|
314
|
+
case enums_1.SLStatus.ZIGBEE_DELIVERY_FAILED: {
|
|
315
|
+
logger_1.logger.debug(() => `~x~> DELIVERY_FAILED [indexOrDestination=${indexOrDestination} apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS);
|
|
316
|
+
// no ACK was received from the destination
|
|
317
|
+
switch (type) {
|
|
318
|
+
case enums_1.EmberOutgoingMessageType.BROADCAST:
|
|
319
|
+
case enums_1.EmberOutgoingMessageType.BROADCAST_WITH_ALIAS:
|
|
320
|
+
case enums_1.EmberOutgoingMessageType.MULTICAST:
|
|
321
|
+
case enums_1.EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: {
|
|
322
|
+
// BC/MC not checking for message sent, avoid unnecessary waitress lookups
|
|
323
|
+
logger_1.logger.error(`Delivery of ${enums_1.EmberOutgoingMessageType[type]} failed for '${indexOrDestination}'.`, NS);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
default: {
|
|
327
|
+
// reject any waitress early (don't wait for timeout if we know we're gonna get there eventually)
|
|
328
|
+
this.oneWaitress.deliveryFailedFor(indexOrDestination, apsFrame);
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
case enums_1.SLStatus.OK: {
|
|
335
|
+
if (type === enums_1.EmberOutgoingMessageType.MULTICAST &&
|
|
336
|
+
apsFrame.destinationEndpoint === 0xff &&
|
|
337
|
+
apsFrame.groupId < consts_1.EMBER_MIN_BROADCAST_ADDRESS &&
|
|
338
|
+
!this.multicastTable.includes(apsFrame.groupId)) {
|
|
339
|
+
// workaround for devices using multicast for state update (coordinator passthrough)
|
|
340
|
+
const tableIdx = this.multicastTable.length;
|
|
341
|
+
const multicastEntry = {
|
|
342
|
+
multicastId: apsFrame.groupId,
|
|
343
|
+
endpoint: endpoints_1.FIXED_ENDPOINTS[0].endpoint,
|
|
344
|
+
networkIndex: endpoints_1.FIXED_ENDPOINTS[0].networkIndex,
|
|
345
|
+
};
|
|
346
|
+
// set immediately to avoid potential race
|
|
347
|
+
this.multicastTable.push(multicastEntry.multicastId);
|
|
348
|
+
try {
|
|
349
|
+
await this.queue.execute(async () => {
|
|
350
|
+
const status = await this.ezsp.ezspSetMulticastTableEntry(tableIdx, multicastEntry);
|
|
351
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
352
|
+
throw new Error(`Failed to register group '${multicastEntry.multicastId}' in multicast table with status=${enums_1.SLStatus[status]}.`);
|
|
353
|
+
}
|
|
354
|
+
logger_1.logger.debug(() => `Registered multicast table entry (${tableIdx}): ${JSON.stringify(multicastEntry)}.`, NS);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
// remove to allow retry on next occurrence
|
|
359
|
+
this.multicastTable.splice(tableIdx, 1);
|
|
360
|
+
logger_1.logger.error(error.message, NS);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// shouldn't be any other status
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Emitted from @see Ezsp.ezspIncomingMessageHandler
|
|
370
|
+
*
|
|
371
|
+
* @param apsFrame The APS frame associated with the response.
|
|
372
|
+
* @param sender The sender of the response. Should match `payload.nodeId` in many responses.
|
|
373
|
+
* @param messageContents The content of the response.
|
|
374
|
+
*/
|
|
375
|
+
onZDOResponse(apsFrame, sender, messageContents) {
|
|
376
|
+
const result = Zdo.Buffalo.readResponse(this.hasZdoMessageOverhead, apsFrame.clusterId, messageContents);
|
|
377
|
+
if (apsFrame.clusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE) {
|
|
378
|
+
// special case to properly resolve a NETWORK_ADDRESS_RESPONSE following a NETWORK_ADDRESS_REQUEST (based on EUI64 from ZDO payload)
|
|
379
|
+
// NOTE: if response has invalid status (no EUI64 available), response waiter will eventually time out
|
|
380
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
381
|
+
this.oneWaitress.resolveZDO(result[1].eui64, apsFrame, result);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
this.oneWaitress.resolveZDO(sender, apsFrame, result);
|
|
386
|
+
}
|
|
387
|
+
this.emit("zdoResponse", apsFrame.clusterId, result);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Emitted from @see Ezsp.ezspIncomingMessageHandler @see Ezsp.ezspGpepIncomingMessageHandler
|
|
391
|
+
*
|
|
392
|
+
* @param type
|
|
393
|
+
* @param apsFrame
|
|
394
|
+
* @param lastHopLqi
|
|
395
|
+
* @param sender
|
|
396
|
+
* @param messageContents
|
|
397
|
+
*/
|
|
398
|
+
onIncomingMessage(type, apsFrame, lastHopLqi, sender, messageContents) {
|
|
399
|
+
const payload = {
|
|
400
|
+
clusterID: apsFrame.clusterId,
|
|
401
|
+
header: Zcl.Header.fromBuffer(messageContents),
|
|
402
|
+
address: sender,
|
|
403
|
+
data: messageContents,
|
|
404
|
+
endpoint: apsFrame.sourceEndpoint,
|
|
405
|
+
linkquality: lastHopLqi,
|
|
406
|
+
groupID: apsFrame.groupId,
|
|
407
|
+
wasBroadcast: type === enums_1.EmberIncomingMessageType.BROADCAST || type === enums_1.EmberIncomingMessageType.BROADCAST_LOOPBACK,
|
|
408
|
+
destinationEndpoint: apsFrame.destinationEndpoint,
|
|
409
|
+
};
|
|
410
|
+
this.oneWaitress.resolveZCL(payload);
|
|
411
|
+
this.emit("zclPayload", payload);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Emitted from @see Ezsp.ezspMacFilterMatchMessageHandler when the message is a valid InterPAN touchlink message.
|
|
415
|
+
*
|
|
416
|
+
* @param _sourcePanId
|
|
417
|
+
* @param sourceAddress
|
|
418
|
+
* @param groupId
|
|
419
|
+
* @param lastHopLqi
|
|
420
|
+
* @param messageContents
|
|
421
|
+
*/
|
|
422
|
+
onTouchlinkMessage(_sourcePanId, sourceAddress, groupId, lastHopLqi, messageContents) {
|
|
423
|
+
const endpoint = endpoints_1.FIXED_ENDPOINTS[0].endpoint;
|
|
424
|
+
const payload = {
|
|
425
|
+
clusterID: Zcl.Clusters.touchlink.ID,
|
|
426
|
+
data: messageContents,
|
|
427
|
+
header: Zcl.Header.fromBuffer(messageContents),
|
|
428
|
+
address: sourceAddress,
|
|
429
|
+
endpoint: endpoint, // arbitrary since not sent over-the-air
|
|
430
|
+
linkquality: lastHopLqi,
|
|
431
|
+
groupID: groupId,
|
|
432
|
+
wasBroadcast: true, // XXX: since always sent broadcast atm...
|
|
433
|
+
destinationEndpoint: endpoint,
|
|
434
|
+
};
|
|
435
|
+
this.oneWaitress.resolveZCL(payload);
|
|
436
|
+
this.emit("zclPayload", payload);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Emitted from @see Ezsp.ezspTrustCenterJoinHandler
|
|
440
|
+
* Also from @see Ezsp.ezspIdConflictHandler as a DEVICE_LEFT
|
|
441
|
+
*
|
|
442
|
+
* @param newNodeId
|
|
443
|
+
* @param newNodeEui64
|
|
444
|
+
* @param status
|
|
445
|
+
* @param policyDecision
|
|
446
|
+
* @param parentOfNewNodeId
|
|
447
|
+
*/
|
|
448
|
+
async onTrustCenterJoin(newNodeId, newNodeEui64, status, policyDecision, parentOfNewNodeId) {
|
|
449
|
+
if (status === enums_1.EmberDeviceUpdate.DEVICE_LEFT) {
|
|
450
|
+
const payload = {
|
|
451
|
+
networkAddress: newNodeId,
|
|
452
|
+
ieeeAddr: newNodeEui64,
|
|
453
|
+
};
|
|
454
|
+
this.emit("deviceLeave", payload);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
if (policyDecision !== enums_1.EmberJoinDecision.DENY_JOIN) {
|
|
458
|
+
const payload = {
|
|
459
|
+
networkAddress: newNodeId,
|
|
460
|
+
ieeeAddr: newNodeEui64,
|
|
461
|
+
};
|
|
462
|
+
// set workaround manuf code if necessary, or revert to default if previous joined device required workaround and new one does not
|
|
463
|
+
const joinManufCode = const_1.WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE[newNodeEui64.substring(0, 8)] ?? DEFAULT_MANUFACTURER_CODE;
|
|
464
|
+
if (this.manufacturerCode !== joinManufCode) {
|
|
465
|
+
await this.queue.execute(async () => {
|
|
466
|
+
logger_1.logger.debug(`[WORKAROUND] Setting coordinator manufacturer code to ${Zcl.ManufacturerCode[joinManufCode]}.`, NS);
|
|
467
|
+
await this.ezsp.ezspSetManufacturerCode(joinManufCode);
|
|
468
|
+
this.manufacturerCode = joinManufCode;
|
|
469
|
+
this.emit("deviceJoined", payload);
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
this.emit("deviceJoined", payload);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
logger_1.logger.warning(`[TRUST CENTER] Device ${newNodeId}:${newNodeEui64} was denied joining via ${parentOfNewNodeId}.`, NS);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
async watchdogCounters() {
|
|
482
|
+
await this.queue.execute(async () => {
|
|
483
|
+
// listed as per EmberCounterType
|
|
484
|
+
const ncpCounters = await this.ezsp.ezspReadAndClearCounters();
|
|
485
|
+
logger_1.logger.info(`[NCP COUNTERS] ${ncpCounters.join(",")}`, NS);
|
|
486
|
+
const ashCounters = this.ezsp.ash.readAndClearCounters();
|
|
487
|
+
logger_1.logger.info(`[ASH COUNTERS] ${ashCounters.join(",")}`, NS);
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Proceed to execute the long list of commands required to setup comms between Host<>NCP.
|
|
492
|
+
* This is called by start and on internal reset.
|
|
493
|
+
*/
|
|
494
|
+
async initEzsp() {
|
|
495
|
+
let result = "resumed";
|
|
496
|
+
// NOTE: something deep in this call can throw too
|
|
497
|
+
const startResult = await this.ezsp.start();
|
|
498
|
+
if (startResult !== enums_1.EzspStatus.SUCCESS) {
|
|
499
|
+
throw new Error(`Failed to start EZSP layer with status=${enums_1.EzspStatus[startResult]}.`);
|
|
500
|
+
}
|
|
501
|
+
// call before any other command, else fails
|
|
502
|
+
await this.emberVersion();
|
|
503
|
+
/** The address cache needs to be initialized and used with the source routing code for the trust center to operate properly. */
|
|
504
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TRUST_CENTER_ADDRESS_CACHE_SIZE, TRUST_CENTER_ADDRESS_CACHE_SIZE);
|
|
505
|
+
/** MAC indirect timeout should be 7.68 secs (STACK_PROFILE_ZIGBEE_PRO) */
|
|
506
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.INDIRECT_TRANSMISSION_TIMEOUT, 7680);
|
|
507
|
+
/** Max hops should be 2 * nwkMaxDepth, where nwkMaxDepth is 15 (STACK_PROFILE_ZIGBEE_PRO) */
|
|
508
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MAX_HOPS, 30);
|
|
509
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SUPPORTED_NETWORKS, 1);
|
|
510
|
+
// allow other devices to modify the binding table
|
|
511
|
+
await this.emberSetEzspPolicy(enums_2.EzspPolicyId.BINDING_MODIFICATION_POLICY, enums_2.EzspDecisionId.CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS);
|
|
512
|
+
// return message tag only in ezspMessageSentHandler()
|
|
513
|
+
await this.emberSetEzspPolicy(enums_2.EzspPolicyId.MESSAGE_CONTENTS_IN_CALLBACK_POLICY, enums_2.EzspDecisionId.MESSAGE_TAG_ONLY_IN_CALLBACK);
|
|
514
|
+
await this.emberSetEzspValue(enums_2.EzspValueId.TRANSIENT_DEVICE_TIMEOUT, 2, (0, math_1.lowHighBytes)(this.stackConfig.TRANSIENT_DEVICE_TIMEOUT));
|
|
515
|
+
await this.ezsp.ezspSetManufacturerCode(this.manufacturerCode);
|
|
516
|
+
// network security init
|
|
517
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.STACK_PROFILE, consts_1.STACK_PROFILE_ZIGBEE_PRO);
|
|
518
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.SECURITY_LEVEL, consts_1.SECURITY_LEVEL_Z3);
|
|
519
|
+
// common configs
|
|
520
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.MAX_END_DEVICE_CHILDREN, this.stackConfig.MAX_END_DEVICE_CHILDREN);
|
|
521
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.END_DEVICE_POLL_TIMEOUT, this.stackConfig.END_DEVICE_POLL_TIMEOUT);
|
|
522
|
+
await this.emberSetEzspConfigValue(enums_2.EzspConfigId.TRANSIENT_KEY_TIMEOUT_S, this.stackConfig.TRANSIENT_KEY_TIMEOUT_S);
|
|
523
|
+
// XXX: temp-fix: forces a side-effect in the firmware that prevents broadcast issues in environments with unusual interferences
|
|
524
|
+
await this.emberSetEzspValue(enums_2.EzspValueId.CCA_THRESHOLD, 1, [0]);
|
|
525
|
+
if (this.stackConfig.CCA_MODE) {
|
|
526
|
+
// validated in `loadStackConfig`
|
|
527
|
+
await this.ezsp.ezspSetRadioIeee802154CcaMode(enums_1.IEEE802154CcaMode[this.stackConfig.CCA_MODE]);
|
|
528
|
+
}
|
|
529
|
+
// WARNING: From here on EZSP commands that affect memory allocation on the NCP should no longer be called (like resizing tables)
|
|
530
|
+
await this.registerFixedEndpoints();
|
|
531
|
+
this.clearNetworkCache();
|
|
532
|
+
result = await this.initTrustCenter();
|
|
533
|
+
// after network UP, as per SDK, ensures clean slate
|
|
534
|
+
await this.initNCPConcentrator();
|
|
535
|
+
// populate network cache info
|
|
536
|
+
const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
|
|
537
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
538
|
+
throw new Error(`Failed to get network parameters with status=${enums_1.SLStatus[status]}.`);
|
|
539
|
+
}
|
|
540
|
+
if (this.adapterOptions.transmitPower != null && parameters.radioTxPower !== this.adapterOptions.transmitPower) {
|
|
541
|
+
const status = await this.ezsp.ezspSetRadioPower(this.adapterOptions.transmitPower);
|
|
542
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
543
|
+
// soft-fail, don't prevent start
|
|
544
|
+
logger_1.logger.error(`Failed to set transmit power to ${this.adapterOptions.transmitPower} status=${enums_1.SLStatus[status]}.`, NS);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
this.networkCache.parameters = parameters;
|
|
548
|
+
this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
|
|
549
|
+
logger_1.logger.debug(() => `[INIT] Network Ready! ${JSON.stringify(this.networkCache)}`, NS);
|
|
550
|
+
this.watchdogCountersHandle = setInterval(this.watchdogCounters.bind(this), WATCHDOG_COUNTERS_FEED_INTERVAL);
|
|
551
|
+
return result;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* NCP concentrator init. Also enables source route discovery mode with RESCHEDULE.
|
|
555
|
+
*
|
|
556
|
+
* From AN1233:
|
|
557
|
+
* To function correctly in a Zigbee PRO network, a trust center also requires that:
|
|
558
|
+
*
|
|
559
|
+
* 1. The trust center application must act as a concentrator (either high or low RAM).
|
|
560
|
+
* 2. The trust center application must have support for source routing.
|
|
561
|
+
* It must record the source routes and properly handle requests by the stack for a particular source route.
|
|
562
|
+
* 3. The trust center application must use an address cache for security, in order to maintain a mapping of IEEE address to short ID.
|
|
563
|
+
*
|
|
564
|
+
* Failure to satisfy all of the above requirements may result in failures when joining/rejoining devices to the network across multiple hops
|
|
565
|
+
* (through a target node that is neither the trust center nor one of its neighboring routers.)
|
|
566
|
+
*/
|
|
567
|
+
async initNCPConcentrator() {
|
|
568
|
+
const status = await this.ezsp.ezspSetConcentrator(true, this.stackConfig.CONCENTRATOR_RAM_TYPE === "low" ? consts_1.EMBER_LOW_RAM_CONCENTRATOR : consts_1.EMBER_HIGH_RAM_CONCENTRATOR, this.stackConfig.CONCENTRATOR_MIN_TIME, this.stackConfig.CONCENTRATOR_MAX_TIME, this.stackConfig.CONCENTRATOR_ROUTE_ERROR_THRESHOLD, this.stackConfig.CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD, this.stackConfig.CONCENTRATOR_MAX_HOPS);
|
|
569
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
570
|
+
throw new Error(`[CONCENTRATOR] Failed to set concentrator with status=${enums_1.SLStatus[status]}.`);
|
|
571
|
+
}
|
|
572
|
+
const remainTilMTORR = await this.ezsp.ezspSetSourceRouteDiscoveryMode(enums_1.EmberSourceRouteDiscoveryMode.RESCHEDULE);
|
|
573
|
+
logger_1.logger.info(`[CONCENTRATOR] Started source route discovery. ${remainTilMTORR}ms until next broadcast.`, NS);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Register fixed endpoints and set any related multicast entries that need to be.
|
|
577
|
+
*/
|
|
578
|
+
async registerFixedEndpoints() {
|
|
579
|
+
for (const ep of endpoints_1.FIXED_ENDPOINTS) {
|
|
580
|
+
const [epStatus] = await this.ezsp.ezspGetEndpointFlags(ep.endpoint);
|
|
581
|
+
// endpoint not already registered
|
|
582
|
+
if (epStatus !== enums_1.SLStatus.OK) {
|
|
583
|
+
// check to see if ezspAddEndpoint needs to be called
|
|
584
|
+
// if ezspInit is called without NCP reset, ezspAddEndpoint is not necessary and will return an error
|
|
585
|
+
const status = await this.ezsp.ezspAddEndpoint(ep.endpoint, ep.profileId, ep.deviceId, ep.deviceVersion, ep.inClusterList.slice(), // copy
|
|
586
|
+
ep.outClusterList.slice());
|
|
587
|
+
if (status === enums_1.SLStatus.OK) {
|
|
588
|
+
logger_1.logger.debug(`Registered endpoint '${ep.endpoint}'.`, NS);
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
throw new Error(`Failed to register endpoint '${ep.endpoint}' with status=${enums_1.SLStatus[status]}.`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
logger_1.logger.debug(`Endpoint '${ep.endpoint}' already registered.`, NS);
|
|
596
|
+
}
|
|
597
|
+
for (const multicastId of ep.multicastIds) {
|
|
598
|
+
const multicastEntry = {
|
|
599
|
+
multicastId,
|
|
600
|
+
endpoint: ep.endpoint,
|
|
601
|
+
networkIndex: ep.networkIndex,
|
|
602
|
+
};
|
|
603
|
+
const status = await this.ezsp.ezspSetMulticastTableEntry(this.multicastTable.length, multicastEntry);
|
|
604
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
605
|
+
throw new Error(`Failed to register group '${multicastId}' in multicast table with status=${enums_1.SLStatus[status]}.`);
|
|
606
|
+
}
|
|
607
|
+
logger_1.logger.debug(() => `Registered multicast table entry (${this.multicastTable.length}): ${JSON.stringify(multicastEntry)}.`, NS);
|
|
608
|
+
this.multicastTable.push(multicastEntry.multicastId);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
*
|
|
614
|
+
* @returns True if the network needed to be formed.
|
|
615
|
+
*/
|
|
616
|
+
async initTrustCenter() {
|
|
617
|
+
// init TC policies
|
|
618
|
+
{
|
|
619
|
+
let status = await this.emberSetEzspPolicy(enums_2.EzspPolicyId.TC_KEY_REQUEST_POLICY, enums_2.EzspDecisionId.ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY);
|
|
620
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
621
|
+
throw new Error(`[INIT TC] Failed to set EzspPolicyId TC_KEY_REQUEST_POLICY to ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY with status=${enums_1.SLStatus[status]}.`);
|
|
622
|
+
}
|
|
623
|
+
/* v8 ignore next */
|
|
624
|
+
const appKeyRequestsPolicy = ALLOW_APP_KEY_REQUESTS ? enums_2.EzspDecisionId.ALLOW_APP_KEY_REQUESTS : enums_2.EzspDecisionId.DENY_APP_KEY_REQUESTS;
|
|
625
|
+
status = await this.emberSetEzspPolicy(enums_2.EzspPolicyId.APP_KEY_REQUEST_POLICY, appKeyRequestsPolicy);
|
|
626
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
627
|
+
throw new Error(`[INIT TC] Failed to set EzspPolicyId APP_KEY_REQUEST_POLICY to ${enums_2.EzspDecisionId[appKeyRequestsPolicy]} with status=${enums_1.SLStatus[status]}.`);
|
|
628
|
+
}
|
|
629
|
+
status = await this.emberSetJoinPolicy(enums_1.EmberJoinDecision.USE_PRECONFIGURED_KEY);
|
|
630
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
631
|
+
throw new Error(`[INIT TC] Failed to set join policy to USE_PRECONFIGURED_KEY with status=${enums_1.SLStatus[status]}.`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
635
|
+
const configNetworkKey = Buffer.from(this.networkOptions.networkKey);
|
|
636
|
+
const networkInitStruct = {
|
|
637
|
+
bitmask: enums_1.EmberNetworkInitBitmask.PARENT_INFO_IN_TOKEN | enums_1.EmberNetworkInitBitmask.END_DEVICE_REJOIN_ON_REBOOT,
|
|
638
|
+
};
|
|
639
|
+
const initStatus = await this.ezsp.ezspNetworkInit(networkInitStruct);
|
|
640
|
+
logger_1.logger.debug(`[INIT TC] Network init status=${enums_1.SLStatus[initStatus]}.`, NS);
|
|
641
|
+
if (initStatus !== enums_1.SLStatus.OK && initStatus !== enums_1.SLStatus.NOT_JOINED) {
|
|
642
|
+
throw new Error(`[INIT TC] Failed network init request with status=${enums_1.SLStatus[initStatus]}.`);
|
|
643
|
+
}
|
|
644
|
+
let action = NetworkInitAction.DONE;
|
|
645
|
+
if (initStatus === enums_1.SLStatus.OK) {
|
|
646
|
+
// network
|
|
647
|
+
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP }, DEFAULT_NETWORK_REQUEST_TIMEOUT, "[INIT TC] Network init");
|
|
648
|
+
const [npStatus, nodeType, netParams] = await this.ezsp.ezspGetNetworkParameters();
|
|
649
|
+
logger_1.logger.debug(() => `[INIT TC] Current adapter network: nodeType=${enums_1.EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`, NS);
|
|
650
|
+
if (npStatus === enums_1.SLStatus.OK &&
|
|
651
|
+
nodeType === enums_1.EmberNodeType.COORDINATOR &&
|
|
652
|
+
this.networkOptions.panID === netParams.panId &&
|
|
653
|
+
(0, es6_1.default)(this.networkOptions.extendedPanID, netParams.extendedPanId)) {
|
|
654
|
+
// config matches adapter so far, no error, we can check the network key
|
|
655
|
+
const context = (0, initters_1.initSecurityManagerContext)();
|
|
656
|
+
context.coreKeyType = enums_1.SecManKeyType.NETWORK;
|
|
657
|
+
context.keyIndex = 0;
|
|
658
|
+
const [nkStatus, networkKey] = await this.ezsp.ezspExportKey(context);
|
|
659
|
+
if (nkStatus !== enums_1.SLStatus.OK) {
|
|
660
|
+
throw new Error(`[INIT TC] Failed to export Network Key with status=${enums_1.SLStatus[nkStatus]}.`);
|
|
661
|
+
}
|
|
662
|
+
// config doesn't match adapter anymore
|
|
663
|
+
if (!networkKey.contents.equals(configNetworkKey)) {
|
|
664
|
+
action = NetworkInitAction.LEAVE;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
// config doesn't match adapter
|
|
669
|
+
action = NetworkInitAction.LEAVE;
|
|
670
|
+
}
|
|
671
|
+
if (action === NetworkInitAction.LEAVE) {
|
|
672
|
+
logger_1.logger.info("[INIT TC] Adapter network does not match config. Leaving network...", NS);
|
|
673
|
+
const leaveStatus = await this.ezsp.ezspLeaveNetwork();
|
|
674
|
+
if (leaveStatus !== enums_1.SLStatus.OK) {
|
|
675
|
+
throw new Error(`[INIT TC] Failed leave network request with status=${enums_1.SLStatus[leaveStatus]}.`);
|
|
676
|
+
}
|
|
677
|
+
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_DOWN }, DEFAULT_NETWORK_REQUEST_TIMEOUT, "[INIT TC] Leave network");
|
|
678
|
+
await (0, utils_1.wait)(200); // settle down
|
|
679
|
+
action = NetworkInitAction.LEFT;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
const backup = this.getStoredBackup();
|
|
683
|
+
if (initStatus === enums_1.SLStatus.NOT_JOINED || action === NetworkInitAction.LEFT) {
|
|
684
|
+
// no network
|
|
685
|
+
if (backup !== undefined) {
|
|
686
|
+
if (this.networkOptions.panID === backup.networkOptions.panId &&
|
|
687
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
688
|
+
Buffer.from(this.networkOptions.extendedPanID).equals(backup.networkOptions.extendedPanId) &&
|
|
689
|
+
this.networkOptions.channelList.includes(backup.logicalChannel) &&
|
|
690
|
+
configNetworkKey.equals(backup.networkOptions.networkKey)) {
|
|
691
|
+
// config matches backup
|
|
692
|
+
action = NetworkInitAction.FORM_BACKUP;
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
// config doesn't match backup
|
|
696
|
+
logger_1.logger.info("[INIT TC] Config does not match backup.", NS);
|
|
697
|
+
action = NetworkInitAction.FORM_CONFIG;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
// no backup
|
|
702
|
+
logger_1.logger.info("[INIT TC] No valid backup found.", NS);
|
|
703
|
+
action = NetworkInitAction.FORM_CONFIG;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
//---- from here on, we assume everything is in place for whatever decision was taken above
|
|
707
|
+
let result = "resumed";
|
|
708
|
+
switch (action) {
|
|
709
|
+
case NetworkInitAction.FORM_BACKUP: {
|
|
710
|
+
logger_1.logger.info("[INIT TC] Forming from backup.", NS);
|
|
711
|
+
// `backup` valid in this `action` path (not detected by TS)
|
|
712
|
+
/* v8 ignore start */
|
|
713
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
714
|
+
const keyList = backup.devices.map((device) => ({
|
|
715
|
+
deviceEui64: ZSpec.Utils.eui64BEBufferToHex(device.ieeeAddress),
|
|
716
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
717
|
+
key: { contents: device.linkKey.key },
|
|
718
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
719
|
+
outgoingFrameCounter: device.linkKey.txCounter,
|
|
720
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
721
|
+
incomingFrameCounter: device.linkKey.rxCounter,
|
|
722
|
+
}));
|
|
723
|
+
/* v8 ignore stop */
|
|
724
|
+
// before forming
|
|
725
|
+
await this.importLinkKeys(keyList);
|
|
726
|
+
await this.formNetwork(true /*from backup*/,
|
|
727
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
728
|
+
backup.networkOptions.networkKey,
|
|
729
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
730
|
+
backup.networkKeyInfo.sequenceNumber,
|
|
731
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
732
|
+
backup.networkKeyInfo.frameCounter,
|
|
733
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
734
|
+
backup.networkOptions.panId,
|
|
735
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
736
|
+
Array.from(backup.networkOptions.extendedPanId),
|
|
737
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
738
|
+
backup.logicalChannel,
|
|
739
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
740
|
+
backup.ezsp.hashed_tclk, // valid from getStoredBackup
|
|
741
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
742
|
+
backup.networkUpdateId);
|
|
743
|
+
result = "restored";
|
|
744
|
+
break;
|
|
745
|
+
}
|
|
746
|
+
case NetworkInitAction.FORM_CONFIG: {
|
|
747
|
+
logger_1.logger.info("[INIT TC] Forming from config.", NS);
|
|
748
|
+
await this.formNetwork(false /*from config*/, configNetworkKey, 0, 0, this.networkOptions.panID,
|
|
749
|
+
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
750
|
+
this.networkOptions.extendedPanID, this.networkOptions.channelList[0], (0, node_crypto_1.randomBytes)(consts_2.EMBER_ENCRYPTION_KEY_SIZE), // rnd TC link key
|
|
751
|
+
0);
|
|
752
|
+
result = "reset";
|
|
753
|
+
break;
|
|
754
|
+
}
|
|
755
|
+
case NetworkInitAction.DONE: {
|
|
756
|
+
logger_1.logger.info("[INIT TC] Adapter network matches config.", NS);
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
// can't let frame counter wrap to zero (uint32_t), will force a broadcast after init if getting too close
|
|
761
|
+
if (backup != null && backup.networkKeyInfo.frameCounter > 0xfeeeeeee) {
|
|
762
|
+
// XXX: while this remains a pretty low occurrence in most (small) networks,
|
|
763
|
+
// currently Z2M won't support the key update because of one-way config...
|
|
764
|
+
// need to investigate handling this properly
|
|
765
|
+
// logger.warning(`[INIT TC] Network key frame counter is reaching its limit. Scheduling broadcast to update network key. `
|
|
766
|
+
// + `This may result in some devices (especially battery-powered) temporarily losing connection.`, NS);
|
|
767
|
+
// // XXX: no idea here on the proper timer value, but this will block the network for several seconds on exec
|
|
768
|
+
// // (probably have to take the behavior of sleepy-end devices into account to improve chances of reaching everyone right away?)
|
|
769
|
+
// setTimeout(async () => {
|
|
770
|
+
// this.requestQueue.enqueue(async (): Promise<SLStatus> => {
|
|
771
|
+
// await this.broadcastNetworkKeyUpdate();
|
|
772
|
+
// return SLStatus.OK;
|
|
773
|
+
// }, logger.error, true);// no reject just log error if any, will retry next start, & prioritize so we know it'll run when expected
|
|
774
|
+
// }, 300000);
|
|
775
|
+
logger_1.logger.warning("[INIT TC] Network key frame counter is reaching its limit. A new network key will have to be instaured soon.", NS);
|
|
776
|
+
}
|
|
777
|
+
return result;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Form a network using given parameters.
|
|
781
|
+
*/
|
|
782
|
+
async formNetwork(fromBackup, networkKey, networkKeySequenceNumber, networkKeyFrameCounter, panId, extendedPanId, radioChannel, tcLinkKey, nwkUpdateId) {
|
|
783
|
+
const state = {
|
|
784
|
+
bitmask: enums_1.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY |
|
|
785
|
+
enums_1.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY |
|
|
786
|
+
enums_1.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY |
|
|
787
|
+
enums_1.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY |
|
|
788
|
+
enums_1.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY,
|
|
789
|
+
preconfiguredKey: { contents: tcLinkKey },
|
|
790
|
+
networkKey: { contents: networkKey },
|
|
791
|
+
networkKeySequenceNumber: networkKeySequenceNumber,
|
|
792
|
+
preconfiguredTrustCenterEui64: ZSpec.BLANK_EUI64,
|
|
793
|
+
};
|
|
794
|
+
if (fromBackup) {
|
|
795
|
+
state.bitmask |= enums_1.EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET;
|
|
796
|
+
const status = await this.ezsp.ezspSetNWKFrameCounter(networkKeyFrameCounter);
|
|
797
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
798
|
+
throw new Error(`[INIT FORM] Failed to set NWK frame counter with status=${enums_1.SLStatus[status]}.`);
|
|
799
|
+
}
|
|
800
|
+
// status = await this.ezsp.ezspSetAPSFrameCounter(tcLinkKeyFrameCounter);
|
|
801
|
+
// if (status !== SLStatus.OK) {
|
|
802
|
+
// throw new Error(`[INIT FORM] Failed to set TC APS frame counter with status=${SLStatus[status]}.`);
|
|
803
|
+
// }
|
|
804
|
+
}
|
|
805
|
+
let status = await this.ezsp.ezspSetInitialSecurityState(state);
|
|
806
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
807
|
+
throw new Error(`[INIT FORM] Failed to set initial security state with status=${enums_1.SLStatus[status]}.`);
|
|
808
|
+
}
|
|
809
|
+
const extended = enums_1.EmberExtendedSecurityBitmask.JOINER_GLOBAL_LINK_KEY | enums_1.EmberExtendedSecurityBitmask.NWK_LEAVE_REQUEST_NOT_ALLOWED;
|
|
810
|
+
status = await this.ezsp.ezspSetExtendedSecurityBitmask(extended);
|
|
811
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
812
|
+
throw new Error(`[INIT FORM] Failed to set extended security bitmask to ${extended} with status=${enums_1.SLStatus[status]}.`);
|
|
813
|
+
}
|
|
814
|
+
if (!fromBackup) {
|
|
815
|
+
status = await this.ezsp.ezspClearKeyTable();
|
|
816
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
817
|
+
logger_1.logger.error(`[INIT FORM] Failed to clear key table with status=${enums_1.SLStatus[status]}.`, NS);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
const netParams = {
|
|
821
|
+
panId,
|
|
822
|
+
extendedPanId,
|
|
823
|
+
radioTxPower: this.adapterOptions.transmitPower || 5,
|
|
824
|
+
radioChannel,
|
|
825
|
+
joinMethod: enums_1.EmberJoinMethod.MAC_ASSOCIATION,
|
|
826
|
+
nwkManagerId: ZSpec.COORDINATOR_ADDRESS,
|
|
827
|
+
nwkUpdateId,
|
|
828
|
+
channels: ZSpec.ALL_802_15_4_CHANNELS_MASK,
|
|
829
|
+
};
|
|
830
|
+
logger_1.logger.info(() => `[INIT FORM] Forming new network with: ${JSON.stringify(netParams)}`, NS);
|
|
831
|
+
status = await this.ezsp.ezspFormNetwork(netParams);
|
|
832
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
833
|
+
throw new Error(`[INIT FORM] Failed form network request with status=${enums_1.SLStatus[status]}.`);
|
|
834
|
+
}
|
|
835
|
+
await this.oneWaitress.startWaitingForEvent({ eventName: oneWaitress_1.OneWaitressEvents.STACK_STATUS_NETWORK_UP }, DEFAULT_NETWORK_REQUEST_TIMEOUT, "[INIT FORM] Form network");
|
|
836
|
+
status = await this.ezsp.ezspStartWritingStackTokens();
|
|
837
|
+
logger_1.logger.debug(`[INIT FORM] Start writing stack tokens status=${enums_1.SLStatus[status]}.`, NS);
|
|
838
|
+
logger_1.logger.info("[INIT FORM] New network formed!", NS);
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Loads currently stored backup and returns it in internal backup model.
|
|
842
|
+
*/
|
|
843
|
+
getStoredBackup() {
|
|
844
|
+
const data = (0, utils_2.readBackup)(this.backupPath);
|
|
845
|
+
if (!data)
|
|
846
|
+
return undefined;
|
|
847
|
+
if ("metadata" in data && data.metadata?.format === "zigpy/open-coordinator-backup" && data.metadata?.version) {
|
|
848
|
+
if (data.metadata?.version !== 1) {
|
|
849
|
+
throw new Error(`[BACKUP] Unsupported open coordinator backup version (version=${data.metadata?.version}).`);
|
|
850
|
+
}
|
|
851
|
+
if (!data.stack_specific?.ezsp || !data.metadata.internal.ezspVersion) {
|
|
852
|
+
throw new Error("[BACKUP] Current backup file is not for EmberZNet stack.");
|
|
853
|
+
}
|
|
854
|
+
if (data.metadata.internal.ezspVersion < BACKUP_OLDEST_SUPPORTED_EZSP_VERSION) {
|
|
855
|
+
(0, node_fs_1.renameSync)(this.backupPath, `${this.backupPath}.old`);
|
|
856
|
+
logger_1.logger.warning("[BACKUP] Current backup file is from an unsupported EZSP version. Renaming and ignoring.", NS);
|
|
857
|
+
return undefined;
|
|
858
|
+
}
|
|
859
|
+
return utils_1.BackupUtils.fromUnifiedBackup(data);
|
|
860
|
+
}
|
|
861
|
+
throw new Error("[BACKUP] Unknown backup format.");
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Export link keys for backup.
|
|
865
|
+
*
|
|
866
|
+
* @return List of keys data with AES hashed keys
|
|
867
|
+
*/
|
|
868
|
+
async exportLinkKeys() {
|
|
869
|
+
const [confStatus, keyTableSize] = await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.KEY_TABLE_SIZE);
|
|
870
|
+
if (confStatus !== enums_1.SLStatus.OK) {
|
|
871
|
+
throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_1.SLStatus[confStatus]}.`);
|
|
872
|
+
}
|
|
873
|
+
let context;
|
|
874
|
+
let plaintextKey;
|
|
875
|
+
let apsKeyMeta;
|
|
876
|
+
let status;
|
|
877
|
+
const keyList = [];
|
|
878
|
+
for (let i = 0; i < keyTableSize; i++) {
|
|
879
|
+
[status, context, plaintextKey, apsKeyMeta] = await this.ezsp.ezspExportLinkKeyByIndex(i);
|
|
880
|
+
logger_1.logger.debug(`[BACKUP] Export link key at index ${i}, status=${enums_1.SLStatus[status]}.`, NS);
|
|
881
|
+
// only include key if we could retrieve one at index and hash it properly
|
|
882
|
+
if (status === enums_1.SLStatus.OK) {
|
|
883
|
+
// Rather than give the real link key, the backup contains a hashed version of the key.
|
|
884
|
+
// This is done to prevent a compromise of the backup data from compromising the current link keys.
|
|
885
|
+
// This is per the Smart Energy spec.
|
|
886
|
+
const hashedKey = ZSpec.Utils.aes128MmoHash(plaintextKey.contents);
|
|
887
|
+
keyList.push({
|
|
888
|
+
deviceEui64: context.eui64,
|
|
889
|
+
key: { contents: hashedKey },
|
|
890
|
+
outgoingFrameCounter: apsKeyMeta.outgoingFrameCounter,
|
|
891
|
+
incomingFrameCounter: apsKeyMeta.incomingFrameCounter,
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
logger_1.logger.info(`[BACKUP] Retrieved ${keyList.length} link keys.`, NS);
|
|
896
|
+
return keyList;
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Import link keys from backup.
|
|
900
|
+
*
|
|
901
|
+
* @param backupData
|
|
902
|
+
*/
|
|
903
|
+
async importLinkKeys(backupData) {
|
|
904
|
+
if (!backupData?.length) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const [confStatus, keyTableSize] = await this.ezsp.ezspGetConfigurationValue(enums_2.EzspConfigId.KEY_TABLE_SIZE);
|
|
908
|
+
if (confStatus !== enums_1.SLStatus.OK) {
|
|
909
|
+
throw new Error(`[BACKUP] Failed to retrieve key table size from NCP with status=${enums_1.SLStatus[confStatus]}.`);
|
|
910
|
+
}
|
|
911
|
+
if (backupData.length > keyTableSize) {
|
|
912
|
+
throw new Error(`[BACKUP] Current key table of ${keyTableSize} is too small to import backup of ${backupData.length}!`);
|
|
913
|
+
}
|
|
914
|
+
const networkStatus = await this.ezsp.ezspNetworkState();
|
|
915
|
+
if (networkStatus !== enums_1.EmberNetworkStatus.NO_NETWORK) {
|
|
916
|
+
throw new Error(`[BACKUP] Cannot import TC data while network is up, networkStatus=${enums_1.EmberNetworkStatus[networkStatus]}.`);
|
|
917
|
+
}
|
|
918
|
+
let status;
|
|
919
|
+
for (let i = 0; i < keyTableSize; i++) {
|
|
920
|
+
// erase any key index not present in backup but available on the NCP
|
|
921
|
+
status =
|
|
922
|
+
i >= backupData.length
|
|
923
|
+
? await this.ezsp.ezspEraseKeyTableEntry(i)
|
|
924
|
+
: await this.ezsp.ezspImportLinkKey(i, backupData[i].deviceEui64, backupData[i].key);
|
|
925
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
926
|
+
throw new Error(`[BACKUP] Failed to ${i >= backupData.length ? "erase" : "set"} key table entry at index ${i} with status=${enums_1.SLStatus[status]}.`);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
logger_1.logger.info(`[BACKUP] Imported ${backupData.length} keys.`, NS);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Routine to update the network key and broadcast the update to the network after a set time.
|
|
933
|
+
* NOTE: This should run at a large interval, but before the uint32_t of the frame counter is able to reach all Fs (can't wrap to 0).
|
|
934
|
+
* This may disrupt sleepy end devices that miss the update, but they should be able to TC rejoin (in most cases...).
|
|
935
|
+
* On the other hand, the more often this runs, the more secure the network is...
|
|
936
|
+
*/
|
|
937
|
+
async broadcastNetworkKeyUpdate() {
|
|
938
|
+
return await this.queue.execute(async () => {
|
|
939
|
+
logger_1.logger.warning("[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.", NS);
|
|
940
|
+
// zero-filled = let stack generate new random network key
|
|
941
|
+
let status = await this.ezsp.ezspBroadcastNextNetworkKey({ contents: Buffer.alloc(consts_2.EMBER_ENCRYPTION_KEY_SIZE) });
|
|
942
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
943
|
+
throw new Error(`[TRUST CENTER] Failed to broadcast next network key with status=${enums_1.SLStatus[status]}.`);
|
|
944
|
+
}
|
|
945
|
+
// XXX: this will block other requests for a while, but should ensure the key propagates without interference?
|
|
946
|
+
// could also stop dispatching entirely and do this outside the queue if necessary/better
|
|
947
|
+
await (0, utils_1.wait)(BROADCAST_NETWORK_KEY_SWITCH_WAIT_TIME);
|
|
948
|
+
status = await this.ezsp.ezspBroadcastNetworkKeySwitch();
|
|
949
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
950
|
+
// XXX: Not sure how likely this is, but this is bad, probably should hard fail?
|
|
951
|
+
throw new Error(`[TRUST CENTER] Failed to broadcast network key switch with status=${enums_1.SLStatus[status]}.`);
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Received when EZSP layer alerts of a problem that needs the NCP to be reset.
|
|
957
|
+
* @param status
|
|
958
|
+
*/
|
|
959
|
+
onNcpNeedsResetAndInit(_status) {
|
|
960
|
+
this.emit("disconnected");
|
|
961
|
+
}
|
|
962
|
+
//---- START Events
|
|
963
|
+
//---- END Events
|
|
964
|
+
//---- START Cache-enabled EZSP wrappers
|
|
965
|
+
/**
|
|
966
|
+
* Clear the cached network values (set to invalid values).
|
|
967
|
+
*/
|
|
968
|
+
clearNetworkCache() {
|
|
969
|
+
this.networkCache = (0, initters_1.initNetworkCache)();
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Return the EUI 64 of the local node
|
|
973
|
+
* This call caches the results on the host to prevent frequent EZSP transactions.
|
|
974
|
+
* Check against BLANK_EUI64 for validity.
|
|
975
|
+
*/
|
|
976
|
+
async emberGetEui64() {
|
|
977
|
+
if (this.networkCache.eui64 === ZSpec.BLANK_EUI64) {
|
|
978
|
+
this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
|
|
979
|
+
}
|
|
980
|
+
return this.networkCache.eui64;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Return the PAN ID of the local node.
|
|
984
|
+
* This call caches the results on the host to prevent frequent EZSP transactions.
|
|
985
|
+
* Check against INVALID_PAN_ID for validity.
|
|
986
|
+
*/
|
|
987
|
+
async emberGetPanId() {
|
|
988
|
+
if (this.networkCache.parameters.panId === ZSpec.INVALID_PAN_ID) {
|
|
989
|
+
const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
|
|
990
|
+
if (status === enums_1.SLStatus.OK) {
|
|
991
|
+
this.networkCache.parameters = parameters;
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
throw new Error(`Failed to get PAN ID (via network parameters) with status=${enums_1.SLStatus[status]}.`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return this.networkCache.parameters.panId;
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Return the Extended PAN ID of the local node.
|
|
1001
|
+
* This call caches the results on the host to prevent frequent EZSP transactions.
|
|
1002
|
+
* Check against BLANK_EXTENDED_PAN_ID for validity.
|
|
1003
|
+
*/
|
|
1004
|
+
async emberGetExtendedPanId() {
|
|
1005
|
+
if ((0, es6_1.default)(this.networkCache.parameters.extendedPanId, ZSpec.BLANK_EXTENDED_PAN_ID)) {
|
|
1006
|
+
const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
|
|
1007
|
+
if (status === enums_1.SLStatus.OK) {
|
|
1008
|
+
this.networkCache.parameters = parameters;
|
|
1009
|
+
}
|
|
1010
|
+
else {
|
|
1011
|
+
throw new Error(`Failed to get Extended PAN ID (via network parameters) with status=${enums_1.SLStatus[status]}.`);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return this.networkCache.parameters.extendedPanId;
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Return the radio channel (uint8_t) of the current network.
|
|
1018
|
+
* This call caches the results on the host to prevent frequent EZSP transactions.
|
|
1019
|
+
* Check against INVALID_RADIO_CHANNEL for validity.
|
|
1020
|
+
*/
|
|
1021
|
+
async emberGetRadioChannel() {
|
|
1022
|
+
if (this.networkCache.parameters.radioChannel === consts_1.INVALID_RADIO_CHANNEL) {
|
|
1023
|
+
const [status, , parameters] = await this.ezsp.ezspGetNetworkParameters();
|
|
1024
|
+
if (status === enums_1.SLStatus.OK) {
|
|
1025
|
+
this.networkCache.parameters = parameters;
|
|
1026
|
+
}
|
|
1027
|
+
else {
|
|
1028
|
+
throw new Error(`Failed to get radio channel (via network parameters) with status=${enums_1.SLStatus[status]}.`);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
return this.networkCache.parameters.radioChannel;
|
|
1032
|
+
}
|
|
1033
|
+
//---- END Cache-enabled EZSP wrappers
|
|
1034
|
+
//---- START EZSP wrappers
|
|
1035
|
+
/**
|
|
1036
|
+
* Ensure the Host & NCP are aligned on protocols using version.
|
|
1037
|
+
* Cache the retrieved information.
|
|
1038
|
+
*
|
|
1039
|
+
* NOTE: currently throws on mismatch until support for lower versions is implemented (not planned atm)
|
|
1040
|
+
*
|
|
1041
|
+
* Does nothing if ncpNeedsResetAndInit == true.
|
|
1042
|
+
*/
|
|
1043
|
+
async emberVersion() {
|
|
1044
|
+
// send the Host version number to the NCP.
|
|
1045
|
+
// The NCP returns the EZSP version that the NCP is running along with the stackType and stackVersion
|
|
1046
|
+
let [ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(consts_2.EZSP_PROTOCOL_VERSION);
|
|
1047
|
+
// verify that the stack type is what is expected
|
|
1048
|
+
if (ncpStackType !== consts_2.EZSP_STACK_TYPE_MESH) {
|
|
1049
|
+
throw new Error(`Stack type ${ncpStackType} is not expected!`);
|
|
1050
|
+
}
|
|
1051
|
+
if (ncpEzspProtocolVer === consts_2.EZSP_PROTOCOL_VERSION) {
|
|
1052
|
+
logger_1.logger.debug(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) matches Host.`, NS);
|
|
1053
|
+
}
|
|
1054
|
+
else if (ncpEzspProtocolVer < consts_2.EZSP_PROTOCOL_VERSION && ncpEzspProtocolVer >= consts_2.EZSP_MIN_PROTOCOL_VERSION) {
|
|
1055
|
+
[ncpEzspProtocolVer, ncpStackType, ncpStackVer] = await this.ezsp.ezspVersion(ncpEzspProtocolVer);
|
|
1056
|
+
logger_1.logger.info(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) lower than Host. Switched.`, NS);
|
|
1057
|
+
}
|
|
1058
|
+
else {
|
|
1059
|
+
throw new Error(`Adapter EZSP protocol version (${ncpEzspProtocolVer}) is not supported by Host [${consts_2.EZSP_MIN_PROTOCOL_VERSION}-${consts_2.EZSP_PROTOCOL_VERSION}].`);
|
|
1060
|
+
}
|
|
1061
|
+
this.ezsp.setProtocolVersion(ncpEzspProtocolVer);
|
|
1062
|
+
logger_1.logger.debug(`Adapter info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`, NS);
|
|
1063
|
+
const [status, versionStruct] = await this.ezsp.ezspGetVersionStruct();
|
|
1064
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1065
|
+
// Should never happen with support of only EZSP v13+
|
|
1066
|
+
throw new Error("NCP has old-style version number. Not supported.");
|
|
1067
|
+
}
|
|
1068
|
+
this.version = {
|
|
1069
|
+
ezsp: ncpEzspProtocolVer,
|
|
1070
|
+
revision: `${versionStruct.major}.${versionStruct.minor}.${versionStruct.patch} [${enums_1.EmberVersionType[versionStruct.type]}]`,
|
|
1071
|
+
...versionStruct,
|
|
1072
|
+
};
|
|
1073
|
+
if (versionStruct.type !== enums_1.EmberVersionType.GA) {
|
|
1074
|
+
logger_1.logger.warning(`Adapter is running a non-GA version (${enums_1.EmberVersionType[versionStruct.type]}).`, NS);
|
|
1075
|
+
}
|
|
1076
|
+
logger_1.logger.info(() => `Adapter version info: ${JSON.stringify(this.version)}`, NS);
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* This function sets an EZSP config value.
|
|
1080
|
+
* WARNING: Do not call for values that cannot be set after init without first resetting NCP (like table sizes).
|
|
1081
|
+
* To avoid an extra NCP call, this does not check for it.
|
|
1082
|
+
* @param configId
|
|
1083
|
+
* @param value uint16_t
|
|
1084
|
+
* @returns
|
|
1085
|
+
*/
|
|
1086
|
+
async emberSetEzspConfigValue(configId, value) {
|
|
1087
|
+
const status = await this.ezsp.ezspSetConfigurationValue(configId, value);
|
|
1088
|
+
logger_1.logger.debug(`[EzspConfigId] SET '${enums_2.EzspConfigId[configId]}' TO '${value}' with status=${enums_1.SLStatus[status]}.`, NS);
|
|
1089
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1090
|
+
logger_1.logger.info(`[EzspConfigId] Failed to SET '${enums_2.EzspConfigId[configId]}' TO '${value}' with status=${enums_1.SLStatus[status]}. Firmware value will be used instead.`, NS);
|
|
1091
|
+
}
|
|
1092
|
+
return status;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* This function sets an EZSP value.
|
|
1096
|
+
* @param valueId
|
|
1097
|
+
* @param valueLength uint8_t
|
|
1098
|
+
* @param value uint8_t *
|
|
1099
|
+
* @returns
|
|
1100
|
+
*/
|
|
1101
|
+
async emberSetEzspValue(valueId, valueLength, value) {
|
|
1102
|
+
const status = await this.ezsp.ezspSetValue(valueId, valueLength, value);
|
|
1103
|
+
logger_1.logger.debug(`[EzspValueId] SET '${enums_2.EzspValueId[valueId]}' TO '${value}' with status=${enums_1.SLStatus[status]}.`, NS);
|
|
1104
|
+
return status;
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* This function sets an EZSP policy.
|
|
1108
|
+
* @param policyId
|
|
1109
|
+
* @param decisionId Can be bitop
|
|
1110
|
+
* @returns
|
|
1111
|
+
*/
|
|
1112
|
+
async emberSetEzspPolicy(policyId, decisionId) {
|
|
1113
|
+
const status = await this.ezsp.ezspSetPolicy(policyId, decisionId);
|
|
1114
|
+
logger_1.logger.debug(`[EzspPolicyId] SET '${enums_2.EzspPolicyId[policyId]}' TO '${decisionId}' with status=${enums_1.SLStatus[status]}.`, NS);
|
|
1115
|
+
return status;
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Set the trust center policy bitmask using decision.
|
|
1119
|
+
* @param decision
|
|
1120
|
+
* @returns
|
|
1121
|
+
*/
|
|
1122
|
+
async emberSetJoinPolicy(decision) {
|
|
1123
|
+
let policy = enums_2.EzspDecisionBitmask.DEFAULT_CONFIGURATION;
|
|
1124
|
+
switch (decision) {
|
|
1125
|
+
case enums_1.EmberJoinDecision.USE_PRECONFIGURED_KEY: {
|
|
1126
|
+
policy = enums_2.EzspDecisionBitmask.ALLOW_JOINS | enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
|
|
1127
|
+
break;
|
|
1128
|
+
}
|
|
1129
|
+
case enums_1.EmberJoinDecision.ALLOW_REJOINS_ONLY: {
|
|
1130
|
+
policy = enums_2.EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS;
|
|
1131
|
+
break;
|
|
1132
|
+
}
|
|
1133
|
+
/*case EmberJoinDecision.SEND_KEY_IN_THE_CLEAR: {
|
|
1134
|
+
policy = EzspDecisionBitmask.ALLOW_JOINS | EzspDecisionBitmask.ALLOW_UNSECURED_REJOINS | EzspDecisionBitmask.SEND_KEY_IN_CLEAR;
|
|
1135
|
+
break;
|
|
1136
|
+
}*/
|
|
1137
|
+
}
|
|
1138
|
+
return await this.emberSetEzspPolicy(enums_2.EzspPolicyId.TRUST_CENTER_POLICY, policy);
|
|
1139
|
+
}
|
|
1140
|
+
//---- END EZSP wrappers
|
|
1141
|
+
//---- START Ember ZDO
|
|
1142
|
+
/**
|
|
1143
|
+
* ZDO
|
|
1144
|
+
* Get the next device request sequence number.
|
|
1145
|
+
*
|
|
1146
|
+
* Requests have sequence numbers so that they can be matched up with the
|
|
1147
|
+
* responses. To avoid complexities, the library uses numbers with the high
|
|
1148
|
+
* bit clear and the stack uses numbers with the high bit set.
|
|
1149
|
+
*
|
|
1150
|
+
* @return uint8_t The next device request sequence number
|
|
1151
|
+
*/
|
|
1152
|
+
nextZDORequestSequence() {
|
|
1153
|
+
this.zdoRequestSequence = ++this.zdoRequestSequence & APPLICATION_ZDO_SEQUENCE_MASK;
|
|
1154
|
+
return this.zdoRequestSequence;
|
|
1155
|
+
}
|
|
1156
|
+
//---- END Ember ZDO
|
|
1157
|
+
//-- START Adapter implementation
|
|
1158
|
+
async start() {
|
|
1159
|
+
logger_1.logger.info("======== Ember Adapter Starting ========", NS);
|
|
1160
|
+
const result = await this.initEzsp();
|
|
1161
|
+
return result;
|
|
1162
|
+
}
|
|
1163
|
+
async stop() {
|
|
1164
|
+
clearInterval(this.watchdogCountersHandle);
|
|
1165
|
+
await this.ezsp.stop();
|
|
1166
|
+
this.ezsp.removeAllListeners();
|
|
1167
|
+
logger_1.logger.info("======== Ember Adapter Stopped ========", NS);
|
|
1168
|
+
}
|
|
1169
|
+
async getCoordinatorIEEE() {
|
|
1170
|
+
return await this.queue.execute(async () => {
|
|
1171
|
+
this.checkInterpanLock();
|
|
1172
|
+
// in all likelihood this will be retrieved from cache
|
|
1173
|
+
return await this.emberGetEui64();
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
async getCoordinatorVersion() {
|
|
1177
|
+
return await Promise.resolve({ type: "EmberZNet", meta: this.version });
|
|
1178
|
+
}
|
|
1179
|
+
// queued
|
|
1180
|
+
async reset(type) {
|
|
1181
|
+
// NOTE: although this function is legacy atm, a couple of new untested EZSP functions that could also prove useful:
|
|
1182
|
+
// this.ezsp.ezspTokenFactoryReset(true/*excludeOutgoingFC*/, true/*excludeBootCounter*/);
|
|
1183
|
+
// this.ezsp.ezspResetNode()
|
|
1184
|
+
/* v8 ignore next */ // weird coverage bug
|
|
1185
|
+
await Promise.reject(new Error(`Not supported '${type}'.`));
|
|
1186
|
+
}
|
|
1187
|
+
async supportsBackup() {
|
|
1188
|
+
return await Promise.resolve(true);
|
|
1189
|
+
}
|
|
1190
|
+
// queued
|
|
1191
|
+
async backup(_ieeeAddressesInDatabase) {
|
|
1192
|
+
return await this.queue.execute(async () => {
|
|
1193
|
+
// grab fresh version here, bypass cache
|
|
1194
|
+
const [netStatus, , netParams] = await this.ezsp.ezspGetNetworkParameters();
|
|
1195
|
+
if (netStatus !== enums_1.SLStatus.OK) {
|
|
1196
|
+
throw new Error(`[BACKUP] Failed to get network parameters with status=${enums_1.SLStatus[netStatus]}.`);
|
|
1197
|
+
}
|
|
1198
|
+
// update cache
|
|
1199
|
+
this.networkCache.parameters = netParams;
|
|
1200
|
+
this.networkCache.eui64 = await this.ezsp.ezspGetEui64();
|
|
1201
|
+
const [netKeyStatus, netKeyInfo] = await this.ezsp.ezspGetNetworkKeyInfo();
|
|
1202
|
+
if (netKeyStatus !== enums_1.SLStatus.OK) {
|
|
1203
|
+
throw new Error(`[BACKUP] Failed to get network keys info with status=${enums_1.SLStatus[netKeyStatus]}.`);
|
|
1204
|
+
}
|
|
1205
|
+
if (!netKeyInfo.networkKeySet) {
|
|
1206
|
+
throw new Error("[BACKUP] No network key set.");
|
|
1207
|
+
}
|
|
1208
|
+
/* v8 ignore next */
|
|
1209
|
+
const keyList = ALLOW_APP_KEY_REQUESTS ? await this.exportLinkKeys() : [];
|
|
1210
|
+
let context = (0, initters_1.initSecurityManagerContext)();
|
|
1211
|
+
context.coreKeyType = enums_1.SecManKeyType.TC_LINK;
|
|
1212
|
+
const [tclkStatus, tcLinkKey] = await this.ezsp.ezspExportKey(context);
|
|
1213
|
+
if (tclkStatus !== enums_1.SLStatus.OK) {
|
|
1214
|
+
throw new Error(`[BACKUP] Failed to export TC Link Key with status=${enums_1.SLStatus[tclkStatus]}.`);
|
|
1215
|
+
}
|
|
1216
|
+
// const [tcKeyStatus, tcKeyInfo] = await this.ezsp.ezspGetApsKeyInfo(context);
|
|
1217
|
+
// if (tcKeyStatus !== SLStatus.OK) {
|
|
1218
|
+
// throw new Error(`[BACKUP] Failed to get TC APS key info with status=${SLStatus[tcKeyStatus]}.`);
|
|
1219
|
+
// }
|
|
1220
|
+
context = (0, initters_1.initSecurityManagerContext)(); // make sure it's back to zeroes
|
|
1221
|
+
context.coreKeyType = enums_1.SecManKeyType.NETWORK;
|
|
1222
|
+
context.keyIndex = 0;
|
|
1223
|
+
const [nkStatus, networkKey] = await this.ezsp.ezspExportKey(context);
|
|
1224
|
+
if (nkStatus !== enums_1.SLStatus.OK) {
|
|
1225
|
+
throw new Error(`[BACKUP] Failed to export Network Key with status=${enums_1.SLStatus[nkStatus]}.`);
|
|
1226
|
+
}
|
|
1227
|
+
return {
|
|
1228
|
+
networkOptions: {
|
|
1229
|
+
panId: netParams.panId, // uint16_t
|
|
1230
|
+
extendedPanId: Buffer.from(netParams.extendedPanId),
|
|
1231
|
+
channelList: ZSpec.Utils.uint32MaskToChannels(netParams.channels),
|
|
1232
|
+
networkKey: networkKey.contents,
|
|
1233
|
+
networkKeyDistribute: false,
|
|
1234
|
+
},
|
|
1235
|
+
logicalChannel: netParams.radioChannel,
|
|
1236
|
+
networkKeyInfo: {
|
|
1237
|
+
sequenceNumber: netKeyInfo.networkKeySequenceNumber,
|
|
1238
|
+
frameCounter: netKeyInfo.networkKeyFrameCounter,
|
|
1239
|
+
},
|
|
1240
|
+
// tcLinkKeyInfo: {
|
|
1241
|
+
// incomingFrameCounter: tcKeyInfo.bitmask & EmberKeyStructBitmask.HAS_INCOMING_FRAME_COUNTER ? tcKeyInfo.incomingFrameCounter : 0,
|
|
1242
|
+
// outgoingFrameCounter: tcKeyInfo.bitmask & EmberKeyStructBitmask.HAS_OUTGOING_FRAME_COUNTER ? tcKeyInfo.outgoingFrameCounter : 0,
|
|
1243
|
+
// },
|
|
1244
|
+
securityLevel: consts_1.SECURITY_LEVEL_Z3,
|
|
1245
|
+
networkUpdateId: netParams.nwkUpdateId,
|
|
1246
|
+
coordinatorIeeeAddress: Buffer.from(this.networkCache.eui64.substring(2) /*take out 0x*/, "hex").reverse(),
|
|
1247
|
+
devices: keyList.map(
|
|
1248
|
+
/* v8 ignore start */
|
|
1249
|
+
(key) => ({
|
|
1250
|
+
networkAddress: null, // not used for restore, no reason to make NCP calls for nothing
|
|
1251
|
+
ieeeAddress: Buffer.from(key.deviceEui64.substring(2) /*take out 0x*/, "hex").reverse(),
|
|
1252
|
+
isDirectChild: false, // not used
|
|
1253
|
+
linkKey: {
|
|
1254
|
+
key: key.key.contents,
|
|
1255
|
+
rxCounter: key.incomingFrameCounter,
|
|
1256
|
+
txCounter: key.outgoingFrameCounter,
|
|
1257
|
+
},
|
|
1258
|
+
})),
|
|
1259
|
+
ezsp: {
|
|
1260
|
+
version: this.version.ezsp,
|
|
1261
|
+
hashed_tclk: tcLinkKey.contents,
|
|
1262
|
+
// tokens: tokensBuf.toString('hex'),
|
|
1263
|
+
// altNetworkKey: altNetworkKey.contents,
|
|
1264
|
+
},
|
|
1265
|
+
};
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
// queued, non-InterPAN
|
|
1269
|
+
async getNetworkParameters() {
|
|
1270
|
+
return await this.queue.execute(async () => {
|
|
1271
|
+
this.checkInterpanLock();
|
|
1272
|
+
// first call will cache for the others, but in all likelihood, it will all be from freshly cached after init
|
|
1273
|
+
// since Controller caches this also.
|
|
1274
|
+
const channel = await this.emberGetRadioChannel();
|
|
1275
|
+
const panID = await this.emberGetPanId();
|
|
1276
|
+
const extendedPanID = await this.emberGetExtendedPanId();
|
|
1277
|
+
return {
|
|
1278
|
+
panID,
|
|
1279
|
+
extendedPanID: ZSpec.Utils.eui64LEBufferToHex(Buffer.from(extendedPanID)),
|
|
1280
|
+
channel,
|
|
1281
|
+
nwkUpdateID: this.networkCache.parameters.nwkUpdateId,
|
|
1282
|
+
};
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
// queued
|
|
1286
|
+
async addInstallCode(ieeeAddress, key, hashed) {
|
|
1287
|
+
return await this.queue.execute(async () => {
|
|
1288
|
+
// Add the key to the transient key table.
|
|
1289
|
+
// This will be used while the DUT joins.
|
|
1290
|
+
const impStatus = await this.ezsp.ezspImportTransientKey(ieeeAddress, { contents: hashed ? key : ZSpec.Utils.aes128MmoHash(key) });
|
|
1291
|
+
if (impStatus === enums_1.SLStatus.OK) {
|
|
1292
|
+
logger_1.logger.debug(`[ADD INSTALL CODE] Success for '${ieeeAddress}'.`, NS);
|
|
1293
|
+
}
|
|
1294
|
+
else {
|
|
1295
|
+
throw new Error(`[ADD INSTALL CODE] Failed for '${ieeeAddress}' with status=${enums_1.SLStatus[impStatus]}.`);
|
|
1296
|
+
}
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
/** WARNING: Adapter impl. Starts timer immediately upon returning */
|
|
1300
|
+
waitFor(networkAddress, endpoint, _frameType, _direction, transactionSequenceNumber, clusterID, commandIdentifier, timeout) {
|
|
1301
|
+
const sourceEndpointInfo = endpoints_1.FIXED_ENDPOINTS[0];
|
|
1302
|
+
const waiter = this.oneWaitress.waitFor({
|
|
1303
|
+
target: networkAddress,
|
|
1304
|
+
apsFrame: {
|
|
1305
|
+
clusterId: clusterID,
|
|
1306
|
+
profileId: sourceEndpointInfo.profileId, // XXX: only used by OTA upstream
|
|
1307
|
+
sequence: 0, // set by stack
|
|
1308
|
+
sourceEndpoint: sourceEndpointInfo.endpoint,
|
|
1309
|
+
destinationEndpoint: endpoint,
|
|
1310
|
+
groupId: 0,
|
|
1311
|
+
options: enums_1.EmberApsOption.NONE,
|
|
1312
|
+
},
|
|
1313
|
+
zclSequence: transactionSequenceNumber,
|
|
1314
|
+
commandIdentifier,
|
|
1315
|
+
}, timeout);
|
|
1316
|
+
return {
|
|
1317
|
+
cancel: () => this.oneWaitress.remove(waiter.id),
|
|
1318
|
+
promise: waiter.start().promise,
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
async sendZdo(ieeeAddress, networkAddress, clusterId, payload, disableResponse) {
|
|
1322
|
+
return await this.queue.execute(async () => {
|
|
1323
|
+
this.checkInterpanLock();
|
|
1324
|
+
const clusterName = Zdo.ClusterId[clusterId];
|
|
1325
|
+
const messageTag = this.nextZDORequestSequence();
|
|
1326
|
+
payload[0] = messageTag;
|
|
1327
|
+
const apsFrame = {
|
|
1328
|
+
profileId: Zdo.ZDO_PROFILE_ID,
|
|
1329
|
+
clusterId,
|
|
1330
|
+
sourceEndpoint: Zdo.ZDO_ENDPOINT,
|
|
1331
|
+
destinationEndpoint: Zdo.ZDO_ENDPOINT,
|
|
1332
|
+
options: exports.DEFAULT_APS_OPTIONS,
|
|
1333
|
+
groupId: 0,
|
|
1334
|
+
sequence: 0, // set by stack
|
|
1335
|
+
};
|
|
1336
|
+
let status;
|
|
1337
|
+
let apsSequence;
|
|
1338
|
+
if (ZSpec.Utils.isBroadcastAddress(networkAddress)) {
|
|
1339
|
+
logger_1.logger.debug(() => `~~~> [ZDO ${clusterName} BROADCAST to=${networkAddress} messageTag=${messageTag} payload=${payload.toString("hex")}]`, NS);
|
|
1340
|
+
[status, apsSequence] = await this.ezsp.ezspSendBroadcast(ZSpec.NULL_NODE_ID, // alias
|
|
1341
|
+
networkAddress, 0, // nwkSequence
|
|
1342
|
+
apsFrame, ZDO_REQUEST_RADIUS, messageTag, payload);
|
|
1343
|
+
apsFrame.sequence = apsSequence;
|
|
1344
|
+
logger_1.logger.debug(`~~~> [SENT ZDO BROADCAST messageTag=${messageTag} apsSequence=${apsSequence} status=${enums_1.SLStatus[status]}]`, NS);
|
|
1345
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1346
|
+
throw new Error(`~x~> [ZDO ${clusterName} BROADCAST to=${networkAddress} messageTag=${messageTag}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
else {
|
|
1350
|
+
logger_1.logger.debug(() => `~~~> [ZDO ${clusterName} UNICAST to=${ieeeAddress}:${networkAddress} messageTag=${messageTag} payload=${payload.toString("hex")}]`, NS);
|
|
1351
|
+
[status, apsSequence] = await this.ezsp.ezspSendUnicast(enums_1.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame, messageTag, payload);
|
|
1352
|
+
apsFrame.sequence = apsSequence;
|
|
1353
|
+
logger_1.logger.debug(`~~~> [SENT ZDO UNICAST messageTag=${messageTag} apsSequence=${apsSequence} status=${enums_1.SLStatus[status]}]`, NS);
|
|
1354
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1355
|
+
throw new Error(`~x~> [ZDO ${clusterName} UNICAST to=${ieeeAddress}:${networkAddress} messageTag=${messageTag}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
if (!disableResponse) {
|
|
1359
|
+
const responseClusterId = Zdo.Utils.getResponseClusterId(clusterId);
|
|
1360
|
+
if (responseClusterId) {
|
|
1361
|
+
return await this.oneWaitress.startWaitingFor({
|
|
1362
|
+
target: responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE ? ieeeAddress : networkAddress,
|
|
1363
|
+
apsFrame,
|
|
1364
|
+
zdoResponseClusterId: responseClusterId,
|
|
1365
|
+
}, DEFAULT_REQUEST_TIMEOUT);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}, networkAddress);
|
|
1369
|
+
}
|
|
1370
|
+
// queued, non-InterPAN
|
|
1371
|
+
async permitJoin(seconds, networkAddress) {
|
|
1372
|
+
const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
|
|
1373
|
+
const preJoining = async () => {
|
|
1374
|
+
if (seconds) {
|
|
1375
|
+
const plaintextKey = { contents: Buffer.from(consts_1.ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY) };
|
|
1376
|
+
const impKeyStatus = await this.ezsp.ezspImportTransientKey(ZSpec.BLANK_EUI64, plaintextKey);
|
|
1377
|
+
if (impKeyStatus !== enums_1.SLStatus.OK) {
|
|
1378
|
+
throw new Error(`[ZDO] Failed import transient key with status=${enums_1.SLStatus[impKeyStatus]}.`);
|
|
1379
|
+
}
|
|
1380
|
+
const setJPstatus = await this.emberSetJoinPolicy(enums_1.EmberJoinDecision.USE_PRECONFIGURED_KEY);
|
|
1381
|
+
if (setJPstatus !== enums_1.SLStatus.OK) {
|
|
1382
|
+
throw new Error(`[ZDO] Failed set join policy with status=${enums_1.SLStatus[setJPstatus]}.`);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
else {
|
|
1386
|
+
await this.ezsp.ezspClearTransientLinkKeys();
|
|
1387
|
+
const setJPstatus = await this.emberSetJoinPolicy(enums_1.EmberJoinDecision.ALLOW_REJOINS_ONLY);
|
|
1388
|
+
if (setJPstatus !== enums_1.SLStatus.OK) {
|
|
1389
|
+
throw new Error(`[ZDO] Failed set join policy with status=${enums_1.SLStatus[setJPstatus]}.`);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
if (networkAddress) {
|
|
1394
|
+
// specific device that is not `Coordinator`
|
|
1395
|
+
await this.queue.execute(async () => {
|
|
1396
|
+
this.checkInterpanLock();
|
|
1397
|
+
await preJoining();
|
|
1398
|
+
});
|
|
1399
|
+
// `authentication`: TC significance always 1 (zb specs)
|
|
1400
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
|
|
1401
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
1402
|
+
/* v8 ignore start */
|
|
1403
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
1404
|
+
// TODO: will disappear once moved upstream
|
|
1405
|
+
throw new Zdo.StatusError(result[0]);
|
|
1406
|
+
}
|
|
1407
|
+
/* v8 ignore stop */
|
|
1408
|
+
}
|
|
1409
|
+
else {
|
|
1410
|
+
// coordinator-only (0), or all
|
|
1411
|
+
await this.queue.execute(async () => {
|
|
1412
|
+
this.checkInterpanLock();
|
|
1413
|
+
await preJoining();
|
|
1414
|
+
});
|
|
1415
|
+
const status = await this.ezsp.ezspPermitJoining(seconds);
|
|
1416
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1417
|
+
throw new Error(`[ZDO] Failed coordinator permit joining request with status=${enums_1.SLStatus[status]}.`);
|
|
1418
|
+
}
|
|
1419
|
+
logger_1.logger.debug(`Permit joining on coordinator for ${seconds} sec.`, NS);
|
|
1420
|
+
// broadcast permit joining ZDO
|
|
1421
|
+
if (networkAddress === undefined) {
|
|
1422
|
+
// `authentication`: TC significance always 1 (zb specs)
|
|
1423
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
|
|
1424
|
+
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
//---- ZCL
|
|
1429
|
+
// queued, non-InterPAN
|
|
1430
|
+
async sendZclFrameToEndpoint(ieeeAddr, networkAddress, endpoint, zclFrame, timeout, disableResponse, disableRecovery, sourceEndpoint, profileId) {
|
|
1431
|
+
const command = zclFrame.command;
|
|
1432
|
+
let commandResponseId;
|
|
1433
|
+
if (command.response !== undefined && disableResponse === false) {
|
|
1434
|
+
commandResponseId = command.response;
|
|
1435
|
+
}
|
|
1436
|
+
else if (!zclFrame.header.frameControl.disableDefaultResponse) {
|
|
1437
|
+
commandResponseId = Zcl.Foundation.defaultRsp.ID;
|
|
1438
|
+
}
|
|
1439
|
+
const apsFrame = {
|
|
1440
|
+
profileId: profileId ?? ((sourceEndpoint && endpoints_1.FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint)) || endpoints_1.FIXED_ENDPOINTS[0]).profileId,
|
|
1441
|
+
clusterId: zclFrame.cluster.ID,
|
|
1442
|
+
sourceEndpoint: sourceEndpoint || endpoints_1.FIXED_ENDPOINTS[0].endpoint,
|
|
1443
|
+
destinationEndpoint: endpoint,
|
|
1444
|
+
options: exports.DEFAULT_APS_OPTIONS,
|
|
1445
|
+
groupId: 0,
|
|
1446
|
+
sequence: 0, // set by stack
|
|
1447
|
+
};
|
|
1448
|
+
// don't RETRY if no response expected
|
|
1449
|
+
if (commandResponseId === undefined) {
|
|
1450
|
+
apsFrame.options &= ~enums_1.EmberApsOption.RETRY;
|
|
1451
|
+
}
|
|
1452
|
+
const data = zclFrame.toBuffer();
|
|
1453
|
+
return await this.queue.execute(async () => {
|
|
1454
|
+
this.checkInterpanLock();
|
|
1455
|
+
logger_1.logger.debug(() => `~~~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
1456
|
+
for (let i = 1; i <= QUEUE_MAX_SEND_ATTEMPTS; i++) {
|
|
1457
|
+
let status = enums_1.SLStatus.FAIL;
|
|
1458
|
+
try {
|
|
1459
|
+
[status] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.DIRECT, networkAddress, apsFrame, data, 0, // alias
|
|
1460
|
+
0);
|
|
1461
|
+
}
|
|
1462
|
+
catch (error) {
|
|
1463
|
+
if (error instanceof ezspError_1.EzspError) {
|
|
1464
|
+
switch (error.code) {
|
|
1465
|
+
case enums_1.EzspStatus.NO_TX_SPACE: {
|
|
1466
|
+
status = enums_1.SLStatus.BUSY;
|
|
1467
|
+
break;
|
|
1468
|
+
}
|
|
1469
|
+
case enums_1.EzspStatus.NOT_CONNECTED: {
|
|
1470
|
+
status = enums_1.SLStatus.NETWORK_DOWN;
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
// `else if` order matters
|
|
1477
|
+
if (status === enums_1.SLStatus.OK) {
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
if (disableRecovery || i === QUEUE_MAX_SEND_ATTEMPTS) {
|
|
1481
|
+
throw new Error(`~x~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
|
|
1482
|
+
}
|
|
1483
|
+
if (status === enums_1.SLStatus.ZIGBEE_MAX_MESSAGE_LIMIT_REACHED || status === enums_1.SLStatus.BUSY) {
|
|
1484
|
+
await (0, utils_1.wait)(QUEUE_BUSY_DEFER_MSEC);
|
|
1485
|
+
}
|
|
1486
|
+
else if (status === enums_1.SLStatus.NETWORK_DOWN) {
|
|
1487
|
+
await (0, utils_1.wait)(QUEUE_NETWORK_DOWN_DEFER_MSEC);
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
throw new Error(`~x~> [ZCL to=${ieeeAddr}:${networkAddress} apsFrame=${JSON.stringify(apsFrame)}] Failed to send request with status=${enums_1.SLStatus[status]}.`);
|
|
1491
|
+
}
|
|
1492
|
+
logger_1.logger.debug(`~x~> [ZCL to=${ieeeAddr}:${networkAddress}] Failed to send request attempt ${i}/${QUEUE_MAX_SEND_ATTEMPTS} with status=${enums_1.SLStatus[status]}.`, NS);
|
|
1493
|
+
}
|
|
1494
|
+
if (commandResponseId !== undefined) {
|
|
1495
|
+
// NOTE: aps sequence number will have been set by send function
|
|
1496
|
+
const result = await this.oneWaitress.startWaitingFor({
|
|
1497
|
+
target: networkAddress,
|
|
1498
|
+
apsFrame,
|
|
1499
|
+
zclSequence: zclFrame.header.transactionSequenceNumber,
|
|
1500
|
+
commandIdentifier: commandResponseId,
|
|
1501
|
+
}, timeout);
|
|
1502
|
+
return result;
|
|
1503
|
+
}
|
|
1504
|
+
}, networkAddress);
|
|
1505
|
+
}
|
|
1506
|
+
// queued, non-InterPAN
|
|
1507
|
+
async sendZclFrameToGroup(groupID, zclFrame, sourceEndpoint, profileId) {
|
|
1508
|
+
const apsFrame = {
|
|
1509
|
+
profileId: profileId ?? ((sourceEndpoint && endpoints_1.FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint)) || endpoints_1.FIXED_ENDPOINTS[0]).profileId,
|
|
1510
|
+
clusterId: zclFrame.cluster.ID,
|
|
1511
|
+
sourceEndpoint: sourceEndpoint || endpoints_1.FIXED_ENDPOINTS[0].endpoint,
|
|
1512
|
+
destinationEndpoint: 0xff,
|
|
1513
|
+
options: exports.DEFAULT_APS_OPTIONS,
|
|
1514
|
+
groupId: groupID,
|
|
1515
|
+
sequence: 0, // set by stack
|
|
1516
|
+
};
|
|
1517
|
+
const data = zclFrame.toBuffer();
|
|
1518
|
+
return await this.queue.execute(async () => {
|
|
1519
|
+
this.checkInterpanLock();
|
|
1520
|
+
logger_1.logger.debug(() => `~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
1521
|
+
const [status] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.MULTICAST, groupID, // not used with MULTICAST
|
|
1522
|
+
apsFrame, data, 0, // alias
|
|
1523
|
+
0);
|
|
1524
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1525
|
+
throw new Error(`~x~> [ZCL GROUP groupId=${groupID}] Failed to send with status=${enums_1.SLStatus[status]}.`);
|
|
1526
|
+
}
|
|
1527
|
+
// NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
|
|
1528
|
+
await (0, utils_1.wait)(QUEUE_BUSY_DEFER_MSEC);
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
// queued, non-InterPAN
|
|
1532
|
+
async sendZclFrameToAll(endpoint, zclFrame, sourceEndpoint, destination, profileId) {
|
|
1533
|
+
const apsFrame = {
|
|
1534
|
+
profileId: profileId ?? ((sourceEndpoint && endpoints_1.FIXED_ENDPOINTS.find((epi) => epi.endpoint === sourceEndpoint)) || endpoints_1.FIXED_ENDPOINTS[0]).profileId,
|
|
1535
|
+
clusterId: zclFrame.cluster.ID,
|
|
1536
|
+
sourceEndpoint,
|
|
1537
|
+
destinationEndpoint: endpoint,
|
|
1538
|
+
options: exports.DEFAULT_APS_OPTIONS,
|
|
1539
|
+
groupId: destination,
|
|
1540
|
+
sequence: 0, // set by stack
|
|
1541
|
+
};
|
|
1542
|
+
const data = zclFrame.toBuffer();
|
|
1543
|
+
return await this.queue.execute(async () => {
|
|
1544
|
+
this.checkInterpanLock();
|
|
1545
|
+
logger_1.logger.debug(() => `~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
1546
|
+
const [status] = await this.ezsp.send(enums_1.EmberOutgoingMessageType.BROADCAST, destination, apsFrame, data, 0, // alias
|
|
1547
|
+
0);
|
|
1548
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1549
|
+
throw new Error(`~x~> [ZCL BROADCAST destination=${destination}] Failed to send with status=${enums_1.SLStatus[status]}.`);
|
|
1550
|
+
}
|
|
1551
|
+
// NOTE: since ezspMessageSentHandler could take a while here, we don't block, it'll just be logged if the delivery failed
|
|
1552
|
+
await (0, utils_1.wait)(QUEUE_BUSY_DEFER_MSEC);
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
//---- InterPAN for Touchlink
|
|
1556
|
+
// XXX: There might be a better way to handle touchlink with ZLL ezsp functions, but I don't have any device to test so, didn't look into it...
|
|
1557
|
+
// TODO: check all this touchlink/interpan stuff
|
|
1558
|
+
// queued
|
|
1559
|
+
async setChannelInterPAN(channel) {
|
|
1560
|
+
return await this.queue.execute(async () => {
|
|
1561
|
+
this.interpanLock = true;
|
|
1562
|
+
const status = await this.ezsp.ezspSetLogicalAndRadioChannel(channel);
|
|
1563
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1564
|
+
this.interpanLock = false; // XXX: ok?
|
|
1565
|
+
throw new Error(`Failed to set InterPAN channel to '${channel}' with status=${enums_1.SLStatus[status]}.`);
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
// queued
|
|
1570
|
+
async sendZclFrameInterPANToIeeeAddr(zclFrame, ieeeAddress) {
|
|
1571
|
+
return await this.queue.execute(async () => {
|
|
1572
|
+
const msgBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_1.MAXIMUM_INTERPAN_LENGTH));
|
|
1573
|
+
// cache-enabled getters
|
|
1574
|
+
const sourcePanId = await this.emberGetPanId();
|
|
1575
|
+
const sourceEui64 = await this.emberGetEui64();
|
|
1576
|
+
msgBuffalo.writeUInt16(consts_1.LONG_DEST_FRAME_CONTROL | consts_1.MAC_ACK_REQUIRED); // macFrameControl
|
|
1577
|
+
msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
|
|
1578
|
+
msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
|
|
1579
|
+
msgBuffalo.writeIeeeAddr(ieeeAddress); // destAddress (longAddress)
|
|
1580
|
+
msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
|
|
1581
|
+
msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
|
|
1582
|
+
msgBuffalo.writeUInt16(consts_1.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
|
|
1583
|
+
msgBuffalo.writeUInt8(enums_1.EmberInterpanMessageType.UNICAST | consts_1.INTERPAN_APS_FRAME_TYPE); // apsFrameControl
|
|
1584
|
+
msgBuffalo.writeUInt16(zclFrame.cluster.ID);
|
|
1585
|
+
msgBuffalo.writeUInt16(ZSpec.TOUCHLINK_PROFILE_ID);
|
|
1586
|
+
logger_1.logger.debug(() => `~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
1587
|
+
const status = await this.ezsp.ezspSendRawMessage(Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]), enums_1.EmberTransmitPriority.NORMAL, true);
|
|
1588
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1589
|
+
throw new Error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${enums_1.SLStatus[status]}.`);
|
|
1590
|
+
}
|
|
1591
|
+
// NOTE: can use ezspRawTransmitCompleteHandler if needed here
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
async sendZclFrameInterPANBroadcast(zclFrame, timeout, disableResponse) {
|
|
1595
|
+
const command = zclFrame.command;
|
|
1596
|
+
if (!disableResponse && command.response === undefined) {
|
|
1597
|
+
throw new Error(`Command '${command.name}' has no response, cannot wait for response.`);
|
|
1598
|
+
}
|
|
1599
|
+
const endpoint = endpoints_1.FIXED_ENDPOINTS[0].endpoint;
|
|
1600
|
+
// just for waitress
|
|
1601
|
+
const apsFrame = {
|
|
1602
|
+
profileId: ZSpec.TOUCHLINK_PROFILE_ID,
|
|
1603
|
+
clusterId: zclFrame.cluster.ID,
|
|
1604
|
+
sourceEndpoint: endpoint, // arbitrary since not sent over-the-air
|
|
1605
|
+
destinationEndpoint: endpoint,
|
|
1606
|
+
options: enums_1.EmberApsOption.NONE,
|
|
1607
|
+
groupId: ZSpec.BroadcastAddress.SLEEPY,
|
|
1608
|
+
sequence: 0, // set by stack
|
|
1609
|
+
};
|
|
1610
|
+
return await this.queue.execute(async () => {
|
|
1611
|
+
const msgBuffalo = new buffalo_1.EzspBuffalo(Buffer.alloc(consts_1.MAXIMUM_INTERPAN_LENGTH));
|
|
1612
|
+
// cache-enabled getters
|
|
1613
|
+
const sourcePanId = await this.emberGetPanId();
|
|
1614
|
+
const sourceEui64 = await this.emberGetEui64();
|
|
1615
|
+
msgBuffalo.writeUInt16(consts_1.SHORT_DEST_FRAME_CONTROL); // macFrameControl
|
|
1616
|
+
msgBuffalo.writeUInt8(0); // sequence Skip Sequence number, stack sets the sequence number.
|
|
1617
|
+
msgBuffalo.writeUInt16(ZSpec.INVALID_PAN_ID); // destPanId
|
|
1618
|
+
msgBuffalo.writeUInt16(apsFrame.groupId); // destAddress (longAddress)
|
|
1619
|
+
msgBuffalo.writeUInt16(sourcePanId); // sourcePanId
|
|
1620
|
+
msgBuffalo.writeIeeeAddr(sourceEui64); // sourceAddress
|
|
1621
|
+
msgBuffalo.writeUInt16(consts_1.STUB_NWK_FRAME_CONTROL); // nwkFrameControl
|
|
1622
|
+
msgBuffalo.writeUInt8(enums_1.EmberInterpanMessageType.BROADCAST | consts_1.INTERPAN_APS_FRAME_TYPE); // apsFrameControl
|
|
1623
|
+
msgBuffalo.writeUInt16(apsFrame.clusterId);
|
|
1624
|
+
msgBuffalo.writeUInt16(apsFrame.profileId);
|
|
1625
|
+
const data = Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]);
|
|
1626
|
+
logger_1.logger.debug(() => `~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.header)}]`, NS);
|
|
1627
|
+
const status = await this.ezsp.ezspSendRawMessage(data, enums_1.EmberTransmitPriority.NORMAL, true);
|
|
1628
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1629
|
+
throw new Error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${enums_1.SLStatus[status]}.`);
|
|
1630
|
+
}
|
|
1631
|
+
// NOTE: can use ezspRawTransmitCompleteHandler if needed here
|
|
1632
|
+
if (!disableResponse && command.response !== undefined) {
|
|
1633
|
+
const result = await this.oneWaitress.startWaitingFor({
|
|
1634
|
+
target: undefined,
|
|
1635
|
+
apsFrame: apsFrame,
|
|
1636
|
+
zclSequence: zclFrame.header.transactionSequenceNumber,
|
|
1637
|
+
commandIdentifier: command.response,
|
|
1638
|
+
}, timeout);
|
|
1639
|
+
return result;
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
// queued
|
|
1644
|
+
async restoreChannelInterPAN() {
|
|
1645
|
+
return await this.queue.execute(async () => {
|
|
1646
|
+
const status = await this.ezsp.ezspSetLogicalAndRadioChannel(this.networkOptions.channelList[0]);
|
|
1647
|
+
if (status !== enums_1.SLStatus.OK) {
|
|
1648
|
+
throw new Error(`Failed to restore InterPAN channel to '${this.networkOptions.channelList[0]}' with status=${enums_1.SLStatus[status]}.`);
|
|
1649
|
+
}
|
|
1650
|
+
// let adapter settle down
|
|
1651
|
+
await (0, utils_1.wait)(QUEUE_NETWORK_DOWN_DEFER_MSEC);
|
|
1652
|
+
this.interpanLock = false;
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
//-- END Adapter implementation
|
|
1656
|
+
checkInterpanLock() {
|
|
1657
|
+
if (this.interpanLock) {
|
|
1658
|
+
throw new Error("[INTERPAN MODE] Cannot execute non-InterPAN commands.");
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
exports.EmberAdapter = EmberAdapter;
|
|
1663
|
+
//# sourceMappingURL=emberAdapter.js.map
|