zigbee-herdsman 6.0.2 → 6.0.4

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.
Files changed (252) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +9 -3
  3. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  4. package/.github/dependabot.yml +0 -22
  5. package/.github/workflows/ci.yml +0 -69
  6. package/.github/workflows/release-please.yml +0 -18
  7. package/.github/workflows/stale.yml +0 -20
  8. package/.github/workflows/typedoc.yaml +0 -47
  9. package/.release-please-manifest.json +0 -3
  10. package/.vscode/extensions.json +0 -3
  11. package/.vscode/settings.json +0 -11
  12. package/biome.json +0 -98
  13. package/examples/join-and-log.js +0 -24
  14. package/release-please-config.json +0 -9
  15. package/src/adapter/adapter.ts +0 -189
  16. package/src/adapter/adapterDiscovery.ts +0 -666
  17. package/src/adapter/const.ts +0 -12
  18. package/src/adapter/deconz/adapter/deconzAdapter.ts +0 -877
  19. package/src/adapter/deconz/driver/constants.ts +0 -246
  20. package/src/adapter/deconz/driver/driver.ts +0 -1540
  21. package/src/adapter/deconz/driver/frame.ts +0 -11
  22. package/src/adapter/deconz/driver/frameParser.ts +0 -753
  23. package/src/adapter/deconz/driver/parser.ts +0 -45
  24. package/src/adapter/deconz/driver/writer.ts +0 -22
  25. package/src/adapter/deconz/types.d.ts +0 -13
  26. package/src/adapter/ember/adapter/emberAdapter.ts +0 -2265
  27. package/src/adapter/ember/adapter/endpoints.ts +0 -86
  28. package/src/adapter/ember/adapter/oneWaitress.ts +0 -324
  29. package/src/adapter/ember/adapter/tokensManager.ts +0 -782
  30. package/src/adapter/ember/consts.ts +0 -178
  31. package/src/adapter/ember/enums.ts +0 -1746
  32. package/src/adapter/ember/ezsp/buffalo.ts +0 -1392
  33. package/src/adapter/ember/ezsp/consts.ts +0 -148
  34. package/src/adapter/ember/ezsp/enums.ts +0 -1114
  35. package/src/adapter/ember/ezsp/ezsp.ts +0 -9061
  36. package/src/adapter/ember/ezspError.ts +0 -10
  37. package/src/adapter/ember/types.ts +0 -866
  38. package/src/adapter/ember/uart/ash.ts +0 -1960
  39. package/src/adapter/ember/uart/consts.ts +0 -109
  40. package/src/adapter/ember/uart/enums.ts +0 -192
  41. package/src/adapter/ember/uart/parser.ts +0 -48
  42. package/src/adapter/ember/uart/queues.ts +0 -247
  43. package/src/adapter/ember/uart/writer.ts +0 -53
  44. package/src/adapter/ember/utils/initters.ts +0 -58
  45. package/src/adapter/ember/utils/math.ts +0 -73
  46. package/src/adapter/events.ts +0 -21
  47. package/src/adapter/ezsp/adapter/backup.ts +0 -109
  48. package/src/adapter/ezsp/adapter/ezspAdapter.ts +0 -614
  49. package/src/adapter/ezsp/driver/commands.ts +0 -2497
  50. package/src/adapter/ezsp/driver/consts.ts +0 -11
  51. package/src/adapter/ezsp/driver/driver.ts +0 -1002
  52. package/src/adapter/ezsp/driver/ezsp.ts +0 -802
  53. package/src/adapter/ezsp/driver/frame.ts +0 -101
  54. package/src/adapter/ezsp/driver/index.ts +0 -4
  55. package/src/adapter/ezsp/driver/multicast.ts +0 -78
  56. package/src/adapter/ezsp/driver/parser.ts +0 -81
  57. package/src/adapter/ezsp/driver/types/basic.ts +0 -201
  58. package/src/adapter/ezsp/driver/types/index.ts +0 -239
  59. package/src/adapter/ezsp/driver/types/named.ts +0 -2330
  60. package/src/adapter/ezsp/driver/types/struct.ts +0 -844
  61. package/src/adapter/ezsp/driver/uart.ts +0 -460
  62. package/src/adapter/ezsp/driver/utils/crc16ccitt.ts +0 -44
  63. package/src/adapter/ezsp/driver/utils/index.ts +0 -32
  64. package/src/adapter/ezsp/driver/writer.ts +0 -64
  65. package/src/adapter/index.ts +0 -3
  66. package/src/adapter/serialPort.ts +0 -58
  67. package/src/adapter/socketPortUtils.ts +0 -16
  68. package/src/adapter/tstype.ts +0 -78
  69. package/src/adapter/z-stack/adapter/adapter-backup.ts +0 -519
  70. package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +0 -457
  71. package/src/adapter/z-stack/adapter/endpoints.ts +0 -57
  72. package/src/adapter/z-stack/adapter/manager.ts +0 -543
  73. package/src/adapter/z-stack/adapter/tstype.ts +0 -6
  74. package/src/adapter/z-stack/adapter/zStackAdapter.ts +0 -1190
  75. package/src/adapter/z-stack/constants/af.ts +0 -27
  76. package/src/adapter/z-stack/constants/common.ts +0 -285
  77. package/src/adapter/z-stack/constants/dbg.ts +0 -23
  78. package/src/adapter/z-stack/constants/index.ts +0 -11
  79. package/src/adapter/z-stack/constants/mac.ts +0 -128
  80. package/src/adapter/z-stack/constants/sapi.ts +0 -25
  81. package/src/adapter/z-stack/constants/sys.ts +0 -72
  82. package/src/adapter/z-stack/constants/util.ts +0 -82
  83. package/src/adapter/z-stack/constants/utils.ts +0 -14
  84. package/src/adapter/z-stack/constants/zdo.ts +0 -103
  85. package/src/adapter/z-stack/models/startup-options.ts +0 -13
  86. package/src/adapter/z-stack/structs/entries/address-manager-entry.ts +0 -44
  87. package/src/adapter/z-stack/structs/entries/address-manager-table.ts +0 -19
  88. package/src/adapter/z-stack/structs/entries/aps-link-key-data-entry.ts +0 -12
  89. package/src/adapter/z-stack/structs/entries/aps-link-key-data-table.ts +0 -21
  90. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-entry.ts +0 -19
  91. package/src/adapter/z-stack/structs/entries/aps-tc-link-key-table.ts +0 -21
  92. package/src/adapter/z-stack/structs/entries/channel-list.ts +0 -8
  93. package/src/adapter/z-stack/structs/entries/has-configured.ts +0 -16
  94. package/src/adapter/z-stack/structs/entries/index.ts +0 -16
  95. package/src/adapter/z-stack/structs/entries/nib.ts +0 -66
  96. package/src/adapter/z-stack/structs/entries/nwk-key-descriptor.ts +0 -15
  97. package/src/adapter/z-stack/structs/entries/nwk-key.ts +0 -13
  98. package/src/adapter/z-stack/structs/entries/nwk-pan-id.ts +0 -8
  99. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-entry.ts +0 -20
  100. package/src/adapter/z-stack/structs/entries/nwk-sec-material-descriptor-table.ts +0 -19
  101. package/src/adapter/z-stack/structs/entries/security-manager-entry.ts +0 -33
  102. package/src/adapter/z-stack/structs/entries/security-manager-table.ts +0 -22
  103. package/src/adapter/z-stack/structs/index.ts +0 -4
  104. package/src/adapter/z-stack/structs/serializable-memory-object.ts +0 -14
  105. package/src/adapter/z-stack/structs/struct.ts +0 -367
  106. package/src/adapter/z-stack/structs/table.ts +0 -198
  107. package/src/adapter/z-stack/unpi/constants.ts +0 -33
  108. package/src/adapter/z-stack/unpi/frame.ts +0 -62
  109. package/src/adapter/z-stack/unpi/index.ts +0 -4
  110. package/src/adapter/z-stack/unpi/parser.ts +0 -56
  111. package/src/adapter/z-stack/unpi/writer.ts +0 -21
  112. package/src/adapter/z-stack/utils/channel-list.ts +0 -40
  113. package/src/adapter/z-stack/utils/index.ts +0 -2
  114. package/src/adapter/z-stack/utils/network-options.ts +0 -26
  115. package/src/adapter/z-stack/znp/buffaloZnp.ts +0 -175
  116. package/src/adapter/z-stack/znp/definition.ts +0 -2713
  117. package/src/adapter/z-stack/znp/index.ts +0 -2
  118. package/src/adapter/z-stack/znp/parameterType.ts +0 -22
  119. package/src/adapter/z-stack/znp/tstype.ts +0 -44
  120. package/src/adapter/z-stack/znp/utils.ts +0 -10
  121. package/src/adapter/z-stack/znp/znp.ts +0 -342
  122. package/src/adapter/z-stack/znp/zpiObject.ts +0 -148
  123. package/src/adapter/zboss/adapter/zbossAdapter.ts +0 -526
  124. package/src/adapter/zboss/commands.ts +0 -1184
  125. package/src/adapter/zboss/consts.ts +0 -9
  126. package/src/adapter/zboss/driver.ts +0 -422
  127. package/src/adapter/zboss/enums.ts +0 -360
  128. package/src/adapter/zboss/frame.ts +0 -227
  129. package/src/adapter/zboss/reader.ts +0 -65
  130. package/src/adapter/zboss/types.ts +0 -0
  131. package/src/adapter/zboss/uart.ts +0 -428
  132. package/src/adapter/zboss/utils.ts +0 -58
  133. package/src/adapter/zboss/writer.ts +0 -49
  134. package/src/adapter/zigate/adapter/patchZdoBuffaloBE.ts +0 -27
  135. package/src/adapter/zigate/adapter/zigateAdapter.ts +0 -618
  136. package/src/adapter/zigate/driver/LICENSE +0 -17
  137. package/src/adapter/zigate/driver/buffaloZiGate.ts +0 -212
  138. package/src/adapter/zigate/driver/commandType.ts +0 -418
  139. package/src/adapter/zigate/driver/constants.ts +0 -150
  140. package/src/adapter/zigate/driver/frame.ts +0 -197
  141. package/src/adapter/zigate/driver/messageType.ts +0 -287
  142. package/src/adapter/zigate/driver/parameterType.ts +0 -32
  143. package/src/adapter/zigate/driver/ziGateObject.ts +0 -146
  144. package/src/adapter/zigate/driver/zigate.ts +0 -423
  145. package/src/adapter/zoh/adapter/utils.ts +0 -27
  146. package/src/adapter/zoh/adapter/zohAdapter.ts +0 -838
  147. package/src/buffalo/buffalo.ts +0 -342
  148. package/src/buffalo/index.ts +0 -1
  149. package/src/controller/controller.ts +0 -1022
  150. package/src/controller/database.ts +0 -124
  151. package/src/controller/events.ts +0 -52
  152. package/src/controller/greenPower.ts +0 -603
  153. package/src/controller/helpers/index.ts +0 -1
  154. package/src/controller/helpers/installCodes.ts +0 -107
  155. package/src/controller/helpers/request.ts +0 -96
  156. package/src/controller/helpers/requestQueue.ts +0 -125
  157. package/src/controller/helpers/zclFrameConverter.ts +0 -47
  158. package/src/controller/helpers/zclTransactionSequenceNumber.ts +0 -19
  159. package/src/controller/index.ts +0 -6
  160. package/src/controller/model/device.ts +0 -1249
  161. package/src/controller/model/endpoint.ts +0 -1105
  162. package/src/controller/model/entity.ts +0 -23
  163. package/src/controller/model/group.ts +0 -424
  164. package/src/controller/model/index.ts +0 -5
  165. package/src/controller/model/zigbeeEntity.ts +0 -30
  166. package/src/controller/touchlink.ts +0 -189
  167. package/src/controller/tstype.ts +0 -274
  168. package/src/index.ts +0 -12
  169. package/src/models/backup-storage-legacy.ts +0 -48
  170. package/src/models/backup-storage-unified.ts +0 -47
  171. package/src/models/backup.ts +0 -37
  172. package/src/models/index.ts +0 -5
  173. package/src/models/network-options.ts +0 -11
  174. package/src/utils/backup.ts +0 -152
  175. package/src/utils/index.ts +0 -5
  176. package/src/utils/logger.ts +0 -20
  177. package/src/utils/patchBigIntSerialization.ts +0 -8
  178. package/src/utils/queue.ts +0 -76
  179. package/src/utils/types.d.ts +0 -3
  180. package/src/utils/utils.ts +0 -19
  181. package/src/utils/wait.ts +0 -5
  182. package/src/utils/waitress.ts +0 -96
  183. package/src/zspec/consts.ts +0 -84
  184. package/src/zspec/enums.ts +0 -22
  185. package/src/zspec/index.ts +0 -3
  186. package/src/zspec/tstypes.ts +0 -18
  187. package/src/zspec/utils.ts +0 -247
  188. package/src/zspec/zcl/buffaloZcl.ts +0 -1220
  189. package/src/zspec/zcl/definition/cluster.ts +0 -5915
  190. package/src/zspec/zcl/definition/clusters-typegen.ts +0 -588
  191. package/src/zspec/zcl/definition/clusters-types.ts +0 -7331
  192. package/src/zspec/zcl/definition/consts.ts +0 -24
  193. package/src/zspec/zcl/definition/enums.ts +0 -203
  194. package/src/zspec/zcl/definition/foundation.ts +0 -329
  195. package/src/zspec/zcl/definition/manufacturerCode.ts +0 -729
  196. package/src/zspec/zcl/definition/status.ts +0 -69
  197. package/src/zspec/zcl/definition/tstype.ts +0 -377
  198. package/src/zspec/zcl/index.ts +0 -11
  199. package/src/zspec/zcl/utils.ts +0 -321
  200. package/src/zspec/zcl/zclFrame.ts +0 -356
  201. package/src/zspec/zcl/zclHeader.ts +0 -102
  202. package/src/zspec/zcl/zclStatusError.ts +0 -10
  203. package/src/zspec/zdo/buffaloZdo.ts +0 -2336
  204. package/src/zspec/zdo/definition/clusters.ts +0 -722
  205. package/src/zspec/zdo/definition/consts.ts +0 -16
  206. package/src/zspec/zdo/definition/enums.ts +0 -99
  207. package/src/zspec/zdo/definition/status.ts +0 -105
  208. package/src/zspec/zdo/definition/tstypes.ts +0 -1062
  209. package/src/zspec/zdo/index.ts +0 -7
  210. package/src/zspec/zdo/utils.ts +0 -76
  211. package/src/zspec/zdo/zdoStatusError.ts +0 -10
  212. package/test/adapter/adapter.test.ts +0 -1062
  213. package/test/adapter/ember/ash.test.ts +0 -337
  214. package/test/adapter/ember/consts.ts +0 -131
  215. package/test/adapter/ember/emberAdapter.test.ts +0 -3449
  216. package/test/adapter/ember/ezsp.test.ts +0 -385
  217. package/test/adapter/ember/ezspBuffalo.test.ts +0 -93
  218. package/test/adapter/ember/ezspError.test.ts +0 -12
  219. package/test/adapter/ember/math.test.ts +0 -206
  220. package/test/adapter/ezsp/frame.test.ts +0 -30
  221. package/test/adapter/ezsp/uart.test.ts +0 -181
  222. package/test/adapter/z-stack/adapter.test.ts +0 -3984
  223. package/test/adapter/z-stack/constants.test.ts +0 -33
  224. package/test/adapter/z-stack/structs.test.ts +0 -115
  225. package/test/adapter/z-stack/unpi.test.ts +0 -213
  226. package/test/adapter/z-stack/znp.test.ts +0 -1284
  227. package/test/adapter/zboss/fixZdoResponse.test.ts +0 -179
  228. package/test/adapter/zigate/patchZdoBuffaloBE.test.ts +0 -81
  229. package/test/adapter/zigate/zdo.test.ts +0 -187
  230. package/test/adapter/zoh/utils.test.ts +0 -36
  231. package/test/adapter/zoh/zohAdapter.test.ts +0 -1307
  232. package/test/benchOptions.ts +0 -14
  233. package/test/buffalo.test.ts +0 -431
  234. package/test/controller.bench.ts +0 -214
  235. package/test/controller.test.ts +0 -8702
  236. package/test/greenpower.test.ts +0 -1408
  237. package/test/mockAdapters.ts +0 -65
  238. package/test/mockDevices.ts +0 -598
  239. package/test/requests.bench.ts +0 -229
  240. package/test/testUtils.ts +0 -20
  241. package/test/tsconfig.json +0 -9
  242. package/test/utils/math.ts +0 -19
  243. package/test/utils.test.ts +0 -279
  244. package/test/vitest.config.mts +0 -26
  245. package/test/zcl.test.ts +0 -2831
  246. package/test/zspec/utils.test.ts +0 -68
  247. package/test/zspec/zcl/buffalo.test.ts +0 -1374
  248. package/test/zspec/zcl/frame.test.ts +0 -960
  249. package/test/zspec/zcl/utils.test.ts +0 -273
  250. package/test/zspec/zdo/buffalo.test.ts +0 -1850
  251. package/test/zspec/zdo/utils.test.ts +0 -241
  252. package/tsconfig.json +0 -24
