iobroker.zigbee 1.6.0 → 1.6.12
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 +16 -2
- package/admin/adapter-settings.js +39 -3
- package/admin/admin.js +179 -27
- package/admin/img/14153905L.png +0 -0
- package/admin/img/81855.png +0 -0
- package/admin/img/HG06338.png +0 -0
- package/admin/img/R7060.png +0 -0
- package/admin/img/TI0001-cover.png +0 -0
- package/admin/img/WHD02.png +0 -0
- package/admin/img/ikea_E1812.png +0 -0
- package/admin/img/tuya_rb280.png +0 -0
- package/admin/index_m.html +141 -24
- package/admin/tab_m.html +170 -216
- package/admin/words.js +31 -30
- package/io-package.json +24 -1
- package/lib/commands.js +35 -4
- package/lib/developer.js +6 -2
- package/lib/devices.js +46 -1
- package/lib/exposes.js +7 -4
- package/lib/groups.js +28 -18
- package/lib/rgb.js +30 -0
- package/lib/states.js +64 -39
- package/lib/statescontroller.js +84 -22
- package/lib/utils.js +19 -0
- package/lib/zbBaseExtension.js +4 -3
- package/lib/zbDelayedAction.js +1 -0
- package/lib/zbDeviceAvailability.js +2 -1
- package/lib/zbDeviceConfigure.js +11 -7
- package/lib/zbDeviceEvent.js +6 -0
- package/lib/zigbeecontroller.js +95 -16
- package/main.js +47 -32
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ Works with devices from this list https://github.com/ioBroker/ioBroker.zigbee/wi
|
|
|
97
97
|
|
|
98
98
|
You can thank the authors by these links:
|
|
99
99
|
* to Kirov Ilya https://www.paypal.me/goofyk
|
|
100
|
-
* to Arthur Rupp https://paypal.me/
|
|
100
|
+
* to Arthur Rupp https://paypal.me/ArthurRupp
|
|
101
101
|
|
|
102
102
|
<!--
|
|
103
103
|
Placeholder for the next version (at the beginning of the line):
|
|
@@ -112,8 +112,22 @@ You can thank the authors by these links:
|
|
|
112
112
|
|
|
113
113
|
## Changelog
|
|
114
114
|
|
|
115
|
+
### 1.6.12 (2022-01)
|
|
116
|
+
* (asgothian) Groups were newly revised (read here https://github.com/ioBroker/ioBroker.zigbee/pull/1327)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
### 1.6.9 (2021-12)
|
|
120
|
+
* (simatec) fix admin Dark-Mode
|
|
121
|
+
* (asgothian) Expose Access Handling
|
|
122
|
+
* (arteck) translations
|
|
123
|
+
* (asgothian) fix groups
|
|
124
|
+
* (agross) use different normalization rules
|
|
125
|
+
|
|
126
|
+
### 1.6.1 (2021-08)
|
|
127
|
+
* (kirovilya) herdsman compatibility
|
|
128
|
+
|
|
115
129
|
### 1.6.0 (2021-08-09)
|
|
116
|
-
Attention!
|
|
130
|
+
## Attention! Attention! Attention! Attention! Attention! Attention! Attention!
|
|
117
131
|
|
|
118
132
|
After introducing a new z-stack startup procedure into zigbee-herdsman, we got some problems with our adapter in version 1.5.6.
|
|
119
133
|
This was discussed [here](https://github.com/ioBroker/ioBroker.zigbee/issues/1110) and [here](https://github.com/Koenkk/zigbee-herdsman/issues/376)
|
|
@@ -3,8 +3,33 @@ const path = location.pathname;
|
|
|
3
3
|
const parts = path.split('/');
|
|
4
4
|
parts.splice(-3);
|
|
5
5
|
|
|
6
|
-
const socket
|
|
7
|
-
|
|
6
|
+
const socket = io.connect('/', { path: parts.join('/') + '/socket.io' });
|
|
7
|
+
var query = (window.location.search || '').replace(/^\?/, '').replace(/#.*$/, '');
|
|
8
|
+
var args = {};
|
|
9
|
+
let theme = null;
|
|
10
|
+
|
|
11
|
+
// parse parameters
|
|
12
|
+
query.trim().split('&').filter(function (t) { return t.trim(); }).forEach(function (b, i) {
|
|
13
|
+
const parts = b.split('=');
|
|
14
|
+
if (!i && parts.length === 1 && !isNaN(parseInt(b, 10))) {
|
|
15
|
+
args.instance = parseInt(b, 10);
|
|
16
|
+
}
|
|
17
|
+
var name = parts[0];
|
|
18
|
+
args[name] = parts.length === 2 ? parts[1] : true;
|
|
19
|
+
|
|
20
|
+
if (name === 'instance') {
|
|
21
|
+
args.instance = parseInt(args.instance, 10) || 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (args[name] === 'true') {
|
|
25
|
+
args[name] = true;
|
|
26
|
+
} else if (args[name] === 'false') {
|
|
27
|
+
args[name] = false;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
var instance = args.instance;
|
|
32
|
+
|
|
8
33
|
let common = null; // common information of adapter
|
|
9
34
|
const host = null; // host object on which the adapter runs
|
|
10
35
|
const changed = false;
|
|
@@ -71,6 +96,17 @@ function loadSettings(callback) {
|
|
|
71
96
|
if (typeof load === 'undefined') {
|
|
72
97
|
alert('Please implement save function in your admin/index.html');
|
|
73
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
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
74
110
|
load(res.native, onChange);
|
|
75
111
|
}
|
|
76
112
|
if (typeof callback === 'function') {
|
|
@@ -205,4 +241,4 @@ function showMessage(message, title, icon) {
|
|
|
205
241
|
}
|
|
206
242
|
$dialogMessage.find('.dialog-text').html(message);
|
|
207
243
|
$dialogMessage.modal().modal('open');
|
|
208
|
-
}
|
|
244
|
+
}
|
package/admin/admin.js
CHANGED
|
@@ -146,7 +146,7 @@ function getGroupCard(dev) {
|
|
|
146
146
|
info = info.concat(`<li><span class="labelinfo">No devices in group</span></li>`);
|
|
147
147
|
} else {
|
|
148
148
|
for (let m=0;m < dev.memberinfo.length; m++) {
|
|
149
|
-
info = info.concat(`<li><span
|
|
149
|
+
info = info.concat(`<li><span align:"left">${dev.memberinfo[m].device}.${dev.memberinfo[m].epid}</span><span align:"right"> ...${dev.memberinfo[m].ieee.slice(-4)}</span></li>`);
|
|
150
150
|
}
|
|
151
151
|
memberCount = (dev.memberinfo.length<8?dev.memberinfo.length:7);
|
|
152
152
|
};
|
|
@@ -154,7 +154,7 @@ function getGroupCard(dev) {
|
|
|
154
154
|
</div>`);
|
|
155
155
|
const image = `<img src="img/group_${memberCount}.png" width="80px" onerror="this.onerror=null;this.src='img/unavailable.png';">`;
|
|
156
156
|
const dashCard = getDashCard(dev,`img/group_${memberCount}.png` );
|
|
157
|
-
const card = `<div id="${id}" class="device">
|
|
157
|
+
const card = `<div id="${id}" class="device group">
|
|
158
158
|
<div class="card hoverable flipable">
|
|
159
159
|
<div class="front face">${dashCard}</div>
|
|
160
160
|
<div class="back face">
|
|
@@ -187,12 +187,16 @@ function getGroupCard(dev) {
|
|
|
187
187
|
return card;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
function sanitizeModelParameter(parameter) {
|
|
191
|
+
const replaceByUnderscore = /[\s/]/g;
|
|
192
|
+
return parameter.replace(replaceByUnderscore, '_');
|
|
193
|
+
}
|
|
191
194
|
|
|
192
195
|
function getCard(dev) {
|
|
193
196
|
const title = dev.common.name,
|
|
194
197
|
id = dev._id,
|
|
195
|
-
type = (dev.common.type ? dev.common.type
|
|
198
|
+
type = (dev.common.type ? dev.common.type : 'unknown'),
|
|
199
|
+
type_url = (dev.common.type ? sanitizeModelParameter(dev.common.type) : 'unknown'),
|
|
196
200
|
img_src = dev.icon || dev.common.icon,
|
|
197
201
|
rooms = [],
|
|
198
202
|
lang = systemLang || 'en';
|
|
@@ -206,7 +210,7 @@ function getCard(dev) {
|
|
|
206
210
|
const room = rooms.join(',') || ' ';
|
|
207
211
|
const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
|
|
208
212
|
const rid = id.split('.').join('_');
|
|
209
|
-
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${
|
|
213
|
+
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
|
|
210
214
|
const image = `<img src="${img_src}" width="80px" onerror="this.onerror=null;this.src='img/unavailable.png';">`,
|
|
211
215
|
nwk = (dev.info && dev.info.device) ? dev.info.device._networkAddress : undefined,
|
|
212
216
|
battery_cls = getBatteryCls(dev.battery),
|
|
@@ -254,6 +258,9 @@ function getCard(dev) {
|
|
|
254
258
|
<button name="edit" class="right btn-flat btn-small">
|
|
255
259
|
<i class="material-icons icon-green">edit</i>
|
|
256
260
|
</button>
|
|
261
|
+
<button name="reconfigure" class="right btn-flat btn-small tooltipped" title="Reconfigure">
|
|
262
|
+
<i class="material-icons icon-red">sync</i>
|
|
263
|
+
</button>
|
|
257
264
|
${permitJoinBtn}
|
|
258
265
|
</div>
|
|
259
266
|
</div>
|
|
@@ -344,25 +351,96 @@ function cleanConfirmation() {
|
|
|
344
351
|
Materialize.updateTextFields();
|
|
345
352
|
}
|
|
346
353
|
|
|
354
|
+
function EndPointIDfromEndPoint(ep)
|
|
355
|
+
{
|
|
356
|
+
if (ep && ep.deviceIeeeAddress && ep.ID)
|
|
357
|
+
return `${ep.deviceIeeeAddress}:${ep.ID}`;
|
|
358
|
+
return 'unidentified';
|
|
359
|
+
}
|
|
360
|
+
|
|
347
361
|
function editName(id, name) {
|
|
362
|
+
console.log('editName called with '+name);
|
|
348
363
|
const dev = devices.find((d) => d._id == id);
|
|
349
364
|
$('#modaledit').find("input[id='d_name']").val(name);
|
|
350
|
-
if (dev.info && dev.info.device._type == 'Router') {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
365
|
+
// if (dev.info && dev.info.device._type == 'Router') {
|
|
366
|
+
const groupables = [];
|
|
367
|
+
if (dev && dev.info && dev.info.endpoints) {
|
|
368
|
+
for (const ep of dev.info.endpoints) {
|
|
369
|
+
if (ep.inputClusters.includes(4)) {
|
|
370
|
+
groupables.push({ epid:EndPointIDfromEndPoint(ep), ep:ep, memberOf:[]});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const numEP = groupables.length;
|
|
375
|
+
// console.log('groupables: '+JSON.stringify(groupables));
|
|
376
|
+
$('#modaledit').find('.row.epid0').addClass('hide');
|
|
377
|
+
$('#modaledit').find('.row.epid1').addClass('hide');
|
|
378
|
+
$('#modaledit').find('.row.epid2').addClass('hide');
|
|
379
|
+
$('#modaledit').find('.row.epid3').addClass('hide');
|
|
380
|
+
if (numEP > 0) {
|
|
381
|
+
// go through all the groups. Find the ones to list for each groupable
|
|
382
|
+
if (numEP == 1) {
|
|
383
|
+
$('#modaledit').find('.endpointid').addClass('hide');
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
$('#modaledit').find('.endpointid').removeClass('hide');
|
|
387
|
+
}
|
|
388
|
+
for (const d of devices) {
|
|
389
|
+
if (d && d.common && d.common.type == 'group') {
|
|
390
|
+
if (d.hasOwnProperty("memberinfo")) {
|
|
391
|
+
for (const member of d.memberinfo) {
|
|
392
|
+
const epid = EndPointIDfromEndPoint(member.ep)
|
|
393
|
+
for (var i=0;i<groupables.length;i++) {
|
|
394
|
+
if (groupables[i].epid == epid) {
|
|
395
|
+
groupables[i].memberOf.push(d.native.id.replace('group_', ''));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
console.log("groupables: " + JSON.stringify(groupables));
|
|
403
|
+
for (var i = 0;i<groupables.length;i++)
|
|
404
|
+
{
|
|
405
|
+
if (i > 1) {
|
|
406
|
+
$('#modaledit').find("translate.device_with_endpoint").innerHtml = name + ' ' + groupables[i].epid;
|
|
407
|
+
}
|
|
408
|
+
$('#modaledit').find('.row.epid'+i).removeClass('hide');
|
|
409
|
+
list2select('#d_groups_ep'+i, groups, groupables[i].memberOf || []);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// } else {
|
|
413
|
+
// $('#modaledit').find('.input-field.endpoints').addClass('hide');
|
|
414
|
+
// $('#modaledit').find('.input-field.groups').addClass('hide');
|
|
415
|
+
// }
|
|
356
416
|
$("#modaledit a.btn[name='save']").unbind('click');
|
|
357
417
|
$("#modaledit a.btn[name='save']").click(() => {
|
|
358
|
-
const newName = $('#modaledit').find("input[id='d_name']").val()
|
|
359
|
-
|
|
360
|
-
|
|
418
|
+
const newName = $('#modaledit').find("input[id='d_name']").val();
|
|
419
|
+
const groupsbyid = {};
|
|
420
|
+
if (groupables.length > 0) {
|
|
421
|
+
for (var i = 0;i<groupables.length;i++) {
|
|
422
|
+
const ng = $('#d_groups_ep'+i).val();
|
|
423
|
+
if (ng.toString() != groupables[i].memberOf.toString())
|
|
424
|
+
groupsbyid[groupables[i].ep.ID] = GenerateGroupChange(groupables[i].memberOf, ng);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
console.log('grpid ' + JSON.stringify(groupsbyid));
|
|
428
|
+
updateDev(id, newName, groupsbyid);
|
|
361
429
|
});
|
|
362
430
|
$('#modaledit').modal('open');
|
|
363
431
|
Materialize.updateTextFields();
|
|
364
432
|
}
|
|
365
433
|
|
|
434
|
+
function GenerateGroupChange(oldmembers, newmembers)
|
|
435
|
+
{
|
|
436
|
+
let grpchng = [];
|
|
437
|
+
for (const oldg of oldmembers)
|
|
438
|
+
if (!newmembers.includes(oldg)) grpchng.push('-'+oldg);
|
|
439
|
+
for (const newg of newmembers)
|
|
440
|
+
if (!oldmembers.includes(newg)) grpchng.push(newg)
|
|
441
|
+
return grpchng;
|
|
442
|
+
}
|
|
443
|
+
|
|
366
444
|
function deleteDevice(id, force) {
|
|
367
445
|
sendTo(namespace, 'deleteDevice', {id: id, force: force}, function (msg) {
|
|
368
446
|
closeWaitingDialog();
|
|
@@ -525,7 +603,7 @@ function showDevices() {
|
|
|
525
603
|
const dev_block = $(this).parents('div.device'),
|
|
526
604
|
id = dev_block.attr('id').replace(namespace+'.group_', ''),
|
|
527
605
|
name = getDevName(dev_block);
|
|
528
|
-
editGroupName(id, name);
|
|
606
|
+
editGroupName(id, name, false);
|
|
529
607
|
});
|
|
530
608
|
$("button.btn-floating[name='join']").click(function() {
|
|
531
609
|
const dev_block = $(this).parents('div.device');
|
|
@@ -544,6 +622,10 @@ function showDevices() {
|
|
|
544
622
|
$("a.btn-flat[name='close']").click((e) => {
|
|
545
623
|
closeReval(e);
|
|
546
624
|
});
|
|
625
|
+
$(".card-reveal-buttons button[name='reconfigure']").click(function() {
|
|
626
|
+
const dev_block = $(this).parents('div.device');
|
|
627
|
+
reconfigureDlg(getDevId(dev_block));
|
|
628
|
+
});
|
|
547
629
|
|
|
548
630
|
showNetworkMap(devices, map);
|
|
549
631
|
translateAll();
|
|
@@ -656,7 +738,7 @@ function getDevices() {
|
|
|
656
738
|
}
|
|
657
739
|
|
|
658
740
|
function getDeviceCards() {
|
|
659
|
-
return $('#devices .device');
|
|
741
|
+
return $('#devices .device').not(".group");
|
|
660
742
|
}
|
|
661
743
|
|
|
662
744
|
function getDeviceCard(devId) {
|
|
@@ -759,11 +841,11 @@ function load(settings, onChange) {
|
|
|
759
841
|
|
|
760
842
|
$('#add_group').click(function() {
|
|
761
843
|
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
|
|
762
|
-
editGroupName(maxind+1, '');
|
|
844
|
+
editGroupName(maxind+1, 'Group ' + maxind+1, true);
|
|
763
845
|
});
|
|
764
846
|
$('#add_grp_btn').click(function() {
|
|
765
847
|
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
|
|
766
|
-
editGroupName(maxind+1, '');
|
|
848
|
+
editGroupName(maxind+1, 'Group ' + maxind+1, true);
|
|
767
849
|
getDevices();
|
|
768
850
|
});
|
|
769
851
|
|
|
@@ -1702,7 +1784,7 @@ function showGroups() {
|
|
|
1702
1784
|
$("a.btn-floating[name='groupedit']").click(function() {
|
|
1703
1785
|
const index = $(this).attr('id'),
|
|
1704
1786
|
name = groups[index];
|
|
1705
|
-
editGroupName(index, name);
|
|
1787
|
+
editGroupName(index, name, false);
|
|
1706
1788
|
});
|
|
1707
1789
|
$("a.btn-floating[name='groupdelete']").click(function() {
|
|
1708
1790
|
const index = $(this).attr('id'),
|
|
@@ -1711,8 +1793,35 @@ function showGroups() {
|
|
|
1711
1793
|
});
|
|
1712
1794
|
}
|
|
1713
1795
|
|
|
1714
|
-
function editGroupName(id, name) {
|
|
1796
|
+
function editGroupName(id, name, isnew) {
|
|
1797
|
+
//const dev = devices.find((d) => d._id == id);
|
|
1798
|
+
//console.log('devices: '+ JSON.stringify(devices));
|
|
1799
|
+
const groupables = [];
|
|
1800
|
+
for (const d of devices) {
|
|
1801
|
+
if (d && d.info && d.info.endpoints) {
|
|
1802
|
+
for (const ep of d.info.endpoints) {
|
|
1803
|
+
if (ep.inputClusters.includes(4))
|
|
1804
|
+
{
|
|
1805
|
+
groupables.push(ep);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
//console.log('device ' + JSON.stringify(d));
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1715
1812
|
//var text = 'Enter new name for "'+name+'" ('+id+')?';
|
|
1813
|
+
if (isnew) {
|
|
1814
|
+
$('#groupedit').find('.editgroup').addClass('hide');
|
|
1815
|
+
$('#groupedit').find('.addgroup').removeClass('hide');
|
|
1816
|
+
$('#groupedit').find('.input-field.members').addClass('hide');
|
|
1817
|
+
$('#groupedit').find('.input-field.groupid').removeClass('hide');
|
|
1818
|
+
}
|
|
1819
|
+
else {
|
|
1820
|
+
$('#groupedit').find('.editgroup').removeClass('hide');
|
|
1821
|
+
$('#groupedit').find('.addgroup').addClass('hide');
|
|
1822
|
+
$('#groupedit').find('.input-field.members').removeClass('hide');
|
|
1823
|
+
$('#groupedit').find('.input-field.groupid').addClass('hide');
|
|
1824
|
+
}
|
|
1716
1825
|
$('#groupedit').find("input[id='g_index']").val(id);
|
|
1717
1826
|
$('#groupedit').find("input[id='g_name']").val(name);
|
|
1718
1827
|
$("#groupedit a.btn[name='save']").unbind('click');
|
|
@@ -1756,6 +1865,21 @@ function updateDev(id, newName, newGroups) {
|
|
|
1756
1865
|
if (dev && dev.common.name != newName) {
|
|
1757
1866
|
renameDevice(id, newName);
|
|
1758
1867
|
}
|
|
1868
|
+
const keys = Object.keys(newGroups)
|
|
1869
|
+
if (keys && keys.length)
|
|
1870
|
+
{
|
|
1871
|
+
sendTo(namespace, 'updateGroupMembership', { id: id, groups: newGroups }, function (msg) {
|
|
1872
|
+
if (msg && msg.error) {
|
|
1873
|
+
showMessage(msg.error, _('Error'));
|
|
1874
|
+
}
|
|
1875
|
+
else {
|
|
1876
|
+
// save dev-groups on success
|
|
1877
|
+
dev.groups = newGroups;
|
|
1878
|
+
}
|
|
1879
|
+
showDevices();
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
/*
|
|
1759
1883
|
if (dev.info.device._type == 'Router') {
|
|
1760
1884
|
const oldGroups = devGroups[id] || [];
|
|
1761
1885
|
if (oldGroups.toString() != newGroups.toString()) {
|
|
@@ -1772,6 +1896,7 @@ function updateDev(id, newName, newGroups) {
|
|
|
1772
1896
|
});
|
|
1773
1897
|
}
|
|
1774
1898
|
}
|
|
1899
|
+
*/
|
|
1775
1900
|
}
|
|
1776
1901
|
|
|
1777
1902
|
function resetConfirmation() {
|
|
@@ -2166,7 +2291,7 @@ function genDevInfo(device) {
|
|
|
2166
2291
|
const dev = (device && device.info) ? device.info.device : undefined;
|
|
2167
2292
|
const mapped = (device && device.info) ? device.info.mapped : undefined;
|
|
2168
2293
|
if (!dev) return `<div class="truncate">No info</div>`;
|
|
2169
|
-
const genRow = function(name, value) {
|
|
2294
|
+
const genRow = function(name, value, refresh) {
|
|
2170
2295
|
if (value === undefined) {
|
|
2171
2296
|
return '';
|
|
2172
2297
|
} else {
|
|
@@ -2185,7 +2310,7 @@ function genDevInfo(device) {
|
|
|
2185
2310
|
}).join('');
|
|
2186
2311
|
}
|
|
2187
2312
|
};
|
|
2188
|
-
const modelUrl = (!mapped) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${mapped.model}.html" target="_blank" rel="noopener noreferrer">${mapped.model}</a>`;
|
|
2313
|
+
const modelUrl = (!mapped) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${sanitizeModelParameter(mapped.model)}.html" target="_blank" rel="noopener noreferrer">${mapped.model}</a>`;
|
|
2189
2314
|
const mappedInfo = (!mapped) ? '' :
|
|
2190
2315
|
`<div style="font-size: 0.9em">
|
|
2191
2316
|
<ul>
|
|
@@ -2230,7 +2355,7 @@ function genDevInfo(device) {
|
|
|
2230
2355
|
${genRow('date code', dev._dateCode)}
|
|
2231
2356
|
${genRow('build', dev._softwareBuildID)}
|
|
2232
2357
|
${genRow('interviewed', dev._interviewCompleted)}
|
|
2233
|
-
${genRow('configured', (dev.meta.configured === 1))}
|
|
2358
|
+
${genRow('configured', (dev.meta.configured === 1), true)}
|
|
2234
2359
|
</ul>
|
|
2235
2360
|
</div>
|
|
2236
2361
|
</div>
|
|
@@ -2246,17 +2371,19 @@ function showDevInfo(id){
|
|
|
2246
2371
|
$('#modaldevinfo').modal('open');
|
|
2247
2372
|
}
|
|
2248
2373
|
|
|
2374
|
+
let waitingTimeout, waitingInt;
|
|
2249
2375
|
|
|
2250
2376
|
function showWaitingDialog(text, timeout){
|
|
2251
2377
|
let countDown = timeout;
|
|
2252
|
-
|
|
2378
|
+
waitingInt = setInterval(function() {
|
|
2253
2379
|
countDown -= 1;
|
|
2254
2380
|
const percent = 100-100*countDown/timeout;
|
|
2255
2381
|
$('#waiting_progress_line').css('width', `${percent}%`);
|
|
2256
2382
|
}, 1000);
|
|
2257
|
-
setTimeout(function() {
|
|
2383
|
+
waitingTimeout = setTimeout(function() {
|
|
2258
2384
|
$('#waiting_progress_line').css('width', `0%`);
|
|
2259
2385
|
clearTimeout(waitingInt);
|
|
2386
|
+
clearTimeout(waitingTimeout);
|
|
2260
2387
|
$('#modalWaiting').modal('close');
|
|
2261
2388
|
}, timeout*1000);
|
|
2262
2389
|
$('#waiting_message').text(text);
|
|
@@ -2264,6 +2391,8 @@ function showWaitingDialog(text, timeout){
|
|
|
2264
2391
|
}
|
|
2265
2392
|
|
|
2266
2393
|
function closeWaitingDialog(){
|
|
2394
|
+
if (waitingInt) clearTimeout(waitingInt);
|
|
2395
|
+
if (waitingTimeout) clearTimeout(waitingTimeout);
|
|
2267
2396
|
$('#modalWaiting').modal('close');
|
|
2268
2397
|
}
|
|
2269
2398
|
|
|
@@ -2427,10 +2556,10 @@ function showExclude() {
|
|
|
2427
2556
|
const exclude_dev = devices.find((d) => d.common.type == exclude_id) || {common: {name: exclude_id}};
|
|
2428
2557
|
// exclude_icon = (exclude_dev.icon) ? `<img src="${exclude_dev.icon}" width="64px">` : '';
|
|
2429
2558
|
|
|
2430
|
-
const modelUrl = (!exclude_id) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${exclude_id}.html" target="_blank" rel="noopener noreferrer">${exclude_id}</a>`;
|
|
2559
|
+
const modelUrl = (!exclude_id) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${sanitizeModelParameter(exclude_id)}.html" target="_blank" rel="noopener noreferrer">${exclude_id}</a>`;
|
|
2431
2560
|
|
|
2432
2561
|
const card = `
|
|
2433
|
-
<div id="${exclude_id}" class="exclude col s12 m6 l4 xl3">
|
|
2562
|
+
<div id="${exclude_id}" class="exclude col s12 m6 l4 xl3" style="height: 135px;padding-bottom: 10px;">
|
|
2434
2563
|
<div class="card hoverable">
|
|
2435
2564
|
<div class="card-content zcard">
|
|
2436
2565
|
<i class="left"><img src="${exclude_dev.icon}" width="64px" onerror="this.onerror=null;this.src='img/unavailable.png';"></i>
|
|
@@ -2698,3 +2827,26 @@ function removeDevice(id) {
|
|
|
2698
2827
|
}
|
|
2699
2828
|
}
|
|
2700
2829
|
}
|
|
2830
|
+
|
|
2831
|
+
function reconfigureDlg(id) {
|
|
2832
|
+
const text = translateWord(`Do you really want to reconfigure device?`);
|
|
2833
|
+
$('#modalreconfigure').find('p').text(text);
|
|
2834
|
+
$("#modalreconfigure a.btn[name='yes']").unbind('click');
|
|
2835
|
+
$("#modalreconfigure a.btn[name='yes']").click(() => {
|
|
2836
|
+
reconfigureDevice(id, force);
|
|
2837
|
+
});
|
|
2838
|
+
$('#modalreconfigure').modal('open');
|
|
2839
|
+
Materialize.updateTextFields();
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2842
|
+
function reconfigureDevice(id) {
|
|
2843
|
+
sendTo(namespace, 'reconfigure', {id: id}, function (msg) {
|
|
2844
|
+
closeWaitingDialog();
|
|
2845
|
+
if (msg) {
|
|
2846
|
+
if (msg.error) {
|
|
2847
|
+
showMessage(msg.error, _('Error'));
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
});
|
|
2851
|
+
showWaitingDialog('Device is being reconfigure', 30);
|
|
2852
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/admin/img/tuya_rb280.png
CHANGED
|
Binary file
|