iobroker.zigbee 1.10.2 → 1.10.11

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 CHANGED
@@ -11,7 +11,11 @@
11
11
 
12
12
  ## ioBroker adapter for Zigbee devices via TI cc2531/cc2530/cc26x2r/cc2538 and deCONZ ConBee/RaspBee.
13
13
 
14
- With the Zigbee-coordinator based on Texas Instruments SoC, deCONZ ConBee/RaspBee modules, Silicon Labs EZSP v8 or ZIGate USB-TTL it creates its own zigbee-network, into which zigbee-devices are connected. By work 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).
14
+ With the Zigbee-coordinator based on Texas Instruments SoC, deCONZ ConBee/RaspBee modules, Silicon Labs EZSP v8 or ZIGate USB-TTL it creates its own zigbee-network, into which zigbee-devices are connected.
15
+
16
+
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).
15
19
 
16
20
  ## Hardware
17
21
 
@@ -50,32 +54,32 @@ While Conbee/RaspBee Support is no longer considered experimental in the zigbee-
50
54
 
51
55
  ### Silicon Labs SoC
52
56
 
53
- Support for [Silicon Lab Zigbee](https://www.silabs.com/wireless/zigbee) based adapters is experimental. The initial support for EZSP v8 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/319) with regards to the state of Silabs EmberZNet Serial Protocol (EZSP) adapter implementation integration into the zigbee-herdsman and zigbee-herdsman-converters libraries which it depends on.
57
+ Support for [Silicon Lab Zigbee](https://www.silabs.com/wireless/zigbee) based adapters is experimental. The initial support for EZSP v8 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/319) with regards to the state of Silabs EmberZNet Serial Protocol (EZSP) adapter implementation integration into the zigbee-herdsman and zigbee-herdsman-converters libraries which it depends on.
54
58
 
55
59
 
56
60
  ### ZiGate SoC
57
61
 
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.
62
+ 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.
59
63
 
60
64
 
61
65
  ## Work with adapter
62
66
 
63
67
  ![](docs/tutorial/zigbee.png)
64
68
 
65
- To start the driver, you must specify the name of the port on which the Zigbee-module (stick) is connected. Usually this is the port `/dev/ttyACM0` or `/dev/ttyUSB0` for the UART-connection. Or you can find with `ls -l /dev/serial/by-id` the device direct.
69
+ To start the driver, you must specify the name of the port on which the Zigbee module (stick) is connected. Usually this is the port `/dev/ttyACM0` or `/dev/ttyUSB0` for the UART-connection. Or you can find with `ls -l /dev/serial/by-id` the device direct.
66
70
 
67
71
  open the settings and change port
68
72
  ![](docs/tutorial/settings.png)
69
73
 
70
74
 
71
- For Windows this will be the COM port number.
75
+ For Windows, this will be the COM port number.
72
76
 
73
- Starting from version 1.0.0 you can also use *tcp connection* for cases using esp8266 (or other microcontrollers) as serial-bridge. For example `tcp://192.168.1.46:8880`. Read more info here https://www.zigbee2mqtt.io/information/connecting_cc2530#via-an-esp8266
77
+ Starting from version 1.0.0, you can also use *tcp connection* for cases using esp8266 (or other microcontrollers) as serial-bridge. For example `tcp://192.168.1.46:8880`. Read more info here https://www.zigbee2mqtt.io/information/connecting_cc2530#via-an-esp8266
74
78
 
75
- To connect devices, you need to switch the Zigbee-coordinator to pairing mode by pressing the green button. The countdown will begin (60 seconds) until the device connectivity is available.
79
+ To connect devices, you need to switch the Zigbee coordinator to pairing mode by pressing the green button. The countdown will begin (60 seconds) until the device connectivity is available.
76
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)
77
81
 
78
- After successful pairing, the device appears in the configuration panel. If the device appears in the configuration panel but has the type "undefined", then this is an unknown device and can not be work with it. If the device is in the list of available devices, but added as "undefined", then try to remove the device and add it again.
82
+ After successful pairing, the device appears in the configuration panel. If the device appears in the configuration panel but has the type "undefined", then this is an unknown device and cannot be worked with it. If the device is in the list of available devices, but added as "undefined", then try to remove the device and add it again.
79
83
 
80
84
  The devices connected to the Zigbee-network and inform the coordinator of their status and events (button presses, motion detection, temperature change). This information is reflected in the ioBroker object-states. Some ioBroker states have feedback and send commands to the zigbee-device when the value changes (switching the state of the outlet or lamp, changing the scene or the brightness of the lamp).
81
85
 
@@ -97,7 +101,7 @@ https://www.zigbee2mqtt.io/information/binding
97
101
 
98
102
  ### Developer Tab
99
103
 
100
- This is a tool for advanced users to test currently unsupported devices or enhance this adapters functionality. More instructions can be found on tab.
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.
101
105
  ![](docs/tutorial/tab-dev-1.png)
102
106
 
103
107
  ## Additional info
@@ -113,7 +117,7 @@ There are knowledge bases that can be useful for working with Zigbee-devices and
113
117
  [Works with devices from this list](https://github.com/ioBroker/ioBroker.zigbee/wiki/Supported-devices)
114
118
 
115
119
 
116
- ## More Informations
120
+ ## More Information
117
121
 
118
122
  [in Deutsch](https://github.com/ioBroker/ioBroker.zigbee/blob/master/docs/de/readme.md)
119
123
 
@@ -128,17 +132,54 @@ or
128
132
  ## Donate
129
133
 
130
134
  You can thank the authors by these links:
131
- * to Kirov Ilya https://www.paypal.me/goofyk
132
135
  * to Arthur Rupp https://paypal.me/ArthurRupp
133
136
 
134
137
  -----------------------------------------------------------------------------------------------------
135
-
136
138
  ## Changelog
139
+ ### 1.10.11 (2024-11-02)
140
+ * BREAKING CHANGE
141
+ *
142
+ * bugs : ChannelScan is currently not available
143
+ *
144
+ *
145
+ * (lebrinkma) fix linter errors
146
+ * (asgothian) disable map display for deactivated devices
147
+ * (asgothian) new option on map: disable physics interaction
148
+ * (asgothian) new zigbee-herdsman-converters 20.28.0
149
+ * (asgothian) new zigbee-herdsman 2.1.1
150
+ * (asgothian) Allow use of keyless converters (used for TuYa and compatible devices in zigbee-herdsman-converters
151
+ * (arteck) swap from request to axios
152
+ * (arteck) delete groups works again
153
+
154
+ ### 1.10.9 (2024-09-05)
155
+ * (arteck) typo admin settings
156
+ * (arteck) eslint config
157
+
158
+ ### 1.10.8 (2024-09-05)
159
+ * (arteck) corr admin settings
160
+ * (arteck) add new eslint version
161
+
162
+ ### 1.10.7 (2024-09-05)
163
+ * (arteck) add flow control option
164
+ * (asgothian) add new NewHerdsman
165
+ * (arteck) add new ezsp coordinator Firmware (7.4.1.0)
166
+
167
+ ### 1.10.5 (2024-06-21)
168
+ * (arteck) icon ota device update
169
+ * (arteck) icon fix
170
+
171
+ ### 1.10.4 (2024-04-20)
172
+ * (arteck) core update
173
+ * (arteck) dependency update
174
+
175
+ ### 1.10.3 (2024-04-06)
176
+ * (arteck) dependency update
177
+
137
178
  ### 1.10.2 (2024-01-25)
138
179
  * (arteck) dependency update
139
180
 
140
181
  ### 1.10.1 (2024-01-21)
141
- * (arteck) Baudrate is now configurable. works ONLY with Deconz/Conbee( 38400 )
182
+ * (arteck) Baudrate is now configurable. works ONLY with Deconz/Conbee(38400)
142
183
  * (arteck) add nvbackup.json delete button
143
184
 
144
185
  ### 1.10.0 (2024-01-13)
@@ -226,17 +267,17 @@ You can thank the authors by these links:
226
267
  * (arteck) new Documentation (thx Stefan)
227
268
 
228
269
  ### 1.8.11 (2022-12-10)
229
- * (arteck) fix compsite exposes with list
270
+ * (arteck) fix compsite exposes with a list
230
271
 
231
272
  ### 1.8.10 (2022-12-12)
232
273
  * (asgothian) fix group access
233
274
  * (asgothian) add option for pairing code:
234
- A new icon allows to open the network after first entering a pairing code
275
+ A new icon allows opening the network after first entering a pairing code
235
276
  listed on the device
236
277
  * (asgothian) easier use of external converters
237
278
  - external converters can now be placed in the zigbee adapter data folder
238
279
  - no absolite path is required to access them
239
- - external converters posted on the github for zigbee-herdsman-converters
280
+ - external converters posted on the GitHub for zigbee-herdsman-converters
240
281
  should work as they are - folders for libraries are rewritten to match
241
282
  the expected location when 'required' from within the zigbee adapter
242
283
  - Log entries will identify which files are entered as converters. Errors
@@ -406,7 +447,7 @@ in this case, the *states* attribute will be formed based on the *exposes* descr
406
447
 
407
448
  ### 1.2.1 (2020-08-16)
408
449
  * Fixes after changing device identify method
409
- * (Garfonso) Allow to unbind from coordinator
450
+ * (Garfonso) Allow unbinding from coordinator
410
451
 
411
452
  ### 1.2.0 (2020-08-09)
412
453
  * Serialport 9.0.0. (zigbee-herdsman)
@@ -422,8 +463,8 @@ Improvements and fixes:
422
463
  * (allofmex) Improved DeveloperTab logs
423
464
  * (allofmex) Add humidity and temperature calibration state to Tuya RH3052
424
465
  * (kirovilya) Fixed a typo due to which extPanID was not set
425
- * (allofmex) Retry reconnect gateway all the time for tcp connected gateway
426
- * (kirovilya) Allow to collect zigbee-herdsman logs to iobroker logs
466
+ * (allofmex) Retry reconnect gateway all the time for TCP-connected gateway
467
+ * (kirovilya) Allow collecting zigbee-herdsman logs to iobroker logs
427
468
  * (kirovilya) Additional states for QBKG12LM
428
469
 
429
470
  New devices:
@@ -481,7 +522,7 @@ new Zigbee-herdsman features:
481
522
  * (kirovilya) Moes Zigbee Thermostatic Radiator
482
523
  * (kirovilya) LifeControl power plug MCLH-03, bulb MCLH-02, water leak MCLH-07, door sensor MCLH-04
483
524
  * (kirovilya) Philips LCT002, LCT011, LTW015, LWG004
484
- * (kirovilya) Gledopto GL-C-007 with with channel
525
+ * (kirovilya) Gledopto GL-C-007 with a channel
485
526
  * (MultivitaminJuice) Iluminize 511.040
486
527
  * (Sacred-Shadow) Bitron 902010/24
487
528
  * (kirovilya) Color indication of LQI and Battery icon
@@ -4,8 +4,8 @@ const parts = path.split('/');
4
4
  parts.splice(-3);
5
5
 
6
6
  const socket = io.connect('/', { path: parts.join('/') + '/socket.io' });
7
- var query = (window.location.search || '').replace(/^\?/, '').replace(/#.*$/, '');
8
- var args = {};
7
+ const query = (window.location.search || '').replace(/^\?/, '').replace(/#.*$/, '');
8
+ const args = {};
9
9
  let theme = null;
10
10
 
11
11
  // parse parameters
@@ -14,7 +14,7 @@ query.trim().split('&').filter(function (t) { return t.trim(); }).forEach(functi
14
14
  if (!i && parts.length === 1 && !isNaN(parseInt(b, 10))) {
15
15
  args.instance = parseInt(b, 10);
16
16
  }
17
- var name = parts[0];
17
+ const name = parts[0];
18
18
  args[name] = parts.length === 2 ? parts[1] : true;
19
19
 
20
20
  if (name === 'instance') {
@@ -28,7 +28,7 @@ query.trim().split('&').filter(function (t) { return t.trim(); }).forEach(functi
28
28
  }
29
29
  });
30
30
 
31
- var instance = args.instance;
31
+ const instance = args.instance;
32
32
 
33
33
  let common = null; // common information of adapter
34
34
  const host = null; // host object on which the adapter runs
@@ -55,7 +55,7 @@ $(document).ready(function () {
55
55
  function loadSystemConfig(callback) {
56
56
  socket.emit('getObject', 'system.config', function (err, res) {
57
57
  if (!err && res && res.common) {
58
- systemLang = res.common.language || systemLang;
58
+ // systemLang = res.common.language || systemLang;
59
59
  systemConfig = res;
60
60
  }
61
61
  socket.emit('getObject', 'system.certificates', function (err, res) {
@@ -96,17 +96,13 @@ function loadSettings(callback) {
96
96
  if (typeof load === 'undefined') {
97
97
  alert('Please implement save function in your admin/index.html');
98
98
  } else {
99
- // detect, that we are now in react container (themeNames = ['dark', 'blue', 'colored', 'light'])
100
-
101
- const _query = query.split('&');
102
-
103
- for (var q = 0; q < _query.length; q++) {
104
- if (_query[q].indexOf('react=') !== -1) {
105
- $('.adapter-container').addClass('react-' + _query[q].substring(6));
106
- theme = 'react-' + _query[q].substring(6);
107
- }
99
+ const _query = query.split('&');
100
+ for (let q = 0; q < _query.length; q++) {
101
+ if (_query[q].indexOf('react=') !== -1) {
102
+ $('.adapter-container').addClass('react-' + _query[q].substring(6));
103
+ theme = 'react-' + _query[q].substring(6);
104
+ }
108
105
  }
109
-
110
106
  load(res.native, onChange);
111
107
  }
112
108
  if (typeof callback === 'function') {
@@ -118,9 +114,101 @@ function loadSettings(callback) {
118
114
  }
119
115
  alert('error loading settings for ' + _adapterInstance + '\n\n' + err);
120
116
  }
117
+ // Design Fix simatec
118
+ checkMediaQuery();
121
119
  });
122
120
  }
123
121
 
122
+ window.addEventListener('resize', checkMediaQuery);
123
+
124
+ function checkMediaQuery() {
125
+ const mediaQuery = window.matchMedia('(max-width: 600px)');
126
+
127
+ if (mediaQuery.matches) {
128
+ designFix();
129
+ console.log('Screen < 600px.');
130
+ } else {
131
+ console.log('Screen > 600px.');
132
+ }
133
+ }
134
+
135
+ // Design Fix simatec
136
+ function designFix() {
137
+ const dropdownToggle = document.querySelector('.dropdown-toggle');
138
+
139
+ if (!dropdownToggle) {
140
+ const cols = document.querySelectorAll('.col:not(.tab)');
141
+ const sClasses = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11'];
142
+
143
+ cols.forEach(col => {
144
+ sClasses.forEach(sClass => {
145
+ if (col.classList.contains(sClass)) {
146
+ col.classList.remove(sClass);
147
+ }
148
+ });
149
+
150
+ col.classList.add('s12');
151
+ });
152
+
153
+ const logo = document.querySelector('.logo');
154
+
155
+ if (logo) {
156
+ const col = logo.closest('.col');
157
+ if (col) {
158
+ const sClasses = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11', 's12', 'm2', 'm4', 'm8', 'm10', 'm12', 'l2', 'l4', 'l8', 'l10', 'l12',];
159
+ sClasses.forEach(sClass => {
160
+ if (col.classList.contains(sClass)) {
161
+ col.classList.remove(sClass);
162
+ }
163
+ });
164
+ col.classList.add('s10');
165
+ col.classList.add('m6');
166
+ col.classList.add('l6');
167
+ }
168
+ }
169
+
170
+ const allTabs = document.querySelectorAll('.tabs');
171
+
172
+ allTabs.forEach(function (tabs) {
173
+ const dropdownToggle = document.createElement('div');
174
+ dropdownToggle.classList.add('dropdown-toggle');
175
+
176
+ const icon = document.createElement('i');
177
+ icon.classList.add('material-icons');
178
+ icon.textContent = 'menu';
179
+ dropdownToggle.appendChild(icon);
180
+
181
+ tabs.insertAdjacentElement('beforebegin', dropdownToggle);
182
+
183
+ const dropdownMenu = document.createElement('div');
184
+ dropdownMenu.classList.add('dropdown-menu');
185
+
186
+ const tabLinks = tabs.querySelectorAll('li a');
187
+
188
+ tabLinks.forEach(function (tab) {
189
+ const dropdownLink = document.createElement('a');
190
+ dropdownLink.href = tab.getAttribute('href');
191
+ dropdownLink.textContent = tab.textContent;
192
+ dropdownMenu.appendChild(dropdownLink);
193
+ dropdownLink.addEventListener('click', function () {
194
+ tab.click();
195
+ dropdownMenu.classList.remove('show');
196
+ });
197
+ });
198
+
199
+ tabs.insertAdjacentElement('beforebegin', dropdownMenu);
200
+
201
+ dropdownToggle.addEventListener('click', function () {
202
+ dropdownMenu.classList.toggle('show');
203
+ });
204
+
205
+ const rect = dropdownToggle.getBoundingClientRect();
206
+ dropdownMenu.style.top = `${rect.bottom}px`;
207
+ dropdownMenu.style.right = '10px';
208
+ });
209
+ }
210
+ }
211
+
124
212
  function prepareTooltips() {
125
213
  $('.admin-icon').each(function () {
126
214
  let id = $(this).data('id');
@@ -156,7 +244,7 @@ function prepareTooltips() {
156
244
  link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + id;
157
245
  }
158
246
  }
159
- if (!link.match('^https?:\/\/')) {
247
+ if (!link.match('^https?:\/\/')) { //eslint-disable-line no-useless-escape
160
248
  if (common.readme) {
161
249
  link = common.readme + '#' + link;
162
250
  } else {
@@ -211,9 +299,8 @@ function onChange(isChanged) {
211
299
  }
212
300
 
213
301
  function showMessage(message, title, icon) {
214
- var $dialogMessage;
215
302
  // noinspection JSJQueryEfficiency
216
- $dialogMessage = $('#dialog-message');
303
+ let $dialogMessage = $('#dialog-message');
217
304
  if (!$dialogMessage.length) {
218
305
  $('body').append(
219
306
  '<div class="m"><div id="dialog-message" class="modal modal-fixed-footer">' +
package/admin/admin.js CHANGED
@@ -15,7 +15,7 @@ let devices = [],
15
15
  networkEvents,
16
16
  responseCodes = false,
17
17
  groups = {},
18
- devGroups = {},
18
+ devGroups = {}, // eslint-disable-line prefer-const
19
19
  binding = [],
20
20
  excludes = [],
21
21
  coordinatorinfo = {
@@ -29,9 +29,25 @@ let devices = [],
29
29
  shuffleInstance;
30
30
  const updateCardInterval = setInterval(updateCardTimer, 6000);
31
31
 
32
+ const networkOptions = {
33
+ autoResize: true,
34
+ height: '100%',
35
+ width: '100%',
36
+ nodes: {
37
+ shape: 'box'
38
+ },
39
+ layout: {
40
+ improvedLayout: true,
41
+ },
42
+ physics: {
43
+ enabled: true,
44
+ }
45
+ };
46
+
47
+
32
48
  const savedSettings = [
33
49
  'port', 'panID', 'channel', 'disableLed', 'countDown', 'groups', 'extPanID', 'precfgkey', 'transmitPower',
34
- 'adapterType', 'debugHerdsman', 'disableBackup', 'disablePing', 'external', 'startWithInconsistent', 'warnOnDeviceAnnouncement', 'baudRate'
50
+ 'adapterType', 'debugHerdsman', 'disableBackup', 'disablePing', 'external', 'startWithInconsistent', 'warnOnDeviceAnnouncement', 'baudRate', 'flowCTRL'
35
51
  ];
36
52
 
37
53
  function getDeviceByID(ID) {
@@ -54,7 +70,7 @@ function getDevice(ieeeAddr) {
54
70
  });
55
71
  }
56
72
 
57
- // eslint-disable-next-line no-unused-vars
73
+
58
74
  function getDeviceByNetwork(nwk) {
59
75
  return devices.find((devInfo) => {
60
76
  try {
@@ -276,7 +292,6 @@ function getCard(dev) {
276
292
  </div>`;
277
293
  return card;
278
294
  }
279
-
280
295
  /*
281
296
  function openReval(e, id, name){
282
297
  const $card = $(e.target).closest('.card');
@@ -369,7 +384,6 @@ function editName(id, name) {
369
384
  console.log('editName called with ' + name);
370
385
  const dev = devices.find((d) => d._id == id);
371
386
  $('#modaledit').find('input[id=\'d_name\']').val(name);
372
- // if (dev.info && dev.info.device._type == 'Router') {
373
387
  const groupables = [];
374
388
  if (dev && dev.info && dev.info.endpoints) {
375
389
  for (const ep of dev.info.endpoints) {
@@ -379,11 +393,13 @@ function editName(id, name) {
379
393
  }
380
394
  }
381
395
  const numEP = groupables.length;
382
- // console.log('groupables: '+JSON.stringify(groupables));
383
396
  $('#modaledit').find('.row.epid0').addClass('hide');
384
397
  $('#modaledit').find('.row.epid1').addClass('hide');
385
398
  $('#modaledit').find('.row.epid2').addClass('hide');
386
399
  $('#modaledit').find('.row.epid3').addClass('hide');
400
+ $('#modaledit').find('.row.epid4').addClass('hide');
401
+ $('#modaledit').find('.row.epid5').addClass('hide');
402
+ $('#modaledit').find('.row.epid6').addClass('hide');
387
403
  if (numEP > 0) {
388
404
  // go through all the groups. Find the ones to list for each groupable
389
405
  if (numEP == 1) {
@@ -396,7 +412,7 @@ function editName(id, name) {
396
412
  if (d.hasOwnProperty('memberinfo')) {
397
413
  for (const member of d.memberinfo) {
398
414
  const epid = EndPointIDfromEndPoint(member.ep);
399
- for (var i = 0; i < groupables.length; i++) {
415
+ for (let i = 0; i < groupables.length; i++) {
400
416
  if (groupables[i].epid == epid) {
401
417
  groupables[i].memberOf.push(d.native.id.replace('group_', ''));
402
418
  }
@@ -406,7 +422,7 @@ function editName(id, name) {
406
422
  }
407
423
  }
408
424
  console.log('groupables: ' + JSON.stringify(groupables));
409
- for (var i = 0; i < groupables.length; i++) {
425
+ for (let i = 0; i < groupables.length; i++) {
410
426
  if (i > 1) {
411
427
  $('#modaledit').find('translate.device_with_endpoint').innerHtml = name + ' ' + groupables[i].epid;
412
428
  }
@@ -414,16 +430,12 @@ function editName(id, name) {
414
430
  list2select('#d_groups_ep' + i, groups, groupables[i].memberOf || []);
415
431
  }
416
432
  }
417
- // } else {
418
- // $('#modaledit').find('.input-field.endpoints').addClass('hide');
419
- // $('#modaledit').find('.input-field.groups').addClass('hide');
420
- // }
421
433
  $('#modaledit a.btn[name=\'save\']').unbind('click');
422
434
  $('#modaledit a.btn[name=\'save\']').click(() => {
423
435
  const newName = $('#modaledit').find('input[id=\'d_name\']').val();
424
436
  const groupsbyid = {};
425
437
  if (groupables.length > 0) {
426
- for (var i = 0; i < groupables.length; i++) {
438
+ for (let i = 0; i < groupables.length; i++) {
427
439
  const ng = $('#d_groups_ep' + i).val();
428
440
  if (ng.toString() != groupables[i].memberOf.toString())
429
441
  groupsbyid[groupables[i].ep.ID] = GenerateGroupChange(groupables[i].memberOf, ng);
@@ -437,7 +449,7 @@ function editName(id, name) {
437
449
  }
438
450
 
439
451
  function GenerateGroupChange(oldmembers, newmembers) {
440
- let grpchng = [];
452
+ const grpchng = [];
441
453
  for (const oldg of oldmembers)
442
454
  if (!newmembers.includes(oldg)) grpchng.push('-' + oldg);
443
455
  for (const newg of newmembers)
@@ -533,7 +545,7 @@ function showDevices() {
533
545
  } else {
534
546
  //if (d.groups && d.info && d.info.device._type == "Router") {
535
547
  if (d.groups) {
536
- // devGroups[d._id] = d.groups;
548
+ //devGroups[d._id] = d.groups;
537
549
  if (typeof d.groups.map == 'function') {
538
550
  d.groupNames = d.groups.map(item => {
539
551
  return groups[item] || '';
@@ -560,9 +572,11 @@ function showDevices() {
560
572
  const roomSelector = $('#room-filter');
561
573
  roomSelector.empty();
562
574
  roomSelector.append(`<li class="device-order-item" data-type="All" tabindex="0"><a class="translate" data-lang="All">All</a></li>`);
563
- allRooms.forEach((item) => {
564
- roomSelector.append(`<li class="device-order-item" data-type="${item}" tabindex="0"><a class="translate" data-lang="${item}">${item}</a></li>`);
565
- });
575
+ Array.from(allRooms)
576
+ .sort()
577
+ .forEach((item) => {
578
+ roomSelector.append(`<li class="device-order-item" data-type="${item}" tabindex="0"><a class="translate" data-lang="${item}">${item}</a></li>`);
579
+ });
566
580
  $('#room-filter a').click(function () {
567
581
  $('#room-filter-btn').text($(this).text());
568
582
  doFilter();
@@ -694,7 +708,7 @@ function letsPairingWithCode(code) {
694
708
  showMessage(msg.error, _('Error'));
695
709
  }
696
710
  else {
697
- showPairingProcess();
711
+ showPairingProcess();
698
712
  }
699
713
  });
700
714
  }
@@ -781,7 +795,7 @@ function getMap() {
781
795
  }
782
796
 
783
797
  // the function loadSettings has to exist ...
784
- // eslint-disable-next-line no-unused-vars
798
+
785
799
  function load(settings, onChange) {
786
800
  if (settings.panID === undefined) {
787
801
  settings.panID = 6754;
@@ -889,13 +903,13 @@ function load(settings, onChange) {
889
903
  });
890
904
 
891
905
  $('#code_pairing').click(function () {
892
- if (!$('#pairing').hasClass('pulse')) {
893
- $('#codeentry a.btn[name=\'pair\']').click(() => {
894
- const code = $('#codeentry').find('input[id=\'qr_code\']').val();
895
- letsPairingWithCode(code)
896
- });
897
- $('#codeentry').modal('open');
898
- }
906
+ if (!$('#pairing').hasClass('pulse')) {
907
+ $('#codeentry a.btn[name=\'pair\']').click(() => {
908
+ const code = $('#codeentry').find('input[id=\'qr_code\']').val();
909
+ letsPairingWithCode(code)
910
+ });
911
+ $('#codeentry').modal('open');
912
+ }
899
913
  });
900
914
 
901
915
  $(document).ready(function () {
@@ -914,6 +928,10 @@ function load(settings, onChange) {
914
928
  $('#device-order-btn').text($(this).text());
915
929
  doSort();
916
930
  });
931
+ $('#device-filter a').click(function () {
932
+ $('#device-filter-btn').text($(this).text());
933
+ doFilter();
934
+ });
917
935
  });
918
936
 
919
937
  const text = $('#pairing').attr('data-tooltip');
@@ -966,9 +984,8 @@ function showPairingProcess() {
966
984
 
967
985
  // ... and the function save has to exist.
968
986
  // you have to make sure the callback is called with the settings object as first param!
969
- // eslint-disable-next-line no-unused-vars
987
+
970
988
  function save(callback) {
971
- // example: select elements with class=value and build settings object
972
989
  const obj = {};
973
990
  $('.value').each(function () {
974
991
  const $this = $(this);
@@ -1098,13 +1115,13 @@ function showNetworkMap(devices, map) {
1098
1115
  const edges = [];
1099
1116
 
1100
1117
  if (map.lqis == undefined || map.lqis.length === 0) { // first init
1101
- $('#filterParent, #filterSibl, #filterPrvChild, #filterMesh').change(function () {
1118
+ $('#filterParent, #filterSibl, #filterPrvChild, #filterMesh, #physicsOn').change(function () {
1102
1119
  updateMapFilter();
1103
1120
  });
1104
1121
  }
1105
1122
 
1106
1123
  const createNode = function (dev, mapEntry) {
1107
- if (dev.common && dev.common.type == 'group') return undefined;
1124
+ if (dev.common && (dev.common.type == 'group' || dev.common.deactivated)) return undefined;
1108
1125
  const extInfo = (mapEntry && mapEntry.networkAddress) ? `\n (nwkAddr: 0x${mapEntry.networkAddress.toString(16)} | ${mapEntry.networkAddress})` : '';
1109
1126
  const node = {
1110
1127
  id: dev._id,
@@ -1295,19 +1312,8 @@ function showNetworkMap(devices, map) {
1295
1312
  nodes: nodesArray,
1296
1313
  edges: mapEdges
1297
1314
  };
1298
- const options = {
1299
- autoResize: true,
1300
- height: '100%',
1301
- width: '100%',
1302
- nodes: {
1303
- shape: 'box'
1304
- },
1305
- layout: {
1306
- improvedLayout: true,
1307
- }
1308
- };
1309
1315
 
1310
- network = new vis.Network(container, data, options);
1316
+ network = new vis.Network(container, data, networkOptions);
1311
1317
 
1312
1318
  const onMapSelect = function (event) {
1313
1319
  // workaround for https://github.com/almende/vis/issues/4112
@@ -1405,6 +1411,8 @@ function updateMapFilter() {
1405
1411
  const showSibl = $('#filterSibl').is(':checked');
1406
1412
  const showPrvChild = $('#filterPrvChild').is(':checked');
1407
1413
  const invisColor = $('#filterMesh').is(':checked') ? 0.2 : 0;
1414
+ networkOptions.physics.enabled = $('#physicsOn').is(':checked');
1415
+ network.setOptions(networkOptions);
1408
1416
  mapEdges.forEach((edge) => {
1409
1417
  if (((edge.relationship === 0 || edge.relationship === 1) && showParent)
1410
1418
  || (edge.relationship === 2 && showSibl)
@@ -2544,7 +2552,7 @@ function showChannels() {
2544
2552
  }
2545
2553
  }
2546
2554
  });
2547
- showWaitingDialog('Scanning channels', 10);
2555
+ showWaitingDialog('Scanning channels - not working yet', 10);
2548
2556
  }
2549
2557
 
2550
2558
  function onlyOne(devs) {
@@ -2746,7 +2754,8 @@ function doFilter(inputText) {
2746
2754
  const lang = systemLang || 'en';
2747
2755
  const searchText = inputText || $('#device-search').val();
2748
2756
  const roomFilter = $('#room-filter-btn').text().toLowerCase();
2749
- if (searchText || roomFilter !== 'all') {
2757
+ const deviceFilter = $('#device-filter-btn').text().toLowerCase();
2758
+ if (searchText || roomFilter !== 'all' || deviceFilter != 'all') {
2750
2759
  shuffleInstance.filter(function (element, shuffle) {
2751
2760
  const devId = element.getAttribute('id');
2752
2761
  const dev = getDeviceByID(devId);
@@ -2770,6 +2779,29 @@ function doFilter(inputText) {
2770
2779
  valid = false;
2771
2780
  }
2772
2781
  }
2782
+ if (valid && dev && deviceFilter !== 'all') {
2783
+ switch (deviceFilter) {
2784
+ case 'connected':
2785
+ valid = (dev.link_quality > 0) && !dev.common.deactivated;
2786
+ break;
2787
+ case 'disconnected':
2788
+ valid = (dev.link_quality <= 0) && !dev.common.deactivated;
2789
+ break;
2790
+ case 'deactivated':
2791
+ valid = dev.common.deactivated;
2792
+ break;
2793
+ case 'router':
2794
+ valid = dev.battery == null;
2795
+ break;
2796
+ case 'enddevice':
2797
+ valid = dev.battery && dev.battery>0;
2798
+ break;
2799
+ case 'group':
2800
+ valid = (dev.common.type == 'group');
2801
+ break;
2802
+ default: valid = true;
2803
+ }
2804
+ }
2773
2805
  return valid;
2774
2806
  });
2775
2807
  } else {
@@ -50,7 +50,7 @@
50
50
  "Read Firmware": "Firmware lesen",
51
51
  "Refresh": "Aktualisieren",
52
52
  "Rename device": "Gerät umbenennen",
53
- "Reset Info": "Ein Soft-Reset startet nur den CC253x Adapter und die zugehörige Software neu. Ein Hard-Reset setzt die Liste ALLER gekoppelten Geräte und die CC253x Einstellungen zurück! Alle Geräte müssen anschließend neu gekoppelt werden!",
53
+ "Reset Info": "Ein Soft-Reset startet den Coordinator und den Adapter neu. Ein Hard-Reset setzt die Liste ALLER gekoppelten Geräte und den Coordinator zurück! Alle Geräte müssen anschließend neu gekoppelt werden!",
54
54
  "Reset confirmation": "Reset bestätigen",
55
55
  "Reset...": "Zurücksetzen…",
56
56
  "Results": "Ergebnisse",