iobroker.zigbee 2.0.4 → 2.0.5
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/README.md +83 -56
- package/admin/admin.js +217 -19
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/tab_m.html +13 -8
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/io-package.json +15 -49
- package/lib/DeviceDebug.js +4 -2
- package/lib/commands.js +21 -2
- package/lib/developer.js +0 -0
- package/lib/exposes.js +8 -3
- package/lib/groups.js +6 -8
- package/lib/localConfig.js +4 -5
- package/lib/ota.js +6 -6
- package/lib/statescontroller.js +276 -101
- package/lib/zbDeviceAvailability.js +2 -2
- package/lib/zbDeviceConfigure.js +92 -58
- package/lib/zigbeecontroller.js +44 -46
- package/main.js +143 -217
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -9,18 +9,15 @@
|
|
|
9
9
|
[](https://weblate.iobroker.net/engage/adapters/?utm_source=widget)
|
|
10
10
|
[](https://www.npmjs.com/package/iobroker.zigbee)
|
|
11
11
|
|
|
12
|
-
## ioBroker adapter for Zigbee devices via
|
|
13
|
-
### cc2531/cc2530 are obsolet
|
|
12
|
+
## ioBroker adapter for Zigbee devices via Zigbee coordinator hardware.
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
Using specialized Zigbee-coordinator hardware, the adapter creates and manages a Zigbee Network which can control and connect a large number of Zigbee Devices. The list of compatible devices inlcudes > 4000 devices from > 450 different vendors. The number of devices in the network depends on the available coordinator hardware. Common coordinator hardware are USB sticks with Texas Instruments CC26xx, Silicon Labs EZSP or ZIGate chipsetz. Some branded USB devices (Sonoff ZB-Dongle, Dresden Electronic Conbee) can also be used. There are also network-based hubs from various manufacturers.
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
By working directly with the coordinator, the driver allows you to manage devices without additional application / gateways / bridge from device manufacturers (Xiaomi / TRADFRI / Hue / Tuya). About the device Zigbee-network can be read [here (in English)](https://www.zigbee2mqtt.io/information/zigbee_network.html).
|
|
16
|
+
By working directly with the coordinator, the driver allows you to manage devices without additional application / gateways / bridge from device manufacturers (Xiaomi / TRADFRI / Hue / Tuya). More information about the Zigbee-network can be read [here (in English)](https://www.zigbee2mqtt.io/information/zigbee_network.html).
|
|
19
17
|
|
|
20
18
|
## Hardware
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
One coordinator device is required for each zigbee Adapter instance. The device must be flashed with the respective coordinator firmware. A list of supported coordinators, the necessary equipment for the firmware and the device preparation process for different coordinator devices are described [here in English](https://www.zigbee2mqtt.io/guide/adapters/) or [smarthomescene.com ](https://smarthomescene.com/blog/best-zigbee-dongles-for-home-assistant-2023/) or [here in Russian](https://myzigbee.ru/books/%D0%BF%D1%80%D0%BE%D1%88%D0%B8%D0%B2%D0%BA%D0%B8/page/%D0%BF%D1%80%D0%BE%D1%88%D0%B8%D0%B2%D0%BA%D0%B0-cc2531cc2530)
|
|
20
|
+
One coordinator device is required for each Zigbee Adapter instance. The device must be flashed with the respective coordinator firmware. A list of supported coordinators, the necessary equipment for the firmware and the device preparation process for different coordinator devices are described [here in English](https://www.zigbee2mqtt.io/guide/adapters/) or [smarthomescene.com ](https://smarthomescene.com/blog/best-zigbee-dongles-for-home-assistant-2023/) or [here in Russian](https://myzigbee.ru/books/%D0%BF%D1%80%D0%BE%D1%88%D0%B8%D0%B2%D0%BA%D0%B8/page/%D0%BF%D1%80%D0%BE%D1%88%D0%B8%D0%B2%D0%BA%D0%B0-cc2531cc2530)
|
|
24
21
|
|
|
25
22
|
|
|
26
23
|
### Texas Instruments SoC
|
|
@@ -35,7 +32,6 @@ Current firmware files for these devices can be found [on GitHub](https://github
|
|
|
35
32
|
<span><img src="https://raw.githubusercontent.com/ioBroker/ioBroker.zigbee/master/docs/de/img/CC2538_CC2592_PA.PNG" width="100"></span>
|
|
36
33
|
<span><img src="https://raw.githubusercontent.com/ioBroker/ioBroker.zigbee/master/docs/de/img/cc26x2r.PNG" width="100"></span>
|
|
37
34
|
|
|
38
|
-
tutorial/zigbee.png
|
|
39
35
|
### Dresden Elektronik SoC
|
|
40
36
|
<span><img src="https://raw.githubusercontent.com/ioBroker/ioBroker.zigbee/master/docs/en/img/deconz.png" width="180"></span>
|
|
41
37
|
|
|
@@ -62,62 +58,82 @@ Support for [Silicon Lab Zigbee](https://www.silabs.com/wireless/zigbee) based a
|
|
|
62
58
|
Support for [ZiGate](https://zigate.fr) based adapters is experimental. The initial support for ZiGate is still not yet considered stable, and the project is in need of more developers volunteering to help with this integration. Please refer to the respective documentation on [this page](https://www.zigbee2mqtt.io/guide/adapters/) and [ongoing development discussion](https://github.com/Koenkk/zigbee-herdsman/issues/242) with regards to the state of ZiGate adapter implementation into the zigbee-herdsman and zigbee-herdsman-converters libraries which it depends on.
|
|
63
59
|
|
|
64
60
|
|
|
65
|
-
##
|
|
61
|
+
## Getting started
|
|
62
|
+
|
|
63
|
+
The adapter should **always** be installed from within the ioBroker Admin. Direct npm and GitHub installations are **not recommended**.
|
|
64
|
+
|
|
65
|
+
At first start, it is vital to set up the adapter settings. These include:
|
|
66
|
+
- the communication to the zigbee Coordinator (COM Port). This can be a device identifier or a network address for Network-based coordinators
|
|
67
|
+
- the required firmware-Type
|
|
68
|
+
- the network parameters PanID (a number between 0 and 65565), extended PanID (a 16 digit HEX number) and the zigbee Channel **important: Do not run the adapter without changing the values for PanID (6754) and Extended PanID (DDDDDDDDDDDDDDDD) to unique values for your Zigbee Installation.**
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+

|
|
72
|
+
Please refer to the [in depth documentation](docs/en/readme.md) ([german version](docs/de/readme.md), [russian version](docs/ru/readme.md)) for a detailed explanation on how to configure the adapter.
|
|
73
|
+
|
|
74
|
+
Once the adapter is up and running, the desired devices need to be integrated into the network. This requires for both the adapter and the device to be in pairing mode. Most new devices will be in pairing-mode when they are powered up for the first time, but some will require a special procedure for this. Please refer to the device manual for information on this.
|
|
66
75
|
|
|
67
|
-
|
|
76
|
+
The adapter is placed in pairing mode by pressing the pairing button:
|
|
77
|
+

|
|
68
78
|
|
|
69
|
-
|
|
79
|
+
A dialog showing a pairing countdown appears. When a new device is discovered, interviewed and paired with the network, messages will be shown in this dialog, and the device will show up in the grid of active devices. Any known device should show up with an image and the correct device name, as well as a number of changable settings. Any unknown device will show up with a device name and a ? as icon, while devices which failed the pairing will show up as 'unknown' with the same ? icon. These should be removed from the network to be paired again. Please refer to the documentation linked above for more details.
|
|
70
80
|
|
|
71
|
-
|
|
72
|
-

|
|
81
|
+
## Advanced options
|
|
73
82
|
|
|
83
|
+
### Groups
|
|
74
84
|
|
|
75
|
-
|
|
85
|
+
The adapter allows for the creation of groups via the 'add group' button. Once a group has been formed, devices can be added to and removed from the group from the device card. Removal is also possible from the group card.
|
|
86
|
+
Groups have the advantage that a single command is sent to control all group members. This is especially helpful when changing the groups brightness and/or color settings.
|
|
87
|
+
Note that not all devices may be added to groups - the device itself needs to support this feature.
|
|
76
88
|
|
|
77
|
-
|
|
89
|
+
Group configuration is available from the device grid.
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
To connect Zigbee devices in most cases, just press the pairing button on the device itself. But there are features for some devices. More information about pairing with devices can be found [here (in English)](https://www.zigbee2mqtt.io/getting_started/pairing_devices.html)
|
|
91
|
+
### Bindings
|
|
81
92
|
|
|
82
|
-
|
|
93
|
+
Bindings can be used to link a remote control directly to a device, like it is e.g. done for the ikea devices. This binding has the advantage that bound devices will continue to work together even if the Zigbee Coordinator is unavailable.
|
|
94
|
+
Note that not all devices may be part of a binding - the devices themselves need to support this feature.
|
|
83
95
|
|
|
84
|
-
The
|
|
96
|
+
The binding configuration is only available from the zigbee tab
|
|
85
97
|
|
|
86
|
-
###
|
|
87
|
-
You may create groups of devices.
|
|
98
|
+
### Network Map
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
The adapter has the ability to generate a map of the mesh network. This usually takes a few minutes and provides a momentary glimpse into how the devices are meshed with each other.
|
|
90
101
|
|
|
91
|
-
|
|
102
|
+
The network map is only available the zigbee tab.
|
|
92
103
|
|
|
93
|
-
|
|
104
|
+
### Debug information
|
|
94
105
|
|
|
95
|
-
|
|
106
|
+
The Adapter offers to collect debug information for specific devices in order to identify problems in device operation and integration. This needs to be enabled on the desired devices from the device grid.
|
|
96
107
|
|
|
108
|
+
The debug information is only available from the zigbee tab.
|
|
97
109
|
|
|
98
|
-
###
|
|
110
|
+
### Local overrides
|
|
99
111
|
|
|
100
|
-
|
|
112
|
+
Device integration can be modified on a *per Model* basis, allowing the user to customise the states associated with the device. Note that before version 2.1.0, this is limited to choosing between the default *expose based* integration and the previous *legacy* integration. More options for customisation are under development.
|
|
113
|
+
|
|
114
|
+
The local overrides are only available from the instance configuration
|
|
115
|
+
|
|
116
|
+
### Developer Mode
|
|
117
|
+
|
|
118
|
+
The developer mode offers the ability to communicate with any paired device solely based on the details of the Zigbee communication rules. Use of this requires an insight into Zigbee Clusters, Attributes and messaging structure. It can be used to control devices which are not currently supported. An in depth desctiption of the developer Tab is available in the documentation.
|
|
119
|
+
|
|
120
|
+
The developer tab is only available from the instance configuration
|
|
101
121
|
|
|
102
|
-
### Developer Tab
|
|
103
122
|
|
|
104
|
-
This is a tool for advanced users to test currently unsupported devices or enhance this adapter's functionality. More instructions can be found on the tab.
|
|
105
|
-

|
|
106
123
|
|
|
107
124
|
## Additional info
|
|
108
125
|
|
|
109
|
-
There is a [friendly project](https://github.com/koenkk/zigbee2mqtt) with similar functionality on the same
|
|
126
|
+
There is a [friendly project](https://github.com/koenkk/zigbee2mqtt) with similar functionality which is based on the same technology. It uses the same base libraries for hardware communication and device integration. Any device listed as compatible in this project is likely to be compatible with the ioBroker.zigbee Adapter. Note that there is a delay between device integration into zigbee2mqtt.io and the Zigbee-Adapter, as compatibility with the hardware libraries requires verification before the adapter can move to the latest version.
|
|
110
127
|
|
|
111
128
|
There are knowledge bases that can be useful for working with Zigbee-devices and equipment:
|
|
112
|
-
* in English https://www.zigbee2mqtt.io/
|
|
129
|
+
* in English https://www.zigbee2mqtt.io/ or https://zigbee.blakadder.com
|
|
113
130
|
* in Russian https://myzigbee.ru/
|
|
114
131
|
|
|
115
132
|
## Supported devices
|
|
116
133
|
|
|
117
|
-
|
|
134
|
+
Pleae refer to [this list](https://www.zigbee2mqtt.io/supported-devices/) to check compatibility. Once a device is listed as compatible there, it is either already compatible with the Zigbee Adapter or can be made compatible using an external converter.
|
|
118
135
|
|
|
119
|
-
|
|
120
|
-
## More Information
|
|
136
|
+
## In Depth Documentation
|
|
121
137
|
|
|
122
138
|
[in Deutsch](https://github.com/ioBroker/ioBroker.zigbee/blob/master/docs/de/readme.md)
|
|
123
139
|
|
|
@@ -136,33 +152,44 @@ You can thank the authors by these links:
|
|
|
136
152
|
|
|
137
153
|
-----------------------------------------------------------------------------------------------------
|
|
138
154
|
## Changelog
|
|
155
|
+
### 2.0.5 (2025-03-25)
|
|
156
|
+
* (asgothian) ZHC 23.6.0
|
|
157
|
+
* (asgothian) ZH 3.3.x
|
|
158
|
+
* (asgothian) removed extra logging
|
|
159
|
+
* (asgothian) fixed memory issue.
|
|
160
|
+
* (asgothian) Configure on Message - 5 attempts.
|
|
161
|
+
* (arteck) update transmitPower
|
|
162
|
+
* (asgothian) fix crash in ZigbeeController.ByteArrayToString
|
|
163
|
+
* (AlexHaxe) device designation for devices without mapped model (allows use in groups and bindings)
|
|
164
|
+
*
|
|
165
|
+
|
|
139
166
|
### 2.0.4 (2025-03-09)
|
|
140
|
-
* back to 2.0.2
|
|
167
|
+
* (arteck) back to 2.0.2
|
|
141
168
|
|
|
142
169
|
### 2.0.3 (2025-03-07)
|
|
143
|
-
* fix configured info
|
|
144
|
-
* fix battery voltage (V -> mV)
|
|
145
|
-
* enable debug interface v1.0
|
|
146
|
-
* Push Zigbee-Herdsman to
|
|
147
|
-
* Push Zigbee-Herdsman-Converters to 23.1.1
|
|
148
|
-
* fix configure on message
|
|
149
|
-
* remove extra warning messages
|
|
150
|
-
* fix Adapter-Checker notes
|
|
151
|
-
* improve base64 image detection
|
|
152
|
-
* removed unused adaptert objects (info.groups, excludes) from adapter config
|
|
170
|
+
* (asgothian) fix configured info
|
|
171
|
+
* (asgothian) fix battery voltage (V -> mV)
|
|
172
|
+
* (asgothian) enable debug interface v1.0
|
|
173
|
+
* (asgothian) Push Zigbee-Herdsman to 2.5.7
|
|
174
|
+
* (asgothian) Push Zigbee-Herdsman-Converters to 23.1.1
|
|
175
|
+
* (asgothian) fix configure on message
|
|
176
|
+
* (asgothian) remove extra warning messages
|
|
177
|
+
* (asgothian) fix Adapter-Checker notes
|
|
178
|
+
* (asgothian) improve base64 image detection
|
|
179
|
+
* (asgothian) removed unused adaptert objects (info.groups, excludes) from adapter config
|
|
153
180
|
*
|
|
154
181
|
|
|
155
182
|
### 2.0.2 (2025-03-02)
|
|
156
|
-
*
|
|
157
|
-
* fix failure to configure for devices needing multiple configurations (Issue #2375)
|
|
158
|
-
* fix hold/release and press/release action handling (Issue #2387)
|
|
159
|
-
* fix lib/legacy requirement for external converters (Issue #2376)
|
|
160
|
-
* improved external converter handling
|
|
161
|
-
* fix OTA bug
|
|
162
|
-
* improved message handling for devices which report values outside their defined ranges
|
|
163
|
-
* preparation for ZHC 22.x (model definition loaded on demand
|
|
164
|
-
* fix legacy definition for devices
|
|
165
|
-
* added action state for remotes.
|
|
183
|
+
* (asgothian) expose generation with expose function requiring a device. (Issue #1842)
|
|
184
|
+
* (asgothian) fix failure to configure for devices needing multiple configurations (Issue #2375)
|
|
185
|
+
* (asgothian) fix hold/release and press/release action handling (Issue #2387)
|
|
186
|
+
* (asgothian) fix lib/legacy requirement for external converters (Issue #2376)
|
|
187
|
+
* (asgothian) improved external converter handling
|
|
188
|
+
* (asgothian) fix OTA bug
|
|
189
|
+
* (asgothian) improved message handling for devices which report values outside their defined ranges
|
|
190
|
+
* (asgothian) preparation for ZHC 22.x (model definition loaded on demand
|
|
191
|
+
* (asgothian) fix legacy definition for devices
|
|
192
|
+
* (asgothian) added action state for remotes.
|
|
166
193
|
*
|
|
167
194
|
|
|
168
195
|
### 2.0.1 (2025-02-25)
|
package/admin/admin.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/*global $, M, _, sendTo, systemLang, translateWord, translateAll, showMessage, socket, document, instance, vis, Option*/
|
|
2
|
-
|
|
3
2
|
/*
|
|
4
3
|
* you must run 'iobroker upload zigbee' if you edited this file to make changes visible
|
|
5
4
|
*/
|
|
@@ -31,7 +30,11 @@ let devices = [],
|
|
|
31
30
|
},
|
|
32
31
|
cidList,
|
|
33
32
|
shuffleInstance,
|
|
34
|
-
errorData = []
|
|
33
|
+
errorData = [],
|
|
34
|
+
debugMessages = {},
|
|
35
|
+
debugInLog = true;
|
|
36
|
+
const dbgMsgfilter = new Set();
|
|
37
|
+
const dbgMsghide = new Set();
|
|
35
38
|
const updateCardInterval = setInterval(updateCardTimer, 6000);
|
|
36
39
|
|
|
37
40
|
const networkOptions = {
|
|
@@ -240,7 +243,6 @@ function getCard(dev) {
|
|
|
240
243
|
rooms.push(dev.rooms[r]);
|
|
241
244
|
}
|
|
242
245
|
}
|
|
243
|
-
console.warn('debug for ' + ieee + ' is ' + isDebug);
|
|
244
246
|
const room = rooms.join(',') || ' ';
|
|
245
247
|
const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
|
|
246
248
|
const rid = id.split('.').join('_');
|
|
@@ -400,7 +402,7 @@ function EndPointIDfromEndPoint(ep) {
|
|
|
400
402
|
}
|
|
401
403
|
|
|
402
404
|
function editName(id, name) {
|
|
403
|
-
console.
|
|
405
|
+
console.warn('editName called with ' + id + ' and ' + name);
|
|
404
406
|
const dev = devices.find((d) => d._id == id);
|
|
405
407
|
$('#modaledit').find('input[id=\'d_name\']').val(name);
|
|
406
408
|
const groupables = [];
|
|
@@ -830,7 +832,6 @@ async function selectImageOverride(id) {
|
|
|
830
832
|
sendTo(namespace, 'getLocalImages', {}, function(msg) {
|
|
831
833
|
if (msg && msg.imageData) {
|
|
832
834
|
const imagedata = msg.imageData;
|
|
833
|
-
console.warn(JSON.stringify(dev.common));
|
|
834
835
|
const default_icon = (dev.common.type === 'group' ? dev.common.modelIcon : `img/${dev.common.type.replace(/\//g, '-')}.png`);
|
|
835
836
|
if (dev.legacyIcon) imagedata.unshift( { file:dev.legacyIcon, name:'legacy', data:dev.legacyIcon});
|
|
836
837
|
imagedata.unshift( { file:'none', name:'default', data:default_icon});
|
|
@@ -844,10 +845,10 @@ async function selectImageOverride(id) {
|
|
|
844
845
|
return image.file;
|
|
845
846
|
},
|
|
846
847
|
function (key, image) {
|
|
847
|
-
if (image.
|
|
848
|
-
return `data-icon="${image.data}"`;
|
|
849
|
-
} else {
|
|
848
|
+
if (image.isBase64) {
|
|
850
849
|
return `data-icon="data:image/png; base64, ${image.data}"`;
|
|
850
|
+
} else {
|
|
851
|
+
return `data-icon="${image.data}"`;
|
|
851
852
|
}
|
|
852
853
|
},
|
|
853
854
|
);
|
|
@@ -857,7 +858,6 @@ async function selectImageOverride(id) {
|
|
|
857
858
|
const image = $('#chooseimage').find('#images option:selected').val();
|
|
858
859
|
const global = $('#chooseimage').find('#globaloverride').prop('checked');
|
|
859
860
|
const name = $('#chooseimage').find('input[id=\'d_name\']').val();
|
|
860
|
-
console.warn(`update device image : ${id} : ${image} : ${global} : ${name} : ${dev.common.name}`);
|
|
861
861
|
const data = {};
|
|
862
862
|
if (image != 'current') data.icon= image;
|
|
863
863
|
if (name != dev.common.name) data.name = name;
|
|
@@ -869,6 +869,202 @@ async function selectImageOverride(id) {
|
|
|
869
869
|
});
|
|
870
870
|
}
|
|
871
871
|
|
|
872
|
+
|
|
873
|
+
function safestring(val) {
|
|
874
|
+
const t = typeof val;
|
|
875
|
+
if (t==='object') return JSON.stringify(val).replaceAll(',',', ');
|
|
876
|
+
if (t==='string') return val.replaceAll(',',', ');
|
|
877
|
+
if (t==='function') return 'function';
|
|
878
|
+
return val;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
function fne(item) {
|
|
882
|
+
const rv = [];
|
|
883
|
+
if (item.flags) {
|
|
884
|
+
if (item.flags.includes('SUCCESS')) rv.push('SUCCESS');
|
|
885
|
+
else rv.push(...item.flags);
|
|
886
|
+
}
|
|
887
|
+
if (item.errors && item.errors.length > 0) {
|
|
888
|
+
if (item.errors.length > 1) rv.push('errors: '+item.errors.join(','));
|
|
889
|
+
else rv.push('error: '+item.errors[0]);
|
|
890
|
+
}
|
|
891
|
+
return rv.join(', ');
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
function HtmlFromInDebugMessages(messages, devID, filter) {
|
|
895
|
+
const Html = [];
|
|
896
|
+
const filterSet = new Set();
|
|
897
|
+
let isodd = true;
|
|
898
|
+
if (dbgMsghide.has('i_'+devID)) {
|
|
899
|
+
console.warn('in all filtered out')
|
|
900
|
+
Html.push(' ')
|
|
901
|
+
} else for (const item of messages) {
|
|
902
|
+
if (item.states.length > 0) {
|
|
903
|
+
const rowspan = item.states.length > 1 ? ` rowspan="${item.states.length}"` : '';
|
|
904
|
+
let idx = item.states.length;
|
|
905
|
+
const IHtml = [];
|
|
906
|
+
let fs = '';
|
|
907
|
+
for (const state of item.states) {
|
|
908
|
+
fs = fs+state.id+'.'+fne(item);
|
|
909
|
+
const redText = (item.errors && item.errors.length > 0 ? ' id="dbgred"' : '');
|
|
910
|
+
idx--;
|
|
911
|
+
const LHtml = [(`<tr id="${isodd ? 'dbgrowodd' : 'dbgroweven'}">`)];
|
|
912
|
+
if (idx==0)
|
|
913
|
+
LHtml.push(`<td${rowspan}>${item.dataID.toString(16).slice(-4)}</td><td${rowspan}>${safestring(item.payload)}</td>`);
|
|
914
|
+
LHtml.push(`<td></td><td${redText}>${safestring(state.payload)}</td><td${redText}>${state.id}</td><td${redText}>${state.value}</td><td${redText}>${fne(item)}</td></tr>`);
|
|
915
|
+
IHtml.unshift(...LHtml)
|
|
916
|
+
}
|
|
917
|
+
if (filter)
|
|
918
|
+
if (filterSet.has(fs)) continue; else filterSet.add(fs);
|
|
919
|
+
Html.unshift(...IHtml);
|
|
920
|
+
isodd=!isodd;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
const ifbutton = `<a id="i_${devID}" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsgfilter.has('i_'+devID) ? 'filter_list' : 'format_align_justify' }</i></a>`
|
|
924
|
+
const ofbutton = `<a id="hi_${devID}" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsghide.has('i_'+devID) ? 'unfold_more' : 'unfold_less' }</i></a>`
|
|
925
|
+
const dataHide = dbgMsgfilter.has('hi_'+devID) ? 'Data hidden' : ' ';
|
|
926
|
+
return `<thead id="dbgtable"><tr><td> </td><td>Incoming messages</td><td> </td><td> </td><td>${dataHide}</td><td>${ifbutton}</td><td>${ofbutton}</td></tr><tr><td>ID</td><td>Zigbee Payload</td><td> </td><td>State Payload</td><td>ID</td><td>value</td><td>Flags</td></tr></thead><tbody>${Html.join('')}</tbody>`;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
function HtmlFromOutDebugMessages(messages, devID, filter) {
|
|
931
|
+
const Html = [];
|
|
932
|
+
const filterSet = new Set();
|
|
933
|
+
let isodd=true;
|
|
934
|
+
if (dbgMsghide.has('o_'+devID)) {
|
|
935
|
+
console.warn('out all filtered out')
|
|
936
|
+
Html.push(' ')
|
|
937
|
+
}
|
|
938
|
+
else for (const item of messages) {
|
|
939
|
+
if (item.states.length > 0) {
|
|
940
|
+
const rowspan = item.states.length > 1 ? ` rowspan="${item.states.length}"` : '';
|
|
941
|
+
let idx = item.states.length;
|
|
942
|
+
let fs = '';
|
|
943
|
+
const IHtml = [];
|
|
944
|
+
for (const state of item.states) {
|
|
945
|
+
fs = fs+state.id+'.'+fne(item);
|
|
946
|
+
const redText = (item.errors && item.errors.length > 0 ? ' id="dbgred"' : '');
|
|
947
|
+
const LHtml = [(`<tr id="${isodd ? 'dbgrowodd' : 'dbgroweven'}">`)];
|
|
948
|
+
idx--;
|
|
949
|
+
if (idx==0)
|
|
950
|
+
LHtml.push(`<td${rowspan}>${item.dataID.toString(16).slice(-4)}</td><td${rowspan}>${safestring(item.payload)}</td>`);
|
|
951
|
+
LHtml.push(`<td${redText}>${state.ep ? state.ep : ''}</td><td${redText}>${state.id}</td><td${redText}>${safestring(state.value)}</td><td${redText}>${safestring(state.payload)}</td><td${redText}>${fne(item)}</td></tr>`);
|
|
952
|
+
IHtml.unshift(...LHtml);
|
|
953
|
+
|
|
954
|
+
}
|
|
955
|
+
if (filter)
|
|
956
|
+
if (filterSet.has(fs)) continue; else filterSet.add(fs);
|
|
957
|
+
Html.unshift(...IHtml);
|
|
958
|
+
isodd=!isodd;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
const ifbutton = `<a id="o_${devID}" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsgfilter.has('o_'+devID) ? 'filter_list' : 'format_align_justify' }</i></a>`
|
|
962
|
+
const ofbutton = `<a id="ho_${devID}" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsghide.has('o_'+devID) ? 'unfold_more' : 'unfold_less'}</i></a>`
|
|
963
|
+
const dataHide = dbgMsgfilter.has('ho_'+devID) ? 'Data hidden' : ' ';
|
|
964
|
+
return `<thead id="dbgtable"><tr><td> </td><td>Outgoing messages</td><td> </td><td> </td><td>${dataHide}</td><td>${ifbutton}</td><td>${ofbutton}</td></tr><tr><td>ID</td><td>Zigbee Payload</td><td>EP</td><td>ID</td><td>value</td><td>State Payload</td><td>Flags</td></tr></thead><tbody>${Html.join('')}</tbody>`;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
function displayDebugMessages(msg) {
|
|
969
|
+
const buttonNames = [];
|
|
970
|
+
if (msg.byId) {
|
|
971
|
+
const dbgData = msg.byId;
|
|
972
|
+
const keys = Object.keys(dbgData);
|
|
973
|
+
const keylength = keys.length;
|
|
974
|
+
const Html = [];
|
|
975
|
+
const button = `<a id="e_all" class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">sync_problem</i></a>`;
|
|
976
|
+
const fbutton = `<a id="f_all" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsgfilter.size != 0 ? 'filter_list' : 'format_align_justify' }</i></a>`;
|
|
977
|
+
const hbutton = `<a id="h_all" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsghide.size != 0 ? 'unfold_more' : 'unfold_less'}</i></a>`;
|
|
978
|
+
const logbutton = `<a id="l_all" class="btn-floating waves-effect waves-light ${debugInLog ? 'green' : 'red'} tooltipped center-align hoverable translateT" title="Log messages"><i class="material-icons large">${debugInLog ? 'speaker_notes' : 'speaker_notes_off'}</i></a>`;
|
|
979
|
+
Html.push(`<li><table><thead id="dbgtable"><tr><td>${logbutton}</td><td colspan="3">Debug information by device</td><td>${fbutton}</td><td>${hbutton}</td><td>${button}</td></tr></thead><tbody>`);
|
|
980
|
+
if (!keylength) {
|
|
981
|
+
Html.push('<tr><td></td><td>No debug data loaded - press reload to refresh</td><td></td><td> </td><td> </td><td> </td><td> </td><td> </td></tr></tbody></table></li>')
|
|
982
|
+
$('#dbg_data_list').html(Html.join(''));
|
|
983
|
+
}
|
|
984
|
+
else {
|
|
985
|
+
Html.push('</tbody></table></li>')
|
|
986
|
+
for (const devID of Object.keys(dbgData)) {
|
|
987
|
+
const dev = devices.find((d) => d._id.endsWith(devID.slice(-16)));
|
|
988
|
+
const type_url = (dev && dev.common && dev.common.type ? sanitizeModelParameter(dev.common.type) : 'unknown');
|
|
989
|
+
const image = `<img src="${dev.common.icon || dev.icon}" width="40px" onerror="this.onerror=null;this.src='img/unavailable.png';">`
|
|
990
|
+
const modelUrl = (type_url === 'unknown') ? 'unknown' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${image}</a>`;
|
|
991
|
+
const devName = (dev && dev.common && dev.common.name) ? dev.common.name : 'unnamed';
|
|
992
|
+
const button = `<a id="e_${devID}" class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">sync_problem</i></a>`
|
|
993
|
+
buttonNames.push(devID);
|
|
994
|
+
Html.push(`<li><table><thead id="dbgtable"><tr><td colspan="4">${devName} (ID: ${devID} Model: ${dev && dev.common ? dev.common.name : 'unknown'})</td><td>${modelUrl}</td><td> </td><td>${button}</td></tr></thead><tbody>`);
|
|
995
|
+
if (dbgData[devID].IN.length > 0) {
|
|
996
|
+
Html.push(`${HtmlFromInDebugMessages(dbgData[devID].IN, devID, dbgMsgfilter.has('i_'+devID))}`);
|
|
997
|
+
}
|
|
998
|
+
if (dbgData[devID].OUT.length > 0) {
|
|
999
|
+
Html.push(`${HtmlFromOutDebugMessages(dbgData[devID].OUT, devID, dbgMsgfilter.has('o_'+devID))}`);
|
|
1000
|
+
}
|
|
1001
|
+
Html.push('</tbody></table></li>');
|
|
1002
|
+
}
|
|
1003
|
+
$('#dbg_data_list').html(Html.join(''));
|
|
1004
|
+
}
|
|
1005
|
+
$(`#e_all`).click(function () {
|
|
1006
|
+
getDebugMessages();
|
|
1007
|
+
});
|
|
1008
|
+
$(`#l_all`).click(function () {
|
|
1009
|
+
debugInLog = !debugInLog;
|
|
1010
|
+
getDebugMessages();
|
|
1011
|
+
});
|
|
1012
|
+
$(`#f_all`).click(function () {
|
|
1013
|
+
if (dbgMsgfilter.size > 0) {
|
|
1014
|
+
dbgMsgfilter.clear();
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
for (const item of Object.keys(msg.byId)) {
|
|
1018
|
+
dbgMsgfilter.add(`o_${item}`)
|
|
1019
|
+
dbgMsgfilter.add(`i_${item}`)
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
displayDebugMessages(debugMessages);
|
|
1023
|
+
});
|
|
1024
|
+
$(`#h_all`).click(function () {
|
|
1025
|
+
if (dbgMsghide.size > 0) {
|
|
1026
|
+
dbgMsghide.clear();
|
|
1027
|
+
}
|
|
1028
|
+
else {
|
|
1029
|
+
for (const item of Object.keys(msg.byId)) {
|
|
1030
|
+
dbgMsghide.add(`o_${item}`)
|
|
1031
|
+
dbgMsghide.add(`i_${item}`)
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
displayDebugMessages(debugMessages);
|
|
1035
|
+
});
|
|
1036
|
+
for (const b of buttonNames) {
|
|
1037
|
+
$(`#e_${b}`).click(function () {
|
|
1038
|
+
getDebugMessages();
|
|
1039
|
+
});
|
|
1040
|
+
$(`#o_${b}`).click(function () {
|
|
1041
|
+
if (dbgMsgfilter.has(`o_${b}`)) dbgMsgfilter.delete(`o_${b}`); else dbgMsgfilter.add(`o_${b}`);
|
|
1042
|
+
displayDebugMessages(debugMessages);
|
|
1043
|
+
});
|
|
1044
|
+
$(`#i_${b}`).click(function () {
|
|
1045
|
+
if (dbgMsgfilter.has(`i_${b}`)) dbgMsgfilter.delete(`i_${b}`); else dbgMsgfilter.add(`i_${b}`);
|
|
1046
|
+
displayDebugMessages(debugMessages);
|
|
1047
|
+
});
|
|
1048
|
+
$(`#ho_${b}`).click(function () {
|
|
1049
|
+
if (dbgMsghide.has(`o_${b}`)) dbgMsghide.delete(`o_${b}`); else dbgMsghide.add(`o_${b}`);
|
|
1050
|
+
displayDebugMessages(debugMessages);
|
|
1051
|
+
});
|
|
1052
|
+
$(`#hi_${b}`).click(function () {
|
|
1053
|
+
if (dbgMsghide.has(`i_${b}`)) dbgMsghide.delete(`i_${b}`); else dbgMsghide.add(`i_${b}`);
|
|
1054
|
+
displayDebugMessages(debugMessages);
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
function getDebugMessages() {
|
|
1061
|
+
sendTo(namespace, 'getDebugMessages', { inlog: debugInLog }, function(msg) {
|
|
1062
|
+
debugMessages = msg;
|
|
1063
|
+
if (msg) displayDebugMessages(debugMessages)
|
|
1064
|
+
})
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
|
|
872
1068
|
function getDevices() {
|
|
873
1069
|
getCoordinatorInfo();
|
|
874
1070
|
sendTo(namespace, 'getDeviceCleanupRequired', {}, function(msg) {
|
|
@@ -899,6 +1095,7 @@ function getDevices() {
|
|
|
899
1095
|
} else {
|
|
900
1096
|
devices = msg;
|
|
901
1097
|
showDevices();
|
|
1098
|
+
getDebugMessages();
|
|
902
1099
|
getExclude();
|
|
903
1100
|
getBinding();
|
|
904
1101
|
}
|
|
@@ -1009,6 +1206,7 @@ function load(settings, onChange) {
|
|
|
1009
1206
|
//dialog = new MatDialog({EndingTop: '50%'});
|
|
1010
1207
|
getDevices();
|
|
1011
1208
|
getNamedColors();
|
|
1209
|
+
//getDebugMessages();
|
|
1012
1210
|
//getMap();
|
|
1013
1211
|
//addCard();
|
|
1014
1212
|
|
|
@@ -1200,8 +1398,13 @@ socket.on('stateChange', function (id, state) {
|
|
|
1200
1398
|
$('#progress_line').css('width', `${percent}%`);
|
|
1201
1399
|
}
|
|
1202
1400
|
} else if (id.match(/\.info\.pairingMessage$/)) {
|
|
1203
|
-
|
|
1204
|
-
|
|
1401
|
+
if (state.val == 'NewDebugMessage') {
|
|
1402
|
+
getDebugMessages();
|
|
1403
|
+
}
|
|
1404
|
+
else {
|
|
1405
|
+
messages.push(state.val);
|
|
1406
|
+
showMessages();
|
|
1407
|
+
}
|
|
1205
1408
|
} else {
|
|
1206
1409
|
const devId = getDevId(id);
|
|
1207
1410
|
putEventToNode(devId);
|
|
@@ -1226,6 +1429,7 @@ socket.on('stateChange', function (id, state) {
|
|
|
1226
1429
|
}
|
|
1227
1430
|
});
|
|
1228
1431
|
|
|
1432
|
+
|
|
1229
1433
|
socket.on('objectChange', function (id, obj) {
|
|
1230
1434
|
if (id.substring(0, namespaceLen) !== namespace) return;
|
|
1231
1435
|
//console.log('objectChange', id, obj);
|
|
@@ -1486,7 +1690,6 @@ function showNetworkMap(devices, map) {
|
|
|
1486
1690
|
const options = data.edges._data.get(id);
|
|
1487
1691
|
if (select) {
|
|
1488
1692
|
options.font.size = 15;
|
|
1489
|
-
console.warn(JSON.stringify(options.font));
|
|
1490
1693
|
} else {
|
|
1491
1694
|
options.font.size = 0;
|
|
1492
1695
|
}
|
|
@@ -2065,7 +2268,6 @@ function editGroup(id, name) {
|
|
|
2065
2268
|
removeMembers.push({id:member.ieee.replace('0x',''), ep:member.epid})
|
|
2066
2269
|
}
|
|
2067
2270
|
}
|
|
2068
|
-
console.warn(`ID: ${Id} name: ${newName} removeMembers: ${JSON.stringify(removeMembers)}`)
|
|
2069
2271
|
updateGroup(Id, newName, (removeMembers.length > 0 ? removeMembers: undefined));
|
|
2070
2272
|
// showGroups();
|
|
2071
2273
|
getDevices();
|
|
@@ -2625,7 +2827,7 @@ function genDevInfo(device) {
|
|
|
2625
2827
|
${genRow('date code', dev._dateCode)}
|
|
2626
2828
|
${genRow('build', dev._softwareBuildID)}
|
|
2627
2829
|
${genRow('interviewed', dev._interviewCompleted)}
|
|
2628
|
-
${genRow('configured', (
|
|
2830
|
+
${genRow('configured', (device.isConfigured), true)}
|
|
2629
2831
|
</ul>
|
|
2630
2832
|
</div>
|
|
2631
2833
|
</div>
|
|
@@ -2817,16 +3019,12 @@ function addExcludeDialog() {
|
|
|
2817
3019
|
$('#excludemodaledit a.btn[name=\'save\']').unbind('click');
|
|
2818
3020
|
$('#excludemodaledit a.btn[name=\'save\']').click(() => {
|
|
2819
3021
|
const exclude_id = $('#excludemodaledit').find('#exclude_target option:selected').val();
|
|
2820
|
-
|
|
2821
3022
|
const ids = devices.map(el => el._id);
|
|
2822
3023
|
const idx = ids.indexOf(exclude_id);
|
|
2823
3024
|
const exclude_model = devices[idx];
|
|
2824
|
-
console.warn('calling addExclude mit model ' + exclude_model)
|
|
2825
|
-
|
|
2826
3025
|
addExclude(exclude_model);
|
|
2827
3026
|
});
|
|
2828
3027
|
prepareExcludeDialog();
|
|
2829
|
-
console.warn('opening dialog');
|
|
2830
3028
|
$('#excludemodaledit').modal('open');
|
|
2831
3029
|
Materialize.updateTextFields();
|
|
2832
3030
|
}
|
|
@@ -2855,7 +3053,7 @@ function getExclude() {
|
|
|
2855
3053
|
excludes = msg.legacy;
|
|
2856
3054
|
showExclude();
|
|
2857
3055
|
}
|
|
2858
|
-
}
|
|
3056
|
+
}
|
|
2859
3057
|
});
|
|
2860
3058
|
}
|
|
2861
3059
|
|
|
File without changes
|
package/admin/tab_m.html
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css"/> -->
|
|
11
11
|
<script type="text/javascript" src="vis-network.min.js"></script>
|
|
12
|
-
<script type="text/javascript" src="webcolors.js"></script>
|
|
13
12
|
<link rel="stylesheet" type="text/css" href="vis-network.min.css"/>
|
|
14
13
|
|
|
15
14
|
<!-- these files always have to be included -->
|
|
@@ -231,16 +230,18 @@
|
|
|
231
230
|
color: blue;
|
|
232
231
|
}
|
|
233
232
|
.m.react-blue div.bg_red {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
.m div.bg_red {
|
|
238
|
-
background-color: LightGray;
|
|
239
|
-
color: DimGray;
|
|
233
|
+
background-color: #400000;
|
|
234
|
+
color: DimGray;
|
|
240
235
|
}
|
|
241
236
|
.m.react-dark div.bg_red {
|
|
242
|
-
|
|
237
|
+
background-color: #400000;
|
|
238
|
+
color: DimGray;
|
|
243
239
|
}
|
|
240
|
+
#dbgroweven { background-color: #404040; color: #c0c0c0 !important; }
|
|
241
|
+
#dbgrowodd { background-color: #c0c0c0; color: #404040 !important; }
|
|
242
|
+
#dbgtable { background-color: #3090c0; color: #404040 !important; }
|
|
243
|
+
#dbgred { color: #C00000 !important;}
|
|
244
|
+
|
|
244
245
|
.m.react-dark i.icon-blue {
|
|
245
246
|
color: rgb(100, 181, 246)!important;
|
|
246
247
|
}
|
|
@@ -911,6 +912,10 @@
|
|
|
911
912
|
<div id="exclude" class="row">
|
|
912
913
|
</div>
|
|
913
914
|
</div>
|
|
915
|
+
<div id="tab-debug" class="col s12 page">
|
|
916
|
+
<ul id="dbg_data_list">
|
|
917
|
+
</ul>
|
|
918
|
+
</div>
|
|
914
919
|
</div>
|
|
915
920
|
</div>
|
|
916
921
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|