matterbridge-zigbee2mqtt 2.2.3-dev.5 → 2.3.0-dev.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.
@@ -1,25 +1,3 @@
1
- /**
2
- * This file contains the class Zigbee2MQTT and all the interfaces to communicate with zigbee2MQTT.
3
- *
4
- * @file zigbee2mqtt.ts
5
- * @author Luca Liguori
6
- * @date 2023-06-30
7
- * @version 2.3.3
8
- *
9
- * Copyright 2023, 2024, 2025 Luca Liguori.
10
- *
11
- * Licensed under the Apache License, Version 2.0 (the "License");
12
- * you may not use this file except in compliance with the License.
13
- * You may obtain a copy of the License at
14
- *
15
- * http://www.apache.org/licenses/LICENSE-2.0
16
- *
17
- * Unless required by applicable law or agreed to in writing, software
18
- * distributed under the License is distributed on an "AS IS" BASIS,
19
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
- * See the License for the specific language governing permissions and
21
- * limitations under the License. *
22
- */
23
1
  import fs from 'fs';
24
2
  import path from 'path';
25
3
  import * as util from 'util';
@@ -30,9 +8,7 @@ import { AnsiLogger, rs, db, dn, gn, er, zb, hk, id, idn, ign, REVERSE, REVERSEO
30
8
  import { mkdir } from 'fs/promises';
31
9
  const writeFile = util.promisify(fs.writeFile);
32
10
  export class Zigbee2MQTT extends EventEmitter {
33
- // Logger
34
11
  log;
35
- // Instance properties
36
12
  mqttHost;
37
13
  mqttPort;
38
14
  mqttTopic;
@@ -55,19 +31,17 @@ export class Zigbee2MQTT extends EventEmitter {
55
31
  z2mDevices;
56
32
  z2mGroups;
57
33
  loggedEntries = 0;
58
- // Define our MQTT options
59
34
  options = {
60
35
  clientId: 'classZigbee2MQTT_' + crypto.randomBytes(8).toString('hex'),
61
36
  keepalive: 60,
62
37
  protocolId: 'MQTT',
63
38
  protocolVersion: 5,
64
- reconnectPeriod: 5000, // 1000
65
- connectTimeout: 60 * 1000, // 30 * 1000
39
+ reconnectPeriod: 5000,
40
+ connectTimeout: 60 * 1000,
66
41
  username: undefined,
67
42
  password: undefined,
68
43
  clean: true,
69
44
  };
70
- // Constructor
71
45
  constructor(mqttHost, mqttPort, mqttTopic, mqttUsername = undefined, mqttPassword = undefined, protocolVersion = 5, debug = false) {
72
46
  super();
73
47
  this.mqttHost = mqttHost;
@@ -85,11 +59,11 @@ export class Zigbee2MQTT extends EventEmitter {
85
59
  this.z2mVersion = '';
86
60
  this.z2mDevices = [];
87
61
  this.z2mGroups = [];
88
- this.log = new AnsiLogger({ logName: 'Zigbee2MQTT', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: debug ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
62
+ this.log = new AnsiLogger({ logName: 'Zigbee2MQTT', logTimestampFormat: 4, logLevel: debug ? "debug" : "info" });
89
63
  this.log.debug(`Created new instance with host: ${mqttHost} port: ${mqttPort} protocol ${protocolVersion} topic: ${mqttTopic} username: ${mqttUsername !== undefined && mqttUsername !== '' ? mqttUsername : 'undefined'} password: ${mqttPassword !== undefined && mqttPassword !== '' ? '*****' : 'undefined'}`);
90
64
  }
91
65
  setLogDebug(logDebug) {
92
- this.log.logLevel = logDebug ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */;
66
+ this.log.logLevel = logDebug ? "debug" : "info";
93
67
  }
94
68
  async setDataPath(dataPath) {
95
69
  try {
@@ -107,7 +81,6 @@ export class Zigbee2MQTT extends EventEmitter {
107
81
  }
108
82
  }
109
83
  }
110
- // Get the URL for connect
111
84
  getUrl() {
112
85
  return 'mqtt://' + this.mqttHost + ':' + this.mqttPort.toString();
113
86
  }
@@ -117,13 +90,12 @@ export class Zigbee2MQTT extends EventEmitter {
117
90
  .then((client) => {
118
91
  this.log.debug('Connection established');
119
92
  this.mqttClient = client;
120
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
121
93
  this.mqttClient.on('connect', (packet) => {
122
- this.log.debug(`MQTT client connect to ${this.getUrl()}${rs}` /* , connack*/);
94
+ this.log.debug(`MQTT client connect to ${this.getUrl()}${rs}`);
123
95
  this.mqttIsConnected = true;
124
96
  this.mqttIsReconnecting = false;
125
97
  this.mqttIsEnding = false;
126
- this.emit('mqtt_connect'); // Never emitted at the start cause we connect async
98
+ this.emit('mqtt_connect');
127
99
  });
128
100
  this.mqttClient.on('reconnect', () => {
129
101
  this.log.debug(`MQTT client reconnect to ${this.getUrl()}${rs}`);
@@ -154,17 +126,11 @@ export class Zigbee2MQTT extends EventEmitter {
154
126
  this.log.debug('MQTT client error', error);
155
127
  this.emit('mqtt_error', error);
156
128
  });
157
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
158
129
  this.mqttClient.on('packetsend', (packet) => {
159
- // this.log.debug('classZigbee2MQTT=>Event packetsend');
160
130
  });
161
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
162
131
  this.mqttClient.on('packetreceive', (packet) => {
163
- // this.log.debug('classZigbee2MQTT=>Event packetreceive');
164
132
  });
165
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
166
133
  this.mqttClient.on('message', (topic, payload, packet) => {
167
- // this.log.debug(`classZigbee2MQTT=>Event message topic: ${topic} payload: ${payload.toString()} packet: ${debugStringify(packet)}`);
168
134
  this.messageHandler(topic, payload);
169
135
  });
170
136
  this.log.debug('Started');
@@ -172,7 +138,6 @@ export class Zigbee2MQTT extends EventEmitter {
172
138
  this.mqttIsReconnecting = false;
173
139
  this.mqttIsEnding = false;
174
140
  this.emit('mqtt_connect');
175
- // Send a heartbeat every 60 seconds
176
141
  this.mqttKeepaliveInterval = setInterval(async () => {
177
142
  this.log.debug('Publishing keepalive MQTT message');
178
143
  try {
@@ -217,7 +182,6 @@ export class Zigbee2MQTT extends EventEmitter {
217
182
  async subscribe(topic) {
218
183
  if (this.mqttClient && this.mqttIsConnected) {
219
184
  this.log.debug(`Subscribing topic: ${topic}`);
220
- // Use subscribeAsync for promise-based handling
221
185
  this.mqttClient
222
186
  .subscribeAsync(topic, { qos: 2 })
223
187
  .then(() => {
@@ -241,7 +205,6 @@ export class Zigbee2MQTT extends EventEmitter {
241
205
  this.mqttPublishQueueTimeout = setInterval(async () => {
242
206
  if (this.mqttClient && this.mqttPublishQueue.length > 0) {
243
207
  this.log.debug(`**Publish ${REVERSE}[${this.mqttPublishQueue.length}-${this.mqttPublishInflights}]${REVERSEOFF} topic: ${this.mqttPublishQueue[0].topic} message: ${this.mqttPublishQueue[0].message}${rs}`);
244
- // this.publish(this.mqttPublishQueue[0].topic, this.mqttPublishQueue[0].message);
245
208
  try {
246
209
  this.mqttPublishInflights++;
247
210
  await this.mqttClient.publishAsync(this.mqttPublishQueue[0].topic, this.mqttPublishQueue[0].message, { qos: 2 });
@@ -294,15 +257,13 @@ export class Zigbee2MQTT extends EventEmitter {
294
257
  async writeBufferJSON(file, buffer) {
295
258
  const filePath = path.join(this.mqttDataPath, file);
296
259
  let jsonData;
297
- // Parse the buffer to JSON
298
260
  try {
299
261
  jsonData = this.tryJsonParse(buffer.toString());
300
262
  }
301
263
  catch (error) {
302
264
  this.log.error('writeBufferJSON: parsing error:', error);
303
- return; // Stop execution if parsing fails
265
+ return;
304
266
  }
305
- // Write the JSON data to a file
306
267
  writeFile(`${filePath}.json`, JSON.stringify(jsonData, null, 2))
307
268
  .then(() => {
308
269
  this.log.debug(`Successfully wrote to ${filePath}.json`);
@@ -313,7 +274,6 @@ export class Zigbee2MQTT extends EventEmitter {
313
274
  }
314
275
  async writeFile(file, data) {
315
276
  const filePath = path.join(this.mqttDataPath, file);
316
- // Write the data to a file
317
277
  writeFile(`${filePath}`, data)
318
278
  .then(() => {
319
279
  this.log.debug(`Successfully wrote to ${filePath}`);
@@ -322,7 +282,6 @@ export class Zigbee2MQTT extends EventEmitter {
322
282
  this.log.error(`Error writing to ${filePath}:`, error);
323
283
  });
324
284
  }
325
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
326
285
  tryJsonParse(text) {
327
286
  try {
328
287
  return JSON.parse(text);
@@ -343,7 +302,6 @@ export class Zigbee2MQTT extends EventEmitter {
343
302
  else {
344
303
  data = { state: payloadString };
345
304
  }
346
- // this.log.debug('classZigbee2MQTT=>Message bridge/state', data);
347
305
  if (data.state === 'online') {
348
306
  this.z2mIsOnline = true;
349
307
  this.emit('online');
@@ -356,7 +314,6 @@ export class Zigbee2MQTT extends EventEmitter {
356
314
  }
357
315
  else if (topic.startsWith(this.mqttTopic + '/bridge/info')) {
358
316
  const data = this.tryJsonParse(payload.toString());
359
- // this.log.info('classZigbee2MQTT=>Message bridge/info', data);
360
317
  this.z2mPermitJoin = data.permit_join ? data.permit_join : false;
361
318
  this.z2mPermitJoinTimeout = data.permit_join_timeout ? data.permit_join_timeout : 0;
362
319
  this.z2mVersion = data.version ? data.version : '';
@@ -375,14 +332,14 @@ export class Zigbee2MQTT extends EventEmitter {
375
332
  this.log.info(`Message bridge/info advanced.legacy_availability_payload is ${data.config.advanced.legacy_availability_payload}`);
376
333
  this.emit('info', this.z2mVersion, this.z2mIsAvailabilityEnabled, this.z2mPermitJoin, this.z2mPermitJoinTimeout);
377
334
  this.emit('bridge-info', data);
378
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */)
335
+ if (this.log.logLevel === "debug")
379
336
  this.writeBufferJSON('bridge-info', payload);
380
337
  }
381
338
  else if (topic.startsWith(this.mqttTopic + '/bridge/devices')) {
382
339
  this.z2mDevices.splice(0, this.z2mDevices.length);
383
340
  const devices = this.tryJsonParse(payload.toString());
384
341
  const data = this.tryJsonParse(payload.toString());
385
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */)
342
+ if (this.log.logLevel === "debug")
386
343
  this.writeBufferJSON('bridge-devices', payload);
387
344
  this.emit('bridge-devices', data);
388
345
  let index = 1;
@@ -437,13 +394,10 @@ export class Zigbee2MQTT extends EventEmitter {
437
394
  };
438
395
  for (const expose of device.definition.exposes) {
439
396
  if (!expose.property && !expose.name && expose.features && expose.type) {
440
- // Specific expose https://www.zigbee2mqtt.io/guide/usage/exposes.html
441
397
  if (z2m.category === '') {
442
- // Only the first type: light, switch ...
443
398
  z2m.category = expose.type;
444
399
  }
445
400
  for (const feature of expose.features) {
446
- // Exposes nested inside features
447
401
  feature.category = expose.type;
448
402
  z2m.exposes.push(feature);
449
403
  if (feature.endpoint) {
@@ -452,7 +406,6 @@ export class Zigbee2MQTT extends EventEmitter {
452
406
  }
453
407
  }
454
408
  else {
455
- // Generic expose https://www.zigbee2mqtt.io/guide/usage/exposes.html
456
409
  expose.category = '';
457
410
  z2m.exposes.push(expose);
458
411
  }
@@ -468,20 +421,18 @@ export class Zigbee2MQTT extends EventEmitter {
468
421
  endpoint: key,
469
422
  };
470
423
  z2m.endpoints.push(endpointWithKey);
471
- // this.log.debug('classZigbee2MQTT=>Message bridge/devices endpoints=>', device.friendly_name, key, endpoint);
472
424
  }
473
425
  this.z2mDevices.push(z2m);
474
426
  }
475
427
  }
476
428
  this.log.debug(`Received ${this.z2mDevices.length} devices`);
477
429
  this.emit('devices');
478
- // this.printDevices();
479
430
  }
480
431
  else if (topic.startsWith(this.mqttTopic + '/bridge/groups')) {
481
432
  this.z2mGroups.splice(0, this.z2mGroups.length);
482
433
  const groups = this.tryJsonParse(payload.toString());
483
434
  const data = this.tryJsonParse(payload.toString());
484
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */)
435
+ if (this.log.logLevel === "debug")
485
436
  this.writeBufferJSON('bridge-groups', payload);
486
437
  this.emit('bridge-groups', data);
487
438
  let index = 1;
@@ -507,7 +458,6 @@ export class Zigbee2MQTT extends EventEmitter {
507
458
  }
508
459
  this.log.debug(`Received ${this.z2mGroups.length} groups`);
509
460
  this.emit('groups');
510
- // this.printGroups();
511
461
  }
512
462
  else if (topic.startsWith(this.mqttTopic + '/bridge/extensions')) {
513
463
  const extensions = this.tryJsonParse(payload.toString());
@@ -565,49 +515,28 @@ export class Zigbee2MQTT extends EventEmitter {
565
515
  }
566
516
  const data = this.tryJsonParse(payload.toString());
567
517
  this.log.debug(`Message topic: ${topic} payload:${rs}`, data);
568
- /*
569
- [05/09/2023, 20:35:26] [z2m] classZigbee2MQTT=>Message bridge/response zigbee2mqtt/bridge/response/group/add {
570
- data: { friendly_name: 'Guest', id: 1 },
571
- status: 'ok',
572
- transaction: '1nqux-2'
573
- }
574
- [11/09/2023, 15:13:54] [z2m] classZigbee2MQTT=>Message bridge/response zigbee2mqtt/bridge/response/group/members/add {
575
- data: { device: '0x84fd27fffe83066f/1', group: 'Master Guest room' },
576
- status: 'ok',
577
- transaction: '2ww7l-5'
578
- }
579
- */
580
518
  }
581
519
  else if (topic.startsWith(this.mqttTopic + '/bridge/logging')) {
582
- // const data = JSON.parse(payload.toString());
583
- // this.log.debug('classZigbee2MQTT=>Message bridge/logging', data);
584
520
  }
585
521
  else if (topic.startsWith(this.mqttTopic + '/bridge/config')) {
586
522
  this.log.debug(`Message topic: ${topic}`);
587
- // const data = JSON.parse(payload.toString());
588
- // this.log.debug('classZigbee2MQTT=>Message bridge/config', data);
589
523
  }
590
524
  else if (topic.startsWith(this.mqttTopic + '/bridge/definitions')) {
591
525
  this.log.debug(`Message topic: ${topic}`);
592
- // const data = JSON.parse(payload.toString());
593
- // this.log.debug('classZigbee2MQTT=>Message bridge/definitions', data);
594
526
  }
595
527
  else if (topic.startsWith(this.mqttTopic + '/bridge')) {
596
528
  this.log.debug(`Message topic: ${topic}`);
597
- // const data = JSON.parse(payload.toString());
598
- // this.log.debug('classZigbee2MQTT=>Message bridge/definitions', data);
599
529
  }
600
530
  else {
601
531
  let entity = topic.replace(this.mqttTopic + '/', '');
602
532
  let service = '';
603
533
  if (entity.search('/')) {
604
- // set get availability or unknown TODO
605
534
  const parts = entity.split('/');
606
535
  entity = parts[0];
607
536
  service = parts[1];
608
537
  }
609
538
  if (entity === 'Coordinator') {
610
- const data = this.tryJsonParse(payload.toString()); // TODO crash on device rename
539
+ const data = this.tryJsonParse(payload.toString());
611
540
  if (service === 'availability') {
612
541
  if (data.state === 'online') {
613
542
  this.log.debug(`Received ONLINE for ${id}Coordinator${rs}`, data);
@@ -618,8 +547,7 @@ export class Zigbee2MQTT extends EventEmitter {
618
547
  }
619
548
  return;
620
549
  }
621
- // Log the first 1000 payloads
622
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */ && this.loggedEntries < 1000) {
550
+ if (this.log.logLevel === "debug" && this.loggedEntries < 1000) {
623
551
  const logEntry = {
624
552
  entity,
625
553
  service,
@@ -656,9 +584,7 @@ export class Zigbee2MQTT extends EventEmitter {
656
584
  return this.z2mGroups.find((group) => group.friendly_name === name);
657
585
  }
658
586
  handleDeviceMessage(deviceIndex, entity, service, payload) {
659
- // this.log.info(`classZigbee2MQTT=>handleDeviceMessage ${id}#${deviceIndex + 1}${rs} entity ${dn}${entity}${rs} service ${zb}${service}${rs} payload ${pl}${payload}${rs}`);
660
587
  if (payload.length === 0 || payload === null) {
661
- // this.log.warn(`handleDeviceMessage ${id}#${deviceIndex + 1}${rs} entity ${dn}${entity}${rs} service ${zb}${service}${rs} payload null`);
662
588
  return;
663
589
  }
664
590
  const payloadString = payload.toString();
@@ -667,41 +593,33 @@ export class Zigbee2MQTT extends EventEmitter {
667
593
  data = this.tryJsonParse(payload.toString());
668
594
  }
669
595
  else {
670
- data = { state: payloadString }; // Only state for availability
596
+ data = { state: payloadString };
671
597
  }
672
598
  if (service === 'availability') {
673
599
  if (data.state === 'online') {
674
600
  this.z2mDevices[deviceIndex].isAvailabilityEnabled = true;
675
601
  this.z2mDevices[deviceIndex].isOnline = true;
676
- // this.log.warn('handleDeviceMessage availability payload: ', data);
677
602
  this.emit('availability', entity, true);
678
603
  this.emit('ONLINE-' + entity);
679
604
  }
680
605
  else if (data.state === 'offline') {
681
606
  this.z2mDevices[deviceIndex].isOnline = false;
682
- // this.log.warn('handleDeviceMessage availability payload: ', data);
683
607
  this.emit('availability', entity, false);
684
608
  this.emit('OFFLINE-' + entity);
685
609
  }
686
610
  }
687
611
  else if (service === 'get') {
688
- // Do nothing
689
612
  }
690
613
  else if (service === 'set') {
691
- // Do nothing
692
614
  }
693
615
  else if (service === undefined) {
694
- // this.log.debug(`classZigbee2MQTT=>emitting message for device ${dn}${entity}${rs} payload ${pl}${payload}${rs}`);
695
616
  this.emit('MESSAGE-' + entity, data);
696
617
  }
697
618
  else {
698
- // MQTT output attribute type
699
619
  }
700
620
  }
701
621
  handleGroupMessage(groupIndex, entity, service, payload) {
702
- // this.log.info(`classZigbee2MQTT=>handleGroupMessage ${id}#${groupIndex + 1}${rs} entity ${gn}${entity}${rs} service ${zb}${service}${rs} payload ${pl}${payload}${rs}`);
703
622
  if (payload.length === 0 || payload === null) {
704
- // this.log.warn(`handleGroupMessage ${id}#${groupIndex + 1}${rs} entity ${gn}${entity}${rs} service ${zb}${service}${rs} payload null`);
705
623
  return;
706
624
  }
707
625
  const payloadString = payload.toString();
@@ -710,7 +628,7 @@ export class Zigbee2MQTT extends EventEmitter {
710
628
  data = this.tryJsonParse(payload.toString());
711
629
  }
712
630
  else {
713
- data = { state: payloadString }; // Only state for availability
631
+ data = { state: payloadString };
714
632
  }
715
633
  data['last_seen'] = new Date().toISOString();
716
634
  if (service === 'availability') {
@@ -727,29 +645,16 @@ export class Zigbee2MQTT extends EventEmitter {
727
645
  }
728
646
  }
729
647
  else if (service === 'get') {
730
- // Do nothing
731
648
  }
732
649
  else if (service === 'set') {
733
- // Do nothing
734
650
  }
735
651
  else if (service === undefined) {
736
- // this.log.debug(`classZigbee2MQTT=>emitting message for group ${gn}${entity}${rs} payload ${pl}${payload}${rs}`);
737
652
  this.emit('MESSAGE-' + entity, data);
738
653
  }
739
654
  else {
740
- // MQTT output attribute type
741
655
  }
742
656
  }
743
657
  handleResponseNetworkmap(payload) {
744
- /*
745
- "routes": [
746
- {
747
- "destinationAddress": 31833,
748
- "nextHop": 31833,
749
- "status": "ACTIVE"
750
- }
751
- ],
752
- */
753
658
  const data = this.tryJsonParse(payload.toString());
754
659
  const topology = data.data.value;
755
660
  const lqi = (lqi) => {
@@ -799,7 +704,7 @@ export class Zigbee2MQTT extends EventEmitter {
799
704
  };
800
705
  const timePassedSince = (lastSeen) => {
801
706
  const now = Date.now();
802
- const difference = now - lastSeen; // difference in milliseconds
707
+ const difference = now - lastSeen;
803
708
  const days = Math.floor(difference / (1000 * 60 * 60 * 24));
804
709
  if (days > 0) {
805
710
  return `${days} days ago`;
@@ -815,116 +720,51 @@ export class Zigbee2MQTT extends EventEmitter {
815
720
  const seconds = Math.floor((difference % (1000 * 60)) / 1000);
816
721
  return `${seconds} seconds ago`;
817
722
  };
818
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */)
723
+ if (this.log.logLevel === "debug")
819
724
  this.writeBufferJSON('networkmap_' + data.data.type, payload);
820
725
  if (data.data.type === 'graphviz') {
821
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */)
726
+ if (this.log.logLevel === "debug")
822
727
  this.writeFile('networkmap_' + data.data.type + '.txt', data.data.value);
823
728
  }
824
729
  if (data.data.type === 'plantuml') {
825
- if (this.log.logLevel === "debug" /* LogLevel.DEBUG */)
730
+ if (this.log.logLevel === "debug")
826
731
  this.writeFile('networkmap_' + data.data.type + '.txt', data.data.value);
827
732
  }
828
733
  if (data.data.type === 'raw') {
829
- // Log nodes with links
830
734
  this.log.warn('Network map nodes:');
831
735
  topology.nodes.sort((a, b) => a.friendlyName.localeCompare(b.friendlyName));
832
736
  topology.nodes.forEach((node, index) => {
833
737
  this.log.debug(`Node [${index.toString().padStart(3, ' ')}] ${node.type === 'EndDevice' ? ign : node.type === 'Router' ? idn : '\x1b[48;5;1m\x1b[38;5;255m'}${node.friendlyName}${rs}${db} addr: ${node.ieeeAddr}-0x${node.networkAddress.toString(16)} type: ${node.type} lastseen: ${timePassedSince(node.lastSeen)}`);
834
- // SourceAddr
835
- const sourceLinks = topology.links.filter((link) => link.sourceIeeeAddr === node.ieeeAddr); // Filter
836
- sourceLinks.sort((a, b) => a.lqi - b.lqi); // Sort by lqi
738
+ const sourceLinks = topology.links.filter((link) => link.sourceIeeeAddr === node.ieeeAddr);
739
+ sourceLinks.sort((a, b) => a.lqi - b.lqi);
837
740
  sourceLinks.forEach((link, index) => {
838
- // const targetNode = topology.nodes.find((node) => node.ieeeAddr === link.target.ieeeAddr);
839
741
  this.log.debug(` link [${index.toString().padStart(4, ' ')}] lqi: ${lqi(link.lqi)} depth: ${depth(link.depth)} relation: ${relationship(link.relationship)} > > > ${friendlyName(link.target.ieeeAddr)}`);
840
742
  });
841
- // TargetAddr
842
- const targetLinks = topology.links.filter((link) => link.targetIeeeAddr === node.ieeeAddr); // Filter
843
- targetLinks.sort((a, b) => a.lqi - b.lqi); // Sort by lqi
743
+ const targetLinks = topology.links.filter((link) => link.targetIeeeAddr === node.ieeeAddr);
744
+ targetLinks.sort((a, b) => a.lqi - b.lqi);
844
745
  targetLinks.forEach((link, index) => {
845
- // const sourceNode = topology.nodes.find((node) => node.ieeeAddr === link.source.ieeeAddr);
846
746
  this.log.debug(` link [${index.toString().padStart(4, ' ')}] lqi: ${lqi(link.lqi)} depth: ${depth(link.depth)} relation: ${relationship(link.relationship)} < < < ${friendlyName(link.source.ieeeAddr)}`);
847
747
  });
848
748
  });
849
- // Log links
850
- /*
851
- this.log.warn('Network map links:');
852
- map.links.sort((a, b) => a.sourceIeeeAddr.localeCompare(b.sourceIeeeAddr));
853
- map.links.forEach( (link, index) => {
854
- const sourceNode = map.nodes.find(node => node.ieeeAddr === link.source.ieeeAddr);
855
- assert(sourceNode, `${wr}NwkAddr error node ${link.sourceIeeeAddr} not found${db}`);
856
- const targetNode = map.nodes.find(node => node.ieeeAddr === link.target.ieeeAddr);
857
- assert(targetNode, `${wr}NwkAddr error node ${link.targetIeeeAddr} not found${db}`);
858
- this.log.debug(`- link[${index}]: ${link.source.ieeeAddr}-${link.source.networkAddress.toString(16)} (${sourceNode?.friendlyName})
859
- Lqi: ${link.lqi} Depth: ${link.depth} Relation: ${link.relationship} => ${link.target.ieeeAddr}-${link.target.networkAddress.toString(16)} (${targetNode?.friendlyName})`);
860
- } );
861
- */
862
749
  }
863
750
  }
864
751
  handleResponseDeviceRename(payload) {
865
- /*
866
- {
867
- data: {
868
- from: '0xcc86ecfffe4e9d25',
869
- homeassistant_rename: false,
870
- to: 'Double switch'
871
- },
872
- status: 'ok',
873
- transaction: 'smeo0-8'
874
- }
875
- */
876
752
  const json = this.tryJsonParse(payload.toString());
877
753
  this.log.debug(`handleResponseDeviceRename from ${json.data.from} to ${json.data.to} status ${json.status}`);
878
754
  const device = this.z2mDevices.find((device) => device.friendly_name === json.data.to);
879
755
  this.emit('device_rename', device?.ieee_address, json.data.from, json.data.to);
880
756
  }
881
757
  handleResponseDeviceRemove(payload) {
882
- /*
883
- {
884
- data: { block: false, force: false, id: 'Presence sensor' },
885
- status: 'ok',
886
- transaction: 'bet01-20'
887
- }
888
- */
889
758
  const json = this.tryJsonParse(payload.toString());
890
759
  this.log.debug(`handleResponseDeviceRemove name ${json.data.id} status ${json.status} block ${json.data.block} force ${json.data.force}`);
891
760
  this.emit('device_remove', json.data.id, json.status, json.data.block, json.data.force);
892
761
  }
893
762
  handleResponseDeviceOptions(payload) {
894
- /*
895
- {
896
- data: {
897
- from: {
898
- color_sync: false,
899
- legacy: false,
900
- state_action: false,
901
- transition: 0
902
- },
903
- id: '0xa4c1388ad0ebb0a6',
904
- restart_required: false,
905
- to: {
906
- color_sync: false,
907
- legacy: false,
908
- state_action: false,
909
- transition: 0
910
- }
911
- },
912
- status: 'ok',
913
- transaction: '8j6s7-3'
914
- }
915
- */
916
763
  const json = this.tryJsonParse(payload.toString());
917
764
  this.log.debug(`handleResponseDeviceOptions ieee_address ${json.data.id} status ${json.status} from ${json.data.from} to ${json.data.to}`);
918
765
  this.emit('device_options', json.data.id, json.status, json.data.from, json.data.to);
919
766
  }
920
767
  handleResponseGroupAdd(payload) {
921
- /*
922
- {
923
- data: { friendly_name: 'Test', id: 7 },
924
- status: 'ok',
925
- transaction: '8j6s7-9'
926
- }
927
- */
928
768
  const json = this.tryJsonParse(payload.toString());
929
769
  this.log.debug(`handleResponseGroupAdd() friendly_name ${json.data.friendly_name} id ${json.data.id} status ${json.status}`);
930
770
  if (json.status === 'ok') {
@@ -932,13 +772,6 @@ export class Zigbee2MQTT extends EventEmitter {
932
772
  }
933
773
  }
934
774
  handleResponseGroupRemove(payload) {
935
- /*
936
- {
937
- data: { force: false, id: 'Test' },
938
- status: 'ok',
939
- transaction: '8j6s7-10'
940
- }
941
- */
942
775
  const json = this.tryJsonParse(payload.toString());
943
776
  this.log.debug(`handleResponseGroupRemove() friendly_name ${json.data.id} status ${json.status}`);
944
777
  if (json.status === 'ok') {
@@ -946,13 +779,6 @@ export class Zigbee2MQTT extends EventEmitter {
946
779
  }
947
780
  }
948
781
  handleResponseGroupRename(payload) {
949
- /*
950
- {
951
- data: { from: 'Test2', homeassistant_rename: false, to: 'Test' },
952
- status: 'ok',
953
- transaction: '0r51l-15'
954
- }
955
- */
956
782
  const json = this.tryJsonParse(payload.toString());
957
783
  this.log.debug(`handleResponseGroupRename() from ${json.data.from} to ${json.data.to} status ${json.status}`);
958
784
  if (json.status === 'ok') {
@@ -960,13 +786,6 @@ export class Zigbee2MQTT extends EventEmitter {
960
786
  }
961
787
  }
962
788
  handleResponseGroupAddMember(payload) {
963
- /*
964
- {
965
- data: { device: '0xa4c1388ad0ebb0a6/1', group: 'Test2' },
966
- status: 'ok',
967
- transaction: '0r51l-7'
968
- }
969
- */
970
789
  const json = this.tryJsonParse(payload.toString());
971
790
  this.log.debug(`handleResponseGroupAddMembers() add to group friendly_name ${json.data.group} device ieee_address ${json.data.device} status ${json.status}`);
972
791
  if (json.status === 'ok' && json.data.device && json.data.device.includes('/')) {
@@ -974,13 +793,6 @@ export class Zigbee2MQTT extends EventEmitter {
974
793
  }
975
794
  }
976
795
  handleResponseGroupRemoveMember(payload) {
977
- /*
978
- {
979
- data: { device: 'Gledopto RGBCTT light', group: 'Test2' },
980
- status: 'ok',
981
- transaction: '0r51l-10'
982
- }
983
- */
984
796
  const json = this.tryJsonParse(payload.toString());
985
797
  this.log.debug(`handleResponseGroupRemoveMember() remove from group friendly_name ${json.data.group} device friendly_name ${json.data.device} status ${json.status}`);
986
798
  if (json.status === 'ok') {
@@ -988,13 +800,6 @@ export class Zigbee2MQTT extends EventEmitter {
988
800
  }
989
801
  }
990
802
  handleResponsePermitJoin(payload) {
991
- /*
992
- {
993
- data: { device?: 'Coordinator', time: 254, value: true },
994
- status: 'ok',
995
- transaction: 'adeis-5'
996
- }
997
- */
998
803
  const json = this.tryJsonParse(payload.toString());
999
804
  this.log.debug(`handleResponsePermitJoin() device: ${json.data.device ? json.data.device : 'All'} time: ${json.data.time} value: ${json.data.value} status: ${json.status}`);
1000
805
  if (json.status === 'ok') {
@@ -1008,75 +813,23 @@ export class Zigbee2MQTT extends EventEmitter {
1008
813
  this.log.error('handleEvent() undefined type', json);
1009
814
  break;
1010
815
  case 'device_leave':
1011
- /*
1012
- {
1013
- data: { friendly_name: 'Light sensor', ieee_address: '0x54ef44100085c321' },
1014
- type: 'device_leave'
1015
- }
1016
- */
1017
816
  this.log.debug(`handleEvent() type: device_leave name: ${json.data.friendly_name} address: ${json.data.ieee_address}`);
1018
817
  this.emit('device_leave', json.data.friendly_name, json.data.ieee_address);
1019
818
  break;
1020
819
  case 'device_joined':
1021
- /*
1022
- {
1023
- data: {
1024
- friendly_name: 'Kitchen Dishwasher water leak sensor',
1025
- ieee_address: '0x00158d0007c2b057'
1026
- },
1027
- type: 'device_joined'
1028
- }
1029
- */
1030
820
  this.log.debug(`handleEvent() type: device_joined name: ${json.data.friendly_name} address: ${json.data.ieee_address}`);
1031
821
  this.emit('device_joined', json.data.friendly_name, json.data.ieee_address);
1032
822
  break;
1033
823
  case 'device_announce':
1034
- /*
1035
- {
1036
- data: {
1037
- friendly_name: 'Kitchen Sink water leak sensor',
1038
- ieee_address: '0x00158d0008f1099b'
1039
- },
1040
- type: 'device_announce'
1041
- }
1042
- */
1043
824
  this.log.debug(`handleEvent() type: device_announce name: ${json.data.friendly_name} address: ${json.data.ieee_address}`);
1044
825
  this.emit('device_announce', json.data.friendly_name, json.data.ieee_address);
1045
826
  break;
1046
827
  case 'device_interview':
1047
- /*
1048
- {
1049
- data: {
1050
- friendly_name: 'Kitchen Sink water leak sensor',
1051
- ieee_address: '0x00158d0008f1099b',
1052
- status: 'started'
1053
- },
1054
- type: 'device_interview'
1055
- }
1056
- {
1057
- data: {
1058
- definition: {
1059
- description: 'Aqara water leak sensor',
1060
- exposes: [Array],
1061
- model: 'SJCGQ11LM',
1062
- options: [Array],
1063
- supports_ota: false,
1064
- vendor: 'Xiaomi'
1065
- },
1066
- friendly_name: 'Kitchen Sink water leak sensor',
1067
- ieee_address: '0x00158d0008f1099b',
1068
- status: 'successful',
1069
- supported: true
1070
- },
1071
- type: 'device_interview'
1072
- }
1073
- */
1074
828
  this.log.debug(`handleEvent() type: device_interview name: ${json.data.friendly_name} address: ${json.data.ieee_address} status: ${json.data.status} supported: ${json.data.supported}`);
1075
829
  this.emit('device_interview', json.data.friendly_name, json.data.ieee_address, json.data.status, json.data.supported);
1076
830
  break;
1077
831
  }
1078
832
  }
1079
- // Function to read JSON config from a file
1080
833
  readConfig(filename) {
1081
834
  this.log.debug(`Reading config from ${filename}`);
1082
835
  try {
@@ -1089,8 +842,6 @@ export class Zigbee2MQTT extends EventEmitter {
1089
842
  return null;
1090
843
  }
1091
844
  }
1092
- // Function to write JSON config to a file
1093
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1094
845
  writeConfig(filename, data) {
1095
846
  this.log.debug(`Writing config to ${filename}`);
1096
847
  try {
@@ -1218,4 +969,3 @@ export class Zigbee2MQTT extends EventEmitter {
1218
969
  });
1219
970
  }
1220
971
  }
1221
- //# sourceMappingURL=zigbee2mqtt.js.map