@@ -1,666 +0,0 @@
1
- import assert from "node:assert";
2
- import {platform} from "node:os";
3
- import type {PortInfo} from "@serialport/bindings-cpp";
4
- import {Bonjour, type Service} from "bonjour-service";
5
- import {wait} from "../utils";
6
- import {logger} from "../utils/logger";
7
- import {SerialPort} from "./serialPort";
8
- import type {Adapter, DiscoverableUsbAdapter, UsbAdapterFingerprint} from "./tstype";
9
-
10
- const NS = "zh:adapter:discovery";
11
-
12
- const enum UsbFingerprintMatchScore {
13
- None = 0,
14
- VidPid = 1,
15
- VidPidManuf = 2,
16
- VidPidPath = 3,
17
- VidPidManufPath = 4,
18
- }
19
-
20
- /**
21
- * @see https://serialport.io/docs/api-bindings-cpp#list
22
- *
23
- * On Windows, there are occurrences where `manufacturer` is replaced by the OS driver. Example: `ITEAD` => `wch.cn`.
24
- *
25
- * In virtualized environments, the passthrough mechanism can affect the `path`.
26
- * Example:
27
- * Linux: /dev/serial/by-id/usb-ITEAD_SONOFF_Zigbee_3.0_USB_Dongle_Plus_V2_20240122184111-if00
28
- * Windows host => Linux guest: /dev/serial/by-id/usb-1a86_USB_Single_Serial_54DD002111-if00
29
- *
30
- * XXX: vendorId `10c4` + productId `ea60` is a problem on Windows since can't match `path` and possibly can't match `manufacturer` to refine properly
31
- */
32
- const USB_FINGERPRINTS: Record<DiscoverableUsbAdapter, UsbAdapterFingerprint[]> = {
33
- deconz: [
34
- {
35
- // Conbee II
36
- vendorId: "1cf1",
37
- productId: "0030",
38
- manufacturer: "dresden elektronik ingenieurtechnik GmbH",
39
- // /dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_DE2132111-if00
40
- pathRegex: ".*conbee.*",
41
- },
42
- {
43
- // Conbee III
44
- vendorId: "0403",
45
- productId: "6015",
46
- manufacturer: "dresden elektronik ingenieurtechnik GmbH",
47
- // /dev/serial/by-id/usb-dresden_elektronik_ConBee_III_DE03188111-if00-port0
48
- pathRegex: ".*conbee.*",
49
- },
50
- ],
51
- ember: [
52
- // {
53
- // // TODO: Easyiot ZB-GW04 (v1.1)
54
- // vendorId: '',
55
- // productId: '',
56
- // manufacturer: '',
57
- // pathRegex: '.*.*',
58
- // },
59
- // {
60
- // // TODO: Easyiot ZB-GW04 (v1.2)
61
- // vendorId: '1a86',
62
- // productId: '',
63
- // manufacturer: '',
64
- // // /dev/serial/by-id/usb-1a86_USB_Serial-if00-port0
65
- // pathRegex: '.*.*',
66
- // },
67
- {
68
- // Home Assistant SkyConnect
69
- vendorId: "10c4",
70
- productId: "ea60",
71
- manufacturer: "Nabu Casa",
72
- // /dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_3abe54797c91ed118fc3cad13b20a111-if00-port0
73
- pathRegex: ".*Nabu_Casa_SkyConnect.*",
74
- },
75
- // {
76
- // // TODO: Home Assistant Yellow
77
- // vendorId: '',
78
- // productId: '',
79
- // manufacturer: '',
80
- // // /dev/ttyAMA1
81
- // pathRegex: '.*.*',
82
- // },
83
- {
84
- // SMLight slzb-07
85
- vendorId: "10c4",
86
- productId: "ea60",
87
- manufacturer: "SMLIGHT",
88
- // /dev/serial/by-id/usb-SMLIGHT_SMLIGHT_SLZB-07_be9faa0786e1ea11bd68dc2d9a583111-if00-port0
89
- // /dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_a215650c853bec119a079e957a0af111-if00-port0
90
- pathRegex: ".*slzb-07_.*", // `_` to not match 07p7
91
- },
92
- {
93
- // SMLight slzb-07mg24
94
- vendorId: "10c4",
95
- productId: "ea60",
96
- manufacturer: "SMLIGHT",
97
- pathRegex: ".*slzb-07mg24.*",
98
- },
99
- {
100
- // Sonoff ZBDongle-E V2 (CH variant)
101
- vendorId: "1a86",
102
- productId: "55d4",
103
- manufacturer: "ITEAD",
104
- // /dev/serial/by-id/usb-ITEAD_SONOFF_Zigbee_3.0_USB_Dongle_Plus_V2_20240122184111-if00
105
- // /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_186ff44314e2ed11b891eb5162c61111-if00-port0
106
- pathRegex: ".*sonoff.*plus.*",
107
- },
108
- {
109
- // Sonoff ZBDongle-E V2 (CP variant)
110
- vendorId: "10c4",
111
- productId: "ea60",
112
- manufacturer: "ITEAD",
113
- // /dev/serial/by-id/usb-Itead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_V2_a6ee897e4d1fef11aa004ad0639e525b-if00-port0
114
- pathRegex: ".*sonoff.*plus_v2_.*",
115
- },
116
- {
117
- // Sonoff ZBDongle-M
118
- vendorId: "10c4",
119
- productId: "ea60",
120
- manufacturer: "SONOFF",
121
- // /dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Max_MG24_08965d6b0674ef11b2f4e61e313510fd-if00-port0
122
- pathRegex: ".*sonoff.*max.*",
123
- },
124
- {
125
- // SONOFF Dongle Plus MG24
126
- vendorId: "10c4",
127
- productId: "ea60",
128
- manufacturer: "SONOFF",
129
- // /dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Plus_MG24_b023a583a66bef118e30a3adc169b110-if00-port0
130
- pathRegex: ".*sonoff.*plus.*mg24.*",
131
- },
132
- {
133
- // SONOFF Dongle Lite MG21
134
- vendorId: "10c4",
135
- productId: "ea60",
136
- manufacturer: "SONOFF",
137
- // /dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Lite_MG21_c82fc0a1a36bef11a026a1adc169b110-if00-port0
138
- pathRegex: ".*sonoff.*lite.*mg21.*",
139
- },
140
- // {
141
- // // TODO: Z-station by z-wave.me (EFR32MG21A020F1024IM32)
142
- // vendorId: '',
143
- // productId: '',
144
- // // manufacturer: '',
145
- // // /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012BA111-if01-port0
146
- // pathRegex: '.*CP2105.*',
147
- // },
148
- ],
149
- zstack: [
150
- {
151
- // ZZH
152
- vendorId: "0403",
153
- productId: "6015",
154
- manufacturer: "Electrolama",
155
- pathRegex: ".*electrolama.*",
156
- },
157
- {
158
- // slae.sh cc2652rb
159
- vendorId: "10c4",
160
- productId: "ea60",
161
- manufacturer: "Silicon Labs",
162
- // /dev/serial/by-id/usb-Silicon_Labs_slae.sh_cc2652rb_stick_-_slaesh_s_iot_stuff_00_12_4B_00_21_A8_EC_79-if00-port0
163
- pathRegex: ".*slae\\.sh_cc2652rb.*",
164
- },
165
- {
166
- // Sonoff ZBDongle-P (CC2652P)
167
- vendorId: "10c4",
168
- productId: "ea60",
169
- manufacturer: "ITEAD",
170
- // /dev/serial/by-id/usb-Silicon_Labs_Sonoff_Zigbee_3.0_USB_Dongle_Plus_0111-if00-port0
171
- // /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_b8b49abd27a6ed11a280eba32981d111-if00-port0
172
- pathRegex: ".*sonoff.*plus(?!_v2_).*",
173
- },
174
- {
175
- // CC2538
176
- vendorId: "0451",
177
- productId: "16c8",
178
- manufacturer: "Texas Instruments",
179
- // zStack30x: /dev/serial/by-id/usb-Texas_Instruments_CC2538_USB_CDC-if00
180
- pathRegex: ".*CC2538.*",
181
- },
182
- {
183
- // CC2531
184
- vendorId: "0451",
185
- productId: "16a8",
186
- manufacturer: "Texas Instruments",
187
- // /dev/serial/by-id/usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B0018ED1111-if00
188
- pathRegex: ".*CC2531.*",
189
- },
190
- {
191
- // Texas instruments launchpads
192
- vendorId: "0451",
193
- productId: "bef3",
194
- manufacturer: "Texas Instruments",
195
- pathRegex: ".*Texas_Instruments.*",
196
- },
197
- {
198
- // SMLight slzb-07p7
199
- vendorId: "10c4",
200
- productId: "ea60",
201
- manufacturer: "SMLIGHT",
202
- // /dev/serial/by-id/usb-SMLIGHT_SMLIGHT_SLZB-07p7_be9faa0786e1ea11bd68dc2d9a583111-if00-port0
203
- pathRegex: ".*SLZB-07p7.*",
204
- },
205
- {
206
- // SMLight slzb-06p7
207
- vendorId: "10c4",
208
- productId: "ea60",
209
- manufacturer: "SMLIGHT",
210
- // /dev/serial/by-id/usb-SMLIGHT_SMLIGHT_SLZB-06p7_82e43faf9872ed118bb924f3fdf7b791-if00-port0
211
- pathRegex: ".*SMLIGHT_SLZB-06p7_.*",
212
- },
213
- {
214
- // SMLight slzb-06p10
215
- vendorId: "10c4",
216
- productId: "ea60",
217
- manufacturer: "SMLIGHT",
218
- // /dev/serial/by-id/usb-SMLIGHT_SMLIGHT_SLZB-06p10_40df2f3e3977ed11b142f6fafdf7b791-if00-port0
219
- pathRegex: ".*SMLIGHT_SLZB-06p10_.*",
220
- },
221
- {
222
- // TubesZB ?
223
- vendorId: "10c4",
224
- productId: "ea60",
225
- // manufacturer: '',
226
- pathRegex: ".*tubeszb.*",
227
- },
228
- {
229
- // TubesZB ?
230
- vendorId: "1a86",
231
- productId: "7523",
232
- // manufacturer: '',
233
- pathRegex: ".*tubeszb.*",
234
- },
235
- {
236
- // ZigStar
237
- vendorId: "1a86",
238
- productId: "7523",
239
- // manufacturer: '',
240
- pathRegex: ".*zigstar.*",
241
- },
242
- ],
243
- zboss: [
244
- {
245
- // Nordic Zigbee NCP
246
- vendorId: "2fe3",
247
- productId: "0100",
248
- manufacturer: "ZEPHYR",
249
- // /dev/serial/by-id/usb-ZEPHYR_Zigbee_NCP_54ACCFAFA6DAD111-if00
250
- pathRegex: ".*ZEPHYR.*",
251
- },
252
- ],
253
- zigate: [
254
- {
255
- // ZiGate PL2303HX (blue)
256
- vendorId: "067b",
257
- productId: "2303",
258
- manufacturer: "zigate_PL2303",
259
- pathRegex: ".*zigate.*",
260
- },
261
- {
262
- // ZiGate CP2102 (red)
263
- vendorId: "10c4",
264
- productId: "ea60",
265
- manufacturer: "zigate_cp2102",
266
- pathRegex: ".*zigate.*",
267
- },
268
- {
269
- // ZiGate+ V2 CDM_21228
270
- vendorId: "0403",
271
- productId: "6015",
272
- // manufacturer: '',
273
- // /dev/serial/by-id/usb-FTDI_ZiGate_ZIGATE+-if00-port0
274
- pathRegex: ".*zigate.*",
275
- },
276
- ],
277
- };
278
-
279
- /**
280
- * Vendor and Product IDs that are prone to conflict if only matching on vendorId+productId.
281
- */
282
- const USB_FINGERPRINTS_CONFLICT_IDS: ReadonlyArray<string /* vendorId:productId */> = ["10c4:ea60"];
283
-
284
- /** Time allotted for mDNS scanning */
285
- const MDNS_SCAN_TIME = 2000;
286
-
287
- async function getSerialPortList(): Promise<PortInfo[]> {
288
- const portInfos = await SerialPort.list();
289
-
290
- // TODO: can sorting be removed in favor of `path` regex matching?
291
-
292
- // CC1352P_2 and CC26X2R1 lists as 2 USB devices with same manufacturer, productId and vendorId
293
- // one is the actual chip interface, other is the XDS110.
294
- // The chip is always exposed on the first one after alphabetical sorting.
295
- /* v8 ignore next */
296
- portInfos.sort((a, b) => (a.path < b.path ? -1 : 1));
297
-
298
- return portInfos;
299
- }
300
-
301
- /**
302
- * Case insensitive string matching.
303
- * @param str1
304
- * @param str2
305
- * @returns
306
- */
307
- function matchString(str1: string, str2: string): boolean {
308
- return str1.localeCompare(str2, undefined, {sensitivity: "base"}) === 0;
309
- }
310
-
311
- /**
312
- * Case insensitive regex matching.
313
- * @param regexStr Passed to RegExp constructor.
314
- * @param str Always returns false if undefined.
315
- * @returns
316
- */
317
- function matchRegex(regexStr: string, str?: string): boolean {
318
- return str !== undefined && new RegExp(regexStr, "i").test(str);
319
- }
320
-
321
- function matchUsbFingerprint(
322
- portInfo: PortInfo,
323
- entries: UsbAdapterFingerprint[],
324
- isWindows: boolean,
325
- conflictProne: boolean,
326
- ): [path: PortInfo["path"], score: number] | undefined {
327
- if (!portInfo.vendorId || !portInfo.productId) {
328
- // port info is missing essential information for proper matching, ignore it
329
- return undefined;
330
- }
331
-
332
- let match: UsbAdapterFingerprint | undefined;
333
- let score: number = UsbFingerprintMatchScore.None;
334
-
335
- for (const entry of entries) {
336
- if (!matchString(portInfo.vendorId, entry.vendorId) || !matchString(portInfo.productId, entry.productId)) {
337
- continue;
338
- }
339
-
340
- // allow matching on vendorId+productId only on Windows
341
- if (score < UsbFingerprintMatchScore.VidPid && isWindows) {
342
- match = entry;
343
- score = UsbFingerprintMatchScore.VidPid;
344
- }
345
-
346
- if (
347
- score < UsbFingerprintMatchScore.VidPidManuf &&
348
- entry.manufacturer &&
349
- portInfo.manufacturer &&
350
- matchString(portInfo.manufacturer, entry.manufacturer)
351
- ) {
352
- match = entry;
353
- score = UsbFingerprintMatchScore.VidPidManuf;
354
-
355
- if (isWindows && !conflictProne) {
356
- // path will never match on Windows (COMx), assume vendor+product+manufacturer is "exact match"
357
- // except for conflict-prone, since it could easily return a mismatch (better to return no match and force manual config)
358
- return [portInfo.path, score];
359
- }
360
- }
361
-
362
- if (
363
- score < UsbFingerprintMatchScore.VidPidPath &&
364
- entry.pathRegex &&
365
- (matchRegex(entry.pathRegex, portInfo.path) || matchRegex(entry.pathRegex, portInfo.pnpId))
366
- ) {
367
- if (score === UsbFingerprintMatchScore.VidPidManuf) {
368
- // best possible match, return early
369
- return [portInfo.path, UsbFingerprintMatchScore.VidPidManufPath];
370
- }
371
-
372
- match = entry;
373
- score = UsbFingerprintMatchScore.VidPidPath;
374
- }
375
- }
376
-
377
- // poor match only returned if port info not conflict-prone
378
- if (match) {
379
- if (score > UsbFingerprintMatchScore.VidPid) {
380
- // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
381
- if (conflictProne && score < UsbFingerprintMatchScore.VidPidPath && matchString(match.manufacturer!, "itead")) {
382
- // can't trust metadata "only" on sonoff dongles with conflicts
383
- return undefined;
384
- }
385
-
386
- return [portInfo.path, score];
387
- }
388
-
389
- if (!conflictProne) {
390
- return [portInfo.path, score];
391
- }
392
- }
393
-
394
- return undefined;
395
- }
396
-
397
- export async function matchUsbAdapter(adapter: Adapter, path: string): Promise<boolean> {
398
- // no point in matching this
399
- if (adapter === "zoh") {
400
- return false;
401
- }
402
-
403
- const isWindows = platform() === "win32";
404
- const portList = await getSerialPortList();
405
-
406
- logger.debug(() => `Connected devices: ${JSON.stringify(portList)}`, NS);
407
-
408
- for (const portInfo of portList) {
409
- if (portInfo.path !== path) {
410
- continue;
411
- }
412
-
413
- const conflictProne = USB_FINGERPRINTS_CONFLICT_IDS.includes(`${portInfo.vendorId}:${portInfo.productId}`);
414
- const match = matchUsbFingerprint(portInfo, USB_FINGERPRINTS[adapter === "ezsp" ? "ember" : adapter], isWindows, conflictProne);
415
-
416
- if (match) {
417
- logger.info(() => `Matched adapter: ${JSON.stringify(portInfo)} => ${adapter}: ${JSON.stringify(match[1])}`, NS);
418
- return true;
419
- }
420
- }
421
-
422
- return false;
423
- }
424
-
425
- export function findUsbAdapterBestMatch(
426
- adapter: Adapter | undefined,
427
- portInfo: PortInfo,
428
- isWindows: boolean,
429
- conflictProne: boolean,
430
- ): [DiscoverableUsbAdapter, NonNullable<ReturnType<typeof matchUsbFingerprint>>] | undefined {
431
- let bestMatch: [DiscoverableUsbAdapter, NonNullable<ReturnType<typeof matchUsbFingerprint>>] | undefined;
432
-
433
- for (const key in USB_FINGERPRINTS) {
434
- if (adapter && adapter !== key) {
435
- continue;
436
- }
437
-
438
- // biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
439
- const match = matchUsbFingerprint(portInfo, USB_FINGERPRINTS[key as DiscoverableUsbAdapter]!, isWindows, conflictProne);
440
-
441
- // register the match if no previous or better score
442
- if (match && (!bestMatch || bestMatch[1][1] < match[1])) {
443
- bestMatch = [key as DiscoverableUsbAdapter, match];
444
-
445
- if (match[1] === UsbFingerprintMatchScore.VidPidManufPath) {
446
- // got best possible match, exit loop
447
- break;
448
- }
449
- }
450
- }
451
-
452
- return bestMatch;
453
- }
454
-
455
- export async function findUsbAdapter(
456
- adapter?: Adapter,
457
- path?: string,
458
- ): Promise<[adapter: DiscoverableUsbAdapter, path: PortInfo["path"]] | undefined> {
459
- const isWindows = platform() === "win32";
460
- // refine to DiscoverableUSBAdapter
461
- adapter = adapter && adapter === "ezsp" ? "ember" : adapter;
462
- const portList = await getSerialPortList();
463
-
464
- logger.debug(() => `Connected devices: ${JSON.stringify(portList)}`, NS);
465
-
466
- for (const portInfo of portList) {
467
- if (path && portInfo.path !== path) {
468
- continue;
469
- }
470
-
471
- const conflictProne = USB_FINGERPRINTS_CONFLICT_IDS.includes(`${portInfo.vendorId}:${portInfo.productId}`);
472
- const bestMatch = findUsbAdapterBestMatch(adapter, portInfo, isWindows, conflictProne);
473
-
474
- if (bestMatch) {
475
- logger.info(
476
- () => `Matched adapter: ${JSON.stringify(portInfo)} => ${bestMatch[0]}: path=${bestMatch[1][0]}, score=${bestMatch[1][1]}`,
477
- NS,
478
- );
479
- return [bestMatch[0], bestMatch[1][0]];
480
- }
481
- }
482
- }
483
-
484
- function getMdnsRadioAdapter(radio: string): Adapter {
485
- switch (radio) {
486
- case "znp":
487
- return "zstack";
488
- case "ezsp":
489
- return "ember";
490
- default:
491
- return radio as Adapter;
492
- }
493
- }
494
-
495
- export async function findMdnsAdapter(path: string): Promise<[adapter: Adapter, path: string]> {
496
- const mdnsDevice = path.substring(7);
497
-
498
- if (mdnsDevice.length === 0) {
499
- throw new Error("No mdns device specified. You must specify the coordinator mdns service type after mdns://, e.g. mdns://my-adapter");
500
- }
501
-
502
- const bj = new Bonjour();
503
-
504
- logger.info(`Starting mdns discovery for coordinator: ${mdnsDevice}`, NS);
505
-
506
- return await new Promise((resolve, reject) => {
507
- bj.findOne({type: mdnsDevice}, MDNS_SCAN_TIME, (service: Service) => {
508
- if (service) {
509
- if (service.txt?.radio_type && service.port) {
510
- const mdnsAddress = service.addresses?.[0] ?? service.host;
511
- const mdnsPort = service.port;
512
- const mdnsAdapter = getMdnsRadioAdapter(service.txt.radio_type);
513
-
514
- logger.info(`Coordinator Address: ${mdnsAddress}`, NS);
515
- logger.info(`Coordinator Port: ${mdnsPort}`, NS);
516
- logger.info(`Coordinator Radio: ${mdnsAdapter}`, NS);
517
- bj.destroy();
518
-
519
- resolve([mdnsAdapter, `tcp://${mdnsAddress}:${mdnsPort}`]);
520
- } else {
521
- bj.destroy();
522
- reject(
523
- new Error(
524
- `Coordinator returned wrong Zeroconf format! The following values are expected:\ntxt.radio_type, got: ${service.txt?.radio_type}\nport, got: ${service.port}`,
525
- ),
526
- );
527
- }
528
- } else {
529
- bj.destroy();
530
- reject(new Error(`Coordinator [${mdnsDevice}] not found after timeout of ${MDNS_SCAN_TIME}ms!`));
531
- }
532
- });
533
- });
534
- }
535
-
536
- export function findTcpAdapter(path: string, adapter?: Adapter): [adapter: Adapter, path: string] {
537
- try {
538
- const url = new URL(path);
539
- assert(url.port !== "");
540
- } catch {
541
- throw new Error("Invalid TCP path, expected format: tcp://<host>:<port>");
542
- }
543
-
544
- if (!adapter) {
545
- throw new Error(`Cannot discover TCP adapters at this time. Specify valid 'adapter' and 'port' in your configuration.`);
546
- }
547
-
548
- // always use `tcp://` format
549
- return [adapter, path.replace(/^socket/, "tcp")];
550
- }
551
-
552
- /**
553
- * Discover adapter using mDNS, TCP or USB.
554
- *
555
- * @param adapter The adapter type.
556
- * - mDNS: Unused.
557
- * - TCP: Required, cannot discover at this time.
558
- * - USB: Optional, limits the discovery to the specified adapter type.
559
- * @param path The path to the adapter.
560
- * - mDNS: Required, serves to initiate the discovery.
561
- * - TCP: Required, cannot discover at this time.
562
- * - USB: Optional, limits the discovery to the specified path.
563
- * @returns adapter An adapter type supported by Z2M. While result is TS-typed, this should be validated against actual values before use.
564
- * @returns path Path to adapter.
565
- */
566
- export async function discoverAdapter(adapter?: Adapter, path?: string): Promise<[adapter: Adapter, path: string]> {
567
- if (path) {
568
- if (path.startsWith("mdns://")) {
569
- return await findMdnsAdapter(path);
570
- }
571
-
572
- if (path.startsWith("tcp://") || path.startsWith("socket://")) {
573
- return findTcpAdapter(path, adapter);
574
- }
575
-
576
- if (adapter) {
577
- try {
578
- const matched = await matchUsbAdapter(adapter, path);
579
-
580
- if (!matched) {
581
- logger.debug(`Unable to match USB adapter: ${adapter} | ${path}`, NS);
582
- }
583
- } catch (error) {
584
- logger.debug(`Error while trying to match USB adapter (${(error as Error).message}).`, NS);
585
- }
586
-
587
- return [adapter, path];
588
- }
589
- }
590
-
591
- try {
592
- // default to matching USB
593
- const match = await findUsbAdapter(adapter, path);
594
-
595
- if (!match) {
596
- throw new Error("No valid USB adapter found");
597
- }
598
-
599
- // keep adapter if `ezsp` since findUSBAdapter returns DiscoverableUSBAdapter
600
- return adapter && adapter === "ezsp" ? [adapter, match[1]] : match;
601
- } catch (error) {
602
- throw new Error(`USB adapter discovery error (${(error as Error).message}). Specify valid 'adapter' and 'port' in your configuration.`);
603
- }
604
- }
605
-
606
- /**
607
- * @returns List of all serial and mDNS devices found, with matching `adapter` if available
608
- */
609
- export async function findAllDevices(): Promise<{name: string; path: string; adapter?: Adapter}[]> {
610
- const devices: {name: string; path: string; adapter?: Adapter}[] = [];
611
- const isWindows = platform() === "win32";
612
-
613
- try {
614
- const portList = await getSerialPortList();
615
-
616
- for (const portInfo of portList) {
617
- // override matching on Windows, too many chances of mismatch due to lacking data
618
- const bestMatch = isWindows
619
- ? undefined
620
- : findUsbAdapterBestMatch(
621
- undefined,
622
- portInfo,
623
- isWindows,
624
- USB_FINGERPRINTS_CONFLICT_IDS.includes(`${portInfo.vendorId}:${portInfo.productId}`),
625
- );
626
- // @ts-expect-error friendlyName Windows only
627
- const friendlyName = portInfo.friendlyName ?? portInfo.pnpId;
628
-
629
- devices.push({
630
- name: `${friendlyName} (${portInfo.manufacturer})`,
631
- path: portInfo.path,
632
- adapter: bestMatch ? bestMatch[0] : undefined,
633
- });
634
- }
635
- /* v8 ignore start */
636
- } catch (error) {
637
- logger.debug(`Failed to retrieve serial list ${(error as Error).message}.`, NS);
638
- }
639
- /* v8 ignore stop */
640
-
641
- try {
642
- const bonjour = new Bonjour();
643
- const browser = bonjour.find(null, (service) => {
644
- if (service.txt?.radio_type) {
645
- const path = `tcp://${service.addresses?.[0] ?? service.host}:${service.port}`;
646
-
647
- devices.push({
648
- name: `${service.name ?? service.txt.name ?? "Unknown"} (${path})`,
649
- path,
650
- adapter: getMdnsRadioAdapter(service.txt.radio_type),
651
- });
652
- }
653
- });
654
-
655
- browser.start();
656
- await wait(MDNS_SCAN_TIME);
657
- browser.stop();
658
- bonjour.destroy();
659
- /* v8 ignore start */
660
- } catch (error) {
661
- logger.debug(`Failed to retrieve mDNS list ${(error as Error).message}.`, NS);
662
- }
663
- /* v8 ignore stop */
664
-
665
- return devices;
666
- }
@@ -1,12 +0,0 @@
1
- import * as Zcl from "../zspec/zcl";
2
-
3
- /**
4
- * Workaround for devices that require a specific manufacturer code to be reported by coordinator while interviewing...
5
- * - Lumi/Aqara devices do not work properly otherwise (missing features): https://github.com/Koenkk/zigbee2mqtt/issues/9274
6
- */
7
- export const WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE: {[ieeePrefix: string]: Zcl.ManufacturerCode} = {
8
- // NOTE: Lumi has a new prefix registered since 2021, in case they start using that one with new devices, it might need to be added here too...
9
- // "0x18c23c" https://maclookup.app/vendors/lumi-united-technology-co-ltd
10
- "0x54ef44": Zcl.ManufacturerCode.LUMI_UNITED_TECHOLOGY_LTD_SHENZHEN,
11
- "0x04cf8c": Zcl.ManufacturerCode.LUMI_UNITED_TECHOLOGY_LTD_SHENZHEN,
12
- };