iobroker.zigbee 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/admin/admin.js +369 -191
- package/admin/index_m.html +30 -6
- package/admin/tab_m.html +31 -11
- package/io-package.json +42 -39
- package/lib/DeviceDebug.js +25 -2
- package/lib/binding.js +7 -7
- package/lib/commands.js +279 -249
- package/lib/developer.js +1 -1
- package/lib/devices.js +2 -2
- package/lib/exclude.js +1 -1
- package/lib/exposes.js +54 -24
- package/lib/groups.js +26 -28
- package/lib/localConfig.js +8 -8
- package/lib/networkmap.js +10 -2
- package/lib/statescontroller.js +134 -90
- package/lib/zbDelayedAction.js +4 -4
- package/lib/zbDeviceAvailability.js +32 -33
- package/lib/zbDeviceConfigure.js +7 -0
- package/lib/zbDeviceEvent.js +39 -6
- package/lib/zigbeecontroller.js +91 -43
- package/main.js +31 -38
- package/package.json +5 -8
- package/lib/tools.js +0 -55
package/admin/admin.js
CHANGED
|
@@ -60,9 +60,9 @@ const networkOptions = {
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
const savedSettings = [
|
|
63
|
-
'port', 'panID', 'channel', 'disableLed', 'countDown', 'groups', 'extPanID', 'precfgkey', 'transmitPower',
|
|
64
|
-
'adapterType', 'debugHerdsman', 'disableBackup', '
|
|
65
|
-
'warnOnDeviceAnnouncement', 'baudRate', 'flowCTRL', 'autostart', 'readAtAnnounce', 'startReadDelay', 'readAllAtStart',
|
|
63
|
+
'port', 'panID', 'channel', 'disableLed', 'countDown', 'groups', 'extPanID', 'precfgkey', 'transmitPower','useNewCompositeStates',
|
|
64
|
+
'adapterType', 'debugHerdsman', 'disableBackup', 'external', 'startWithInconsistent','pingTimeout','listDevicesAtStart',
|
|
65
|
+
'warnOnDeviceAnnouncement', 'baudRate', 'flowCTRL', 'autostart', 'readAtAnnounce', 'startReadDelay', 'readAllAtStart','pingCluster'
|
|
66
66
|
];
|
|
67
67
|
|
|
68
68
|
function getDeviceByID(ID) {
|
|
@@ -78,7 +78,7 @@ function getDeviceByID(ID) {
|
|
|
78
78
|
function getDevice(ieeeAddr) {
|
|
79
79
|
return devices.find((devInfo) => {
|
|
80
80
|
try {
|
|
81
|
-
return devInfo.info.device.
|
|
81
|
+
return devInfo.info.device.ieee == ieeeAddr;
|
|
82
82
|
} catch (e) {
|
|
83
83
|
//console.log("No dev with ieee " + ieeeAddr);
|
|
84
84
|
}
|
|
@@ -89,7 +89,7 @@ function getDevice(ieeeAddr) {
|
|
|
89
89
|
function getDeviceByNetwork(nwk) {
|
|
90
90
|
return devices.find((devInfo) => {
|
|
91
91
|
try {
|
|
92
|
-
return devInfo.info.device.
|
|
92
|
+
return devInfo.info.device.nwk == nwk;
|
|
93
93
|
} catch (e) {
|
|
94
94
|
//console.log("No dev with nwkAddr " + nwk);
|
|
95
95
|
}
|
|
@@ -120,7 +120,8 @@ function getCoordinatorCard(dev) {
|
|
|
120
120
|
rid = id.split('.').join('_'),
|
|
121
121
|
image = `<img src="${img_src}" width="80px">`,
|
|
122
122
|
paired = '',
|
|
123
|
-
status = dev ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : `<div class="col tool"><i class="material-icons icon-red">remove_circle</i></div>`,
|
|
123
|
+
status = coordinatorinfo.autostart ? (dev ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : `<div class="col tool"><i class="material-icons icon-red">remove_circle</i></div>`) : `<div class="col tool"><i class="material-icons icon-orange">pause_circle_filled</i></div>`,
|
|
124
|
+
//status = dev ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : `<div class="col tool"><i class="material-icons icon-red">remove_circle</i></div>`,
|
|
124
125
|
lqi_cls = dev ? getLQICls(dev.link_quality) : -1,
|
|
125
126
|
lq = (dev && dev.link_quality) ? `<div class="col tool"><i id="${rid}_link_quality_icon" class="material-icons ${lqi_cls}">network_check</i><div id="${rid}_link_quality" class="center" style="font-size:0.7em">${dev.link_quality}</div></div>` : '',
|
|
126
127
|
info = `<div style="min-height:88px; font-size: 0.8em" class="truncate">
|
|
@@ -136,13 +137,15 @@ function getCoordinatorCard(dev) {
|
|
|
136
137
|
<li><span class="label">ZHC / ZH:</span><span>${coordinatorinfo.converters} / ${coordinatorinfo.herdsman}</span></li>
|
|
137
138
|
</ul>
|
|
138
139
|
</div>`,
|
|
139
|
-
permitJoinBtn =
|
|
140
|
+
permitJoinBtn = '<div class="col tool"><button name="joinCard" class="waves-effect btn-small btn-flat right hoverable green"><i class="material-icons icon-green">leak_add</i></button></div>',
|
|
141
|
+
//permitJoinBtn = `<div class="col tool"><button name="join" class="btn-floating-sml waves-effect waves-light right hoverable green><i class="material-icons">leak_add</i></button></div>`,
|
|
140
142
|
card = `<div id="${id}" class="device">
|
|
141
143
|
<div class="card hoverable">
|
|
142
144
|
<div class="card-content zcard">
|
|
143
145
|
<span class="top right small" style="border-radius: 50%">
|
|
144
146
|
${lq}
|
|
145
147
|
${status}
|
|
148
|
+
${permitJoinBtn}
|
|
146
149
|
</span>
|
|
147
150
|
<!--/a--!>
|
|
148
151
|
<span id="dName" class="card-title truncate">${title}</span><!--${paired}--!>
|
|
@@ -150,11 +153,6 @@ function getCoordinatorCard(dev) {
|
|
|
150
153
|
${info}
|
|
151
154
|
<div class="footer right-align"></div>
|
|
152
155
|
</div>
|
|
153
|
-
<div class="card-action">
|
|
154
|
-
<div class="card-reveal-buttons">
|
|
155
|
-
${permitJoinBtn}
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
156
|
</div>
|
|
159
157
|
</div>`;
|
|
160
158
|
return card;
|
|
@@ -175,9 +173,10 @@ function getGroupCard(dev) {
|
|
|
175
173
|
}
|
|
176
174
|
}
|
|
177
175
|
devGroups[numid] = dev;
|
|
176
|
+
const roomInfo = rooms.length ? `<li><span class="labelinfo">rooms:</span><span>${rooms.join(',') || ''}</span></li>` : '';
|
|
178
177
|
const room = rooms.join(',') || ' ';
|
|
179
178
|
let memberCount = 0;
|
|
180
|
-
let info = `<div style="min-height:88px; font-size: 0.8em;
|
|
179
|
+
let info = `<div style="min-height:88px; font-size: 0.8em; overflow-y: auto" class="truncate">
|
|
181
180
|
<ul>`;
|
|
182
181
|
info = info.concat(`<li><span class="labelinfo">Group ${numid}</span></li>`);
|
|
183
182
|
if (dev.memberinfo === undefined) {
|
|
@@ -189,7 +188,7 @@ function getGroupCard(dev) {
|
|
|
189
188
|
memberCount = (dev.memberinfo.length < 8 ? dev.memberinfo.length : 7);
|
|
190
189
|
}
|
|
191
190
|
;
|
|
192
|
-
info = info.concat(`
|
|
191
|
+
info = info.concat(` ${roomInfo}</ul>
|
|
193
192
|
</div>`);
|
|
194
193
|
const image = `<img src="${dev.common.icon}" width="64px" onerror="this.onerror=null;this.src='img/unavailable.png';">`;
|
|
195
194
|
const dashCard = getDashCard(dev, dev.common.icon, memberCount > 0);
|
|
@@ -207,11 +206,11 @@ function getGroupCard(dev) {
|
|
|
207
206
|
</div>
|
|
208
207
|
<i class="left">${image}</i>
|
|
209
208
|
${info}
|
|
209
|
+
|
|
210
210
|
<div class="footer right-align"></div>
|
|
211
211
|
</div>
|
|
212
212
|
<div class="card-action">
|
|
213
213
|
<div class="card-reveal-buttons">
|
|
214
|
-
<span class="left" style="padding-top:8px">${room}</span>
|
|
215
214
|
<button name="deletegrp" class="right btn-flat btn-small">
|
|
216
215
|
<i class="material-icons icon-black">delete</i>
|
|
217
216
|
</button>
|
|
@@ -254,12 +253,13 @@ function getCard(dev) {
|
|
|
254
253
|
rooms.push(dev.rooms[r]);
|
|
255
254
|
}
|
|
256
255
|
}
|
|
257
|
-
const room = rooms.join(',') || ' ';
|
|
258
256
|
const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
|
|
259
257
|
const rid = id.split('.').join('_');
|
|
260
258
|
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
|
|
259
|
+
const groupInfo = dev.groupNames ? `<li><span class="labelinfo">groups:</span><span>${dev.groupNames || ''}</span></li>` : '';
|
|
260
|
+
const roomInfo = rooms.length ? `<li><span class="labelinfo">rooms:</span><span>${rooms.join(',') || ''}</span></li>` : '';
|
|
261
261
|
const image = `<img src="${img_src}" width="80px" onerror="this.onerror=null;this.src='img/unavailable.png';">`,
|
|
262
|
-
nwk = (dev.info && dev.info.device) ? dev.info.device.
|
|
262
|
+
nwk = (dev.info && dev.info.device) ? dev.info.device.nwk : undefined,
|
|
263
263
|
battery_cls = (isActive ? getBatteryCls(dev.battery) : ''),
|
|
264
264
|
lqi_cls = getLQICls(dev.link_quality),
|
|
265
265
|
battery = (dev.battery && isActive) ? `<div class="col tool"><i id="${rid}_battery_icon" class="material-icons ${battery_cls}">battery_std</i><div id="${rid}_battery" class="center" style="font-size:0.7em">${dev.battery}</div></div>` : '',
|
|
@@ -272,12 +272,14 @@ function getCard(dev) {
|
|
|
272
272
|
<li><span class="labelinfo">ieee:</span><span>0x${ieee}</span></li>
|
|
273
273
|
<li><span class="labelinfo">nwk:</span><span>${(nwk) ? nwk.toString() + ' (0x' + nwk.toString(16) + ')' : ''}</span></li>
|
|
274
274
|
<li><span class="labelinfo">model:</span><span>${modelUrl}</span></li>
|
|
275
|
-
|
|
275
|
+
${groupInfo}
|
|
276
|
+
${roomInfo}
|
|
276
277
|
</ul>
|
|
277
278
|
</div>`,
|
|
278
279
|
deactBtn = `<button name="swapactive" class="right btn-flat btn-small tooltipped" title="${(isActive ? 'Deactivate' : 'Activate')}"><i class="material-icons ${(isActive ? 'icon-green' : 'icon-red')}">power_settings_new</i></button>`,
|
|
279
280
|
debugBtn = `<button name="swapdebug" class="right btn-flat btn-small tooltipped" title="${(isDebug > -1 ? (isDebug > 0) ?'Automatic by '+debugDevices[isDebug-1]: 'Disable Debug' : 'Enable Debug')}"><i class="material-icons icon-${(isDebug > -1 ? (isDebug > 0 ? 'orange' : 'green') : 'gray')}">bug_report</i></button>`,
|
|
280
281
|
infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '';
|
|
282
|
+
|
|
281
283
|
const dashCard = getDashCard(dev);
|
|
282
284
|
const card = `<div id="${id}" class="device">
|
|
283
285
|
<div class="card hoverable flipable ${isActive ? '' : 'bg_red'}">
|
|
@@ -300,7 +302,7 @@ function getCard(dev) {
|
|
|
300
302
|
<div class="card-action">
|
|
301
303
|
<div class="card-reveal-buttons">
|
|
302
304
|
${infoBtn}
|
|
303
|
-
|
|
305
|
+
|
|
304
306
|
<span class="left fw_info"></span>
|
|
305
307
|
<button name="delete" class="right btn-flat btn-small tooltipped" title="Delete">
|
|
306
308
|
<i class="material-icons icon-red">delete</i>
|
|
@@ -385,7 +387,7 @@ function deleteConfirmation(id, name) {
|
|
|
385
387
|
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
386
388
|
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
387
389
|
const force = $('#force').prop('checked');
|
|
388
|
-
|
|
390
|
+
deleteZigbeeDevice(id, force);
|
|
389
391
|
});
|
|
390
392
|
$('#modaldelete').modal('open');
|
|
391
393
|
Materialize.updateTextFields();
|
|
@@ -444,29 +446,50 @@ function editName(id, name) {
|
|
|
444
446
|
|
|
445
447
|
const device_options = {};
|
|
446
448
|
const received_options = {};
|
|
449
|
+
console.warn('editName called with ' + id + ' and ' + name);
|
|
450
|
+
const dev = devices.find((d) => d._id == id);
|
|
451
|
+
$('#modaledit').find('input[id=\'d_name\']').val(name);
|
|
452
|
+
const groupables = [];
|
|
447
453
|
|
|
448
454
|
function removeOption(k) {
|
|
449
|
-
if (k && device_options.hasOwnProperty(k))
|
|
455
|
+
if (k && device_options.hasOwnProperty(k)) {
|
|
456
|
+
if (dev.info.mapped && dev.info.mapped.options && dev.info.mapped.options.includes(device_options[k].key))
|
|
457
|
+
availableOptions.push(device_options[k].key)
|
|
458
|
+
delete device_options[k];
|
|
459
|
+
}
|
|
450
460
|
}
|
|
451
461
|
|
|
452
462
|
function addOption() {
|
|
453
463
|
let idx=1;
|
|
454
464
|
let key = '';
|
|
465
|
+
const optionName = $('#option_Selector').val();
|
|
466
|
+
console.warn(`option name is ${optionName}`);
|
|
455
467
|
do {
|
|
456
468
|
key = `o${idx++}`;
|
|
457
469
|
}
|
|
458
470
|
while (device_options.hasOwnProperty(key));
|
|
459
|
-
device_options[key] = {key
|
|
471
|
+
device_options[key] = { key:optionName, value:''};
|
|
472
|
+
console.warn(`device_options: ${JSON.stringify(device_options)}`);
|
|
473
|
+
idx = availableOptions.indexOf(optionName);
|
|
474
|
+
console.warn(`idx: ${idx}, ao:${JSON.stringify(availableOptions)}, on: ${optionName}`);
|
|
475
|
+
if (idx > -1) availableOptions.splice(idx, 1);
|
|
460
476
|
}
|
|
461
477
|
|
|
462
|
-
function updateOptions() {
|
|
478
|
+
function updateOptions(candidates) {
|
|
479
|
+
if (candidates.length > 0) {
|
|
480
|
+
$('#modaledit').find('.new_options_available').removeClass('hide');
|
|
481
|
+
list2select('#option_Selector', candidates, [], (key, val) => { return val; }, (key, val) => { return val; })
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
$('#modaledit').find('.new_options_available').addClass('hide');
|
|
485
|
+
}
|
|
463
486
|
const html_options=[];
|
|
464
487
|
|
|
465
|
-
console.warn(`
|
|
488
|
+
console.warn(`option_Selector is ${JSON.stringify(device_options)}`)
|
|
466
489
|
|
|
467
490
|
for (const k in device_options) {
|
|
468
491
|
html_options.push(`<div class="row">`);
|
|
469
|
-
html_options.push(`<div class="input-field suffix col s5 m5 l5"><input id="option_key_${k}" type="text" class="value" /><label for="option_key_${k}">Option</label></div>`)
|
|
492
|
+
html_options.push(`<div class="input-field suffix col s5 m5 l5"><input disabled id="option_key_${k}" type="text" class="value" /><label for="option_key_${k}">Option</label></div>`)
|
|
470
493
|
html_options.push(`<div class="input-field suffix col s5 m5 l5"><input id="option_value_${k}" type="text" class="value" /><label for="option_value_${k}">Value</label></div>`)
|
|
471
494
|
html_options.push(`<div class="col"><a id="option_rem_${k}" class='btn' ><i class="material-icons">remove_circle</i></a></div>`);
|
|
472
495
|
html_options.push(`</div>`)
|
|
@@ -480,11 +503,11 @@ function editName(id, name) {
|
|
|
480
503
|
$(`#option_key_${k}`).val(device_options[k].key);
|
|
481
504
|
$(`#option_value_${k}`).val(device_options[k].value);
|
|
482
505
|
$(`#option_rem_${k}`).unbind('click');
|
|
483
|
-
$(`#option_rem_${k}`).click(() => { removeOption(k); updateOptions() });
|
|
506
|
+
$(`#option_rem_${k}`).click(() => { removeOption(k); updateOptions(availableOptions) });
|
|
484
507
|
}
|
|
485
508
|
}
|
|
486
509
|
else {
|
|
487
|
-
$('#modaledit').find('.options_available').addClass('hide');
|
|
510
|
+
if (candidates.length == 0) $('#modaledit').find('.options_available').addClass('hide');
|
|
488
511
|
}
|
|
489
512
|
}
|
|
490
513
|
|
|
@@ -513,18 +536,15 @@ function editName(id, name) {
|
|
|
513
536
|
|
|
514
537
|
|
|
515
538
|
|
|
516
|
-
console.warn('editName called with ' + id + ' and ' + name);
|
|
517
|
-
const dev = devices.find((d) => d._id == id);
|
|
518
|
-
$('#modaledit').find('input[id=\'d_name\']').val(name);
|
|
519
|
-
const groupables = [];
|
|
520
539
|
if (dev && dev.info && dev.info.endpoints) {
|
|
521
540
|
for (const ep of dev.info.endpoints) {
|
|
522
|
-
if (ep.
|
|
541
|
+
if (ep.input_clusters.includes(4)) {
|
|
523
542
|
groupables.push({epid: EndPointIDfromEndPoint(ep), ep: ep, memberOf: []});
|
|
524
543
|
}
|
|
525
544
|
}
|
|
526
545
|
}
|
|
527
546
|
const numEP = groupables.length;
|
|
547
|
+
const availableOptions = (dev.info.mapped ? dev.info.mapped.options.slice() || []:[]);
|
|
528
548
|
|
|
529
549
|
if (numEP > 0) {
|
|
530
550
|
$('#modaledit').find('.groups_available').removeClass('hide');
|
|
@@ -571,7 +591,7 @@ function editName(id, name) {
|
|
|
571
591
|
sendTo(namespace, 'getLocalConfigItems', { target:id, global:false, key:'options' }, function (msg) {
|
|
572
592
|
if (msg) {
|
|
573
593
|
if (msg.error) showMessage(msg.error, '_Error');
|
|
574
|
-
console.warn(`return is ${msg}`)
|
|
594
|
+
console.warn(`return is ${JSON.stringify(msg)}`)
|
|
575
595
|
Object.keys(device_options).forEach(key => delete device_options[key]);
|
|
576
596
|
Object.keys(received_options).forEach(key => delete received_options[key]);
|
|
577
597
|
if (typeof msg.options === 'object') {
|
|
@@ -579,12 +599,16 @@ function editName(id, name) {
|
|
|
579
599
|
let cnt = 1;
|
|
580
600
|
for (const key in msg.options)
|
|
581
601
|
{
|
|
602
|
+
const idx = availableOptions.indexOf(key);
|
|
603
|
+
console.warn(`key ${key} : index : ${idx}`);
|
|
604
|
+
if (idx > -1) availableOptions.splice(idx,1);
|
|
582
605
|
received_options[key]=msg.options[key];
|
|
583
606
|
device_options[`o${cnt}`] = { key:key, value:msg.options[key]}
|
|
584
607
|
cnt++;
|
|
585
608
|
}
|
|
586
609
|
}
|
|
587
|
-
|
|
610
|
+
console.warn(`avo ${JSON.stringify(availableOptions)}, mapped: ${JSON.stringify(dev.info.mapped.options)}`);
|
|
611
|
+
updateOptions(availableOptions);
|
|
588
612
|
|
|
589
613
|
} else showMessage('callback without message');
|
|
590
614
|
});
|
|
@@ -593,7 +617,7 @@ function editName(id, name) {
|
|
|
593
617
|
$('#modaledit a.btn[name=\'add_options\']').click(() => {
|
|
594
618
|
getOptionsFromUI(device_options, received_options);
|
|
595
619
|
addOption();
|
|
596
|
-
updateOptions()
|
|
620
|
+
updateOptions(availableOptions)
|
|
597
621
|
});
|
|
598
622
|
$('#modaledit a.btn[name=\'save\']').click(() => {
|
|
599
623
|
const newName = $('#modaledit').find('input[id=\'d_name\']').val();
|
|
@@ -634,8 +658,8 @@ function GenerateGroupChange(oldmembers, newmembers) {
|
|
|
634
658
|
return grpchng;
|
|
635
659
|
}
|
|
636
660
|
|
|
637
|
-
function
|
|
638
|
-
sendTo(namespace, '
|
|
661
|
+
function deleteZigbeeDevice(id, force) {
|
|
662
|
+
sendTo(namespace, 'deleteZigbeeDevice', {id: id, force: force}, function (msg) {
|
|
639
663
|
closeWaitingDialog();
|
|
640
664
|
if (msg) {
|
|
641
665
|
if (msg.error) {
|
|
@@ -719,12 +743,12 @@ function showDevices() {
|
|
|
719
743
|
html += card;
|
|
720
744
|
continue;
|
|
721
745
|
};
|
|
722
|
-
if (d.info && d.info.device && d.info.device.
|
|
746
|
+
if (d.info && d.info.device && d.info.device.type == 'Coordinator') {
|
|
723
747
|
hasCoordinator=true;
|
|
724
748
|
const card = getCoordinatorCard(d);
|
|
725
749
|
html += card;
|
|
726
750
|
} else {
|
|
727
|
-
//if (d.groups && d.info && d.info.device.
|
|
751
|
+
//if (d.groups && d.info && d.info.device.type == "Router") {
|
|
728
752
|
if (d.groups) {
|
|
729
753
|
//devGroups[d._id] = d.groups;
|
|
730
754
|
if (typeof d.groups.map == 'function') {
|
|
@@ -819,13 +843,18 @@ function showDevices() {
|
|
|
819
843
|
const name = getDevName(dev_block);
|
|
820
844
|
editGroup(id, name, false);
|
|
821
845
|
});
|
|
822
|
-
$('button
|
|
846
|
+
$('button[name=\'joinCard\']').click(function () {
|
|
823
847
|
const dev_block = $(this).parents('div.device');
|
|
824
848
|
if (!$('#pairing').hasClass('pulse')) {
|
|
825
849
|
joinProcess(getDevId(dev_block));
|
|
826
850
|
}
|
|
827
851
|
showPairingProcess();
|
|
828
852
|
});
|
|
853
|
+
$('button[name=\'deviceQuery\']').click(function () {
|
|
854
|
+
const dev_block = $(this).parents('div.device');
|
|
855
|
+
sendTo(namespace, 'setState', {id: `${getDevId(dev_block)}.device_query`, val: true}, function (data) {
|
|
856
|
+
//console.log(data);
|
|
857
|
+
}); });
|
|
829
858
|
$('#modalpairing a.btn[name=\'extendpairing\']').click(function () {
|
|
830
859
|
letsPairing();
|
|
831
860
|
});
|
|
@@ -856,6 +885,14 @@ function showDevices() {
|
|
|
856
885
|
translateAll();
|
|
857
886
|
}
|
|
858
887
|
|
|
888
|
+
function downloadIcons() {
|
|
889
|
+
sendTo(namespace, 'downloadIcons', {}, function (msg) {
|
|
890
|
+
if (msg && msg.msg) {
|
|
891
|
+
showMessage(msg.msg, _('Result'));
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
|
|
859
896
|
function checkFwUpdate() {
|
|
860
897
|
const deviceCards = getDeviceCards();
|
|
861
898
|
const getFwInfoNode = function (deviceCard) {
|
|
@@ -1080,6 +1117,7 @@ function HtmlFromInDebugMessages(messages, devID, filter) {
|
|
|
1080
1117
|
const Html = [];
|
|
1081
1118
|
const filterSet = new Set();
|
|
1082
1119
|
let isodd = true;
|
|
1120
|
+
const buttonList = [];
|
|
1083
1121
|
if (dbgMsghide.has('i_'+devID)) {
|
|
1084
1122
|
console.warn('in all filtered out')
|
|
1085
1123
|
Html.push(' ')
|
|
@@ -1094,8 +1132,11 @@ function HtmlFromInDebugMessages(messages, devID, filter) {
|
|
|
1094
1132
|
const redText = (item.errors && item.errors.length > 0 ? ' id="dbgred"' : '');
|
|
1095
1133
|
idx--;
|
|
1096
1134
|
const LHtml = [(`<tr id="${isodd ? 'dbgrowodd' : 'dbgroweven'}">`)];
|
|
1097
|
-
if (idx==0)
|
|
1098
|
-
|
|
1135
|
+
if (idx==0) {
|
|
1136
|
+
const msgbutton = `<a id="lx_${item.dataID}" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Messages from ${new Date(item.dataID).toLocaleTimeString()}"><i class="material-icons large">speaker_notes</i></a>`
|
|
1137
|
+
buttonList.push(item.dataID)
|
|
1138
|
+
LHtml.push(`<td${rowspan}>${msgbutton}</td><td${rowspan}>${safestring(item.payload)}</td>`);
|
|
1139
|
+
}
|
|
1099
1140
|
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>`);
|
|
1100
1141
|
IHtml.unshift(...LHtml)
|
|
1101
1142
|
}
|
|
@@ -1108,7 +1149,7 @@ function HtmlFromInDebugMessages(messages, devID, filter) {
|
|
|
1108
1149
|
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>`
|
|
1109
1150
|
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>`
|
|
1110
1151
|
const dataHide = dbgMsgfilter.has('hi_'+devID) ? 'Data hidden' : ' ';
|
|
1111
|
-
return
|
|
1152
|
+
return {html:`<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>`, buttonList };
|
|
1112
1153
|
}
|
|
1113
1154
|
|
|
1114
1155
|
|
|
@@ -1116,6 +1157,7 @@ function HtmlFromOutDebugMessages(messages, devID, filter) {
|
|
|
1116
1157
|
const Html = [];
|
|
1117
1158
|
const filterSet = new Set();
|
|
1118
1159
|
let isodd=true;
|
|
1160
|
+
const buttonList = [];
|
|
1119
1161
|
if (dbgMsghide.has('o_'+devID)) {
|
|
1120
1162
|
console.warn('out all filtered out')
|
|
1121
1163
|
Html.push(' ')
|
|
@@ -1131,8 +1173,11 @@ function HtmlFromOutDebugMessages(messages, devID, filter) {
|
|
|
1131
1173
|
const redText = (item.errors && item.errors.length > 0 ? ' id="dbgred"' : '');
|
|
1132
1174
|
const LHtml = [(`<tr id="${isodd ? 'dbgrowodd' : 'dbgroweven'}">`)];
|
|
1133
1175
|
idx--;
|
|
1134
|
-
if (idx==0)
|
|
1135
|
-
|
|
1176
|
+
if (idx==0) {
|
|
1177
|
+
const msgbutton = `<a id="lx_${item.dataID}" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Messages from ${new Date(item.dataID).toLocaleTimeString()}"><i class="material-icons large">speaker_notes</i></a>`
|
|
1178
|
+
LHtml.push(`<td${rowspan}>${msgbutton}</td><td${rowspan}>${safestring(item.payload)}</td>`);
|
|
1179
|
+
buttonList.push(item.dataID)
|
|
1180
|
+
}
|
|
1136
1181
|
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>`);
|
|
1137
1182
|
IHtml.unshift(...LHtml);
|
|
1138
1183
|
|
|
@@ -1146,22 +1191,24 @@ function HtmlFromOutDebugMessages(messages, devID, filter) {
|
|
|
1146
1191
|
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>`
|
|
1147
1192
|
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>`
|
|
1148
1193
|
const dataHide = dbgMsgfilter.has('ho_'+devID) ? 'Data hidden' : ' ';
|
|
1149
|
-
return
|
|
1194
|
+
return { html:`<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>`, buttonList};
|
|
1150
1195
|
}
|
|
1151
1196
|
|
|
1152
1197
|
|
|
1153
1198
|
function displayDebugMessages(msg) {
|
|
1154
1199
|
const buttonNames = [];
|
|
1200
|
+
const idButtons = [];
|
|
1155
1201
|
if (msg.byId) {
|
|
1156
1202
|
const dbgData = msg.byId;
|
|
1157
1203
|
const keys = Object.keys(dbgData);
|
|
1158
1204
|
const keylength = keys.length;
|
|
1159
1205
|
const Html = [];
|
|
1160
1206
|
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>`;
|
|
1161
|
-
const
|
|
1207
|
+
const dbutton = `<a id="d_all" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons icon-yellowlarge">delete_forever</i></a>`;
|
|
1208
|
+
const fbutton = `<a id="f_all" class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">${dbgMsgfilter.size != 0 ? 'filter_list' : 'format_align_justify' }</i></a>`;
|
|
1162
1209
|
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>`;
|
|
1163
1210
|
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>`;
|
|
1164
|
-
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>`);
|
|
1211
|
+
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><td>${dbutton}</td></tr></thead><tbody>`);
|
|
1165
1212
|
if (!keylength) {
|
|
1166
1213
|
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>')
|
|
1167
1214
|
$('#dbg_data_list').html(Html.join(''));
|
|
@@ -1176,20 +1223,28 @@ function displayDebugMessages(msg) {
|
|
|
1176
1223
|
const modelUrl = (type_url === 'unknown') ? 'unknown' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${image}</a>`;
|
|
1177
1224
|
const devName = (dev && dev.common && dev.common.name) ? dev.common.name : 'unnamed';
|
|
1178
1225
|
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>`
|
|
1226
|
+
const dbutton = `<a id="d_${devID}" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons icon-yellow large">delete_forever</i></a>`;
|
|
1179
1227
|
buttonNames.push(devID);
|
|
1180
|
-
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
|
|
1228
|
+
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>${button}</td><td>${dbutton}</td></tr></thead><tbody>`);
|
|
1181
1229
|
if (dbgData[devID].IN.length > 0) {
|
|
1182
|
-
|
|
1230
|
+
const indata = HtmlFromInDebugMessages(dbgData[devID].IN, devID, dbgMsgfilter.has('i_'+devID));
|
|
1231
|
+
Html.push(`${indata.html}`);
|
|
1232
|
+
idButtons.push(...indata.buttonList)
|
|
1183
1233
|
}
|
|
1184
1234
|
if (dbgData[devID].OUT.length > 0) {
|
|
1185
|
-
|
|
1235
|
+
const outdata = HtmlFromOutDebugMessages(dbgData[devID].OUT, devID, dbgMsgfilter.has('o_'+devID));
|
|
1236
|
+
Html.push(`${outdata.html}`);
|
|
1237
|
+
idButtons.push(...outdata.buttonList)
|
|
1186
1238
|
}
|
|
1187
1239
|
Html.push('</tbody></table></li>');
|
|
1188
1240
|
}
|
|
1189
1241
|
$('#dbg_data_list').html(Html.join(''));
|
|
1190
1242
|
}
|
|
1191
1243
|
$(`#e_all`).click(function () {
|
|
1192
|
-
getDebugMessages();
|
|
1244
|
+
getDebugMessages(false);
|
|
1245
|
+
});
|
|
1246
|
+
$(`#d_all`).click(function () {
|
|
1247
|
+
getDebugMessages(true, 'all');
|
|
1193
1248
|
});
|
|
1194
1249
|
$(`#l_all`).click(function () {
|
|
1195
1250
|
debugInLog = !debugInLog;
|
|
@@ -1221,7 +1276,10 @@ function displayDebugMessages(msg) {
|
|
|
1221
1276
|
});
|
|
1222
1277
|
for (const b of buttonNames) {
|
|
1223
1278
|
$(`#e_${b}`).click(function () {
|
|
1224
|
-
getDebugMessages();
|
|
1279
|
+
getDebugMessages(false);
|
|
1280
|
+
});
|
|
1281
|
+
$(`#d_${b}`).click(function () {
|
|
1282
|
+
getDebugMessages(true, b);
|
|
1225
1283
|
});
|
|
1226
1284
|
$(`#o_${b}`).click(function () {
|
|
1227
1285
|
if (dbgMsgfilter.has(`o_${b}`)) dbgMsgfilter.delete(`o_${b}`); else dbgMsgfilter.add(`o_${b}`);
|
|
@@ -1240,76 +1298,167 @@ function displayDebugMessages(msg) {
|
|
|
1240
1298
|
displayDebugMessages(debugMessages);
|
|
1241
1299
|
});
|
|
1242
1300
|
}
|
|
1301
|
+
for (const b of idButtons) {
|
|
1302
|
+
console.warn(`trying to add link to button ${b}`);
|
|
1303
|
+
$(`#lx_${b}`).click(function() { showMessageList(b)});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
function showNamedMessages(messages, title, icon, timestamp) {
|
|
1309
|
+
// noinspection JSJQueryEfficiency
|
|
1310
|
+
let $dialogMessage = $('#dialog-message');
|
|
1311
|
+
if (!$dialogMessage.length) {
|
|
1312
|
+
$('body').append(
|
|
1313
|
+
'<div class="m"><div id="dialog-message" class="modal modal-fixed-footer">' +
|
|
1314
|
+
' <div class="modal-content">' +
|
|
1315
|
+
' <h6 class="dialog-title title"></h6>' +
|
|
1316
|
+
' <p><i class="large material-icons dialog-icon"></i><span class="dialog-text"></span></p>' +
|
|
1317
|
+
' </div>' +
|
|
1318
|
+
' <div class="modal-footer">' +
|
|
1319
|
+
' <a class="modal-action modal-close waves-effect waves-green btn-flat translate">Ok</a>' +
|
|
1320
|
+
' </div>' +
|
|
1321
|
+
'</div></div>');
|
|
1322
|
+
$dialogMessage = $('#dialog-message');
|
|
1323
|
+
}
|
|
1324
|
+
if (icon) {
|
|
1325
|
+
$dialogMessage.find('.dialog-icon')
|
|
1326
|
+
.show()
|
|
1327
|
+
.html(icon);
|
|
1328
|
+
} else {
|
|
1329
|
+
$dialogMessage.find('.dialog-icon').hide();
|
|
1330
|
+
}
|
|
1331
|
+
if (title) {
|
|
1332
|
+
$dialogMessage.find('.dialog-title').html(title).show();
|
|
1333
|
+
} else {
|
|
1334
|
+
$dialogMessage.find('.dialog-title').hide();
|
|
1335
|
+
}
|
|
1336
|
+
const lihtml = ['```<br><ul>'];
|
|
1337
|
+
for (const key of Object.keys(messages)) {
|
|
1338
|
+
lihtml.push(`<li>${key}: ${messages[key]}</li>`)
|
|
1339
|
+
}
|
|
1340
|
+
lihtml.push('</ul><br>```')
|
|
1341
|
+
$dialogMessage.find('.dialog-text').html(lihtml);
|
|
1342
|
+
$dialogMessage.modal().modal('open');
|
|
1343
|
+
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
function showMessageList(msgId) {
|
|
1347
|
+
console.warn(`trying to show messages for ${msgId}`);
|
|
1348
|
+
console.warn(JSON.stringify(debugMessages));
|
|
1349
|
+
for (const devId of Object.keys(debugMessages.byId)) {
|
|
1350
|
+
for (const id of debugMessages.byId[devId].IN) {
|
|
1351
|
+
if (id.dataID == msgId) {
|
|
1352
|
+
console.warn(`showing messages for ${id.type} ${devId}`);
|
|
1353
|
+
showNamedMessages(id.messages, `Messages from ${new Date(msgId).toLocaleTimeString()} for device ${devId}`);
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
for (const id of debugMessages.byId[devId].OUT) {
|
|
1358
|
+
if (id.dataID == msgId) {
|
|
1359
|
+
console.warn(`showing messages for ${msgId}`);
|
|
1360
|
+
showNamedMessages(id.messages, `Messages from ${new Date(msgId).toLocaleTimeString()} for device ${devId}`);
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1243
1364
|
}
|
|
1365
|
+
console.warn(`nothing to show`);
|
|
1366
|
+
|
|
1367
|
+
|
|
1244
1368
|
}
|
|
1245
1369
|
|
|
1246
|
-
function getDebugMessages() {
|
|
1247
|
-
sendTo(namespace, 'getDebugMessages', { inlog: debugInLog }, function(msg) {
|
|
1370
|
+
function getDebugMessages(deleteBeforeRead, deleteSelected) {
|
|
1371
|
+
sendTo(namespace, 'getDebugMessages', { inlog: debugInLog, del:deleteBeforeRead ? deleteSelected : '' }, function(msg) {
|
|
1248
1372
|
debugMessages = msg;
|
|
1249
1373
|
if (msg) displayDebugMessages(debugMessages)
|
|
1250
1374
|
})
|
|
1251
1375
|
}
|
|
1252
1376
|
|
|
1253
|
-
|
|
1377
|
+
const lockout = {
|
|
1378
|
+
timeoutid:undefined,
|
|
1379
|
+
isActive:false,
|
|
1380
|
+
};
|
|
1254
1381
|
function getDevices() {
|
|
1255
1382
|
console.warn('getDevices called')
|
|
1256
|
-
sendTo(namespace, 'getCoordinatorInfo', {}, function (msg) {
|
|
1257
|
-
console.warn(`getCoordinatorInfo returned ${JSON.stringify(msg)}`)
|
|
1258
|
-
if (msg) {
|
|
1259
|
-
console.warn(JSON.stringify(msg))
|
|
1260
|
-
if (msg.error) {
|
|
1261
|
-
errorData.push(msg.error);
|
|
1262
|
-
delete msg.error;
|
|
1263
|
-
isHerdsmanRunning = false;
|
|
1264
|
-
} else {
|
|
1265
|
-
isHerdsmanRunning = true;
|
|
1266
|
-
}
|
|
1267
|
-
coordinatorinfo = msg;
|
|
1268
|
-
updateStartButton()
|
|
1269
|
-
}
|
|
1270
|
-
sendTo(namespace, 'getDevices', {}, function (msg) {
|
|
1271
|
-
if (msg) {
|
|
1272
|
-
devices = msg.devices ? msg.devices : [];
|
|
1273
|
-
// check if stashed error messages are sent alongside
|
|
1274
|
-
if (msg.clean)
|
|
1275
|
-
$('#state_cleanup_btn').removeClass('hide');
|
|
1276
|
-
else
|
|
1277
|
-
$('#state_cleanup_btn').addClass('hide');
|
|
1278
|
-
if (msg.errors && msg.errors.length > 0) {
|
|
1279
|
-
$('#show_errors_btn').removeClass('hide');
|
|
1280
|
-
errorData = msg.errors;
|
|
1281
|
-
}
|
|
1282
|
-
else {
|
|
1283
|
-
$('#show_errors_btn').addClass('hide');
|
|
1284
|
-
}
|
|
1285
1383
|
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
else
|
|
1292
|
-
debugDevices = [];
|
|
1293
|
-
if (debugMessages.byId) {
|
|
1294
|
-
debugMessages.byId = msg;
|
|
1295
|
-
if (msg) displayDebugMessages(debugMessages)
|
|
1296
|
-
}
|
|
1384
|
+
function sendForData() {
|
|
1385
|
+
sendTo(namespace, 'getCoordinatorInfo', {}, function (msg) {
|
|
1386
|
+
console.warn(`getCoordinatorInfo returned ${JSON.stringify(msg)}`)
|
|
1387
|
+
if (msg) {
|
|
1388
|
+
console.warn(JSON.stringify(msg))
|
|
1297
1389
|
if (msg.error) {
|
|
1298
1390
|
errorData.push(msg.error);
|
|
1391
|
+
delete msg.error;
|
|
1299
1392
|
isHerdsmanRunning = false;
|
|
1300
|
-
updateStartButton();
|
|
1301
|
-
showDevices();
|
|
1302
1393
|
} else {
|
|
1303
1394
|
isHerdsmanRunning = true;
|
|
1304
|
-
updateStartButton();
|
|
1305
|
-
showDevices();
|
|
1306
|
-
getDebugMessages();
|
|
1307
|
-
getExclude();
|
|
1308
|
-
getBinding();
|
|
1309
1395
|
}
|
|
1396
|
+
coordinatorinfo = msg;
|
|
1397
|
+
updateStartButton()
|
|
1310
1398
|
}
|
|
1399
|
+
sendTo(namespace, 'getDevices', {}, function (msg) {
|
|
1400
|
+
if (msg) {
|
|
1401
|
+
devices = msg.devices ? msg.devices : [];
|
|
1402
|
+
// check if stashed error messages are sent alongside
|
|
1403
|
+
if (msg.clean)
|
|
1404
|
+
$('#state_cleanup_btn').removeClass('hide');
|
|
1405
|
+
else
|
|
1406
|
+
$('#state_cleanup_btn').addClass('hide');
|
|
1407
|
+
if (msg.errors && msg.errors.length > 0) {
|
|
1408
|
+
$('#show_errors_btn').removeClass('hide');
|
|
1409
|
+
errorData = msg.errors;
|
|
1410
|
+
}
|
|
1411
|
+
else {
|
|
1412
|
+
$('#show_errors_btn').addClass('hide');
|
|
1413
|
+
}
|
|
1414
|
+
let newDebugMessages = false;
|
|
1415
|
+
|
|
1416
|
+
//check if debug messages are sent alongside
|
|
1417
|
+
if (msg && typeof (msg.debugDevices == 'array')) {
|
|
1418
|
+
debugDevices = msg.debugDevices;
|
|
1419
|
+
console.warn('debug devices is sent')
|
|
1420
|
+
}
|
|
1421
|
+
else
|
|
1422
|
+
debugDevices = [];
|
|
1423
|
+
if (debugMessages.byId) {
|
|
1424
|
+
newDebugMessages = true;
|
|
1425
|
+
console.warn('having debug messages');
|
|
1426
|
+
debugMessages.byId = msg;
|
|
1427
|
+
if (msg) displayDebugMessages(debugMessages)
|
|
1428
|
+
}
|
|
1429
|
+
lockout.isActive = false;
|
|
1430
|
+
if (msg.error) {
|
|
1431
|
+
errorData.push(msg.error);
|
|
1432
|
+
isHerdsmanRunning = false;
|
|
1433
|
+
updateStartButton();
|
|
1434
|
+
showDevices();
|
|
1435
|
+
} else {
|
|
1436
|
+
isHerdsmanRunning = true;
|
|
1437
|
+
updateStartButton();
|
|
1438
|
+
showDevices();
|
|
1439
|
+
if (!newDebugMessages) {
|
|
1440
|
+
console.warn('getting debug messages');
|
|
1441
|
+
getDebugMessages();
|
|
1442
|
+
}
|
|
1443
|
+
//getExclude();
|
|
1444
|
+
getBinding();
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1311
1448
|
});
|
|
1312
|
-
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
if (lockout.timeoutid) {
|
|
1452
|
+
clearTimeout(lockout.timeoutid);
|
|
1453
|
+
console.warn('clearing getDevices timeout')
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
setTimeout(() => {
|
|
1457
|
+
lockout.isActive = true;
|
|
1458
|
+
lockout.timeoutid = undefined;
|
|
1459
|
+
sendForData();
|
|
1460
|
+
}, 100);
|
|
1461
|
+
|
|
1313
1462
|
}
|
|
1314
1463
|
|
|
1315
1464
|
function getNamedColors() {
|
|
@@ -1331,10 +1480,10 @@ function getDeviceCard(devId) {
|
|
|
1331
1480
|
return $('#devices').find(`div[id='${namespace}.${devId}']`);
|
|
1332
1481
|
}
|
|
1333
1482
|
|
|
1334
|
-
function getMap() {
|
|
1483
|
+
function getMap(rebuild) {
|
|
1335
1484
|
$('#refresh').addClass('disabled');
|
|
1336
1485
|
if (isHerdsmanRunning) {
|
|
1337
|
-
sendTo(namespace, 'getMap', {}, function (msg) {
|
|
1486
|
+
sendTo(namespace, 'getMap', { forcebuild:rebuild}, function (msg) {
|
|
1338
1487
|
$('#refresh').removeClass('disabled');
|
|
1339
1488
|
if (msg) {
|
|
1340
1489
|
if (msg.error) {
|
|
@@ -1404,6 +1553,7 @@ function load(settings, onChange) {
|
|
|
1404
1553
|
settings.baudRate = 115200;
|
|
1405
1554
|
}
|
|
1406
1555
|
if (settings.autostart === undefined) settings.autostart = false;
|
|
1556
|
+
if (typeof settings.pingCluster != 'string') settings.pingCluster = settings.disablePing ? 'off' : 'default';
|
|
1407
1557
|
|
|
1408
1558
|
// example: select elements with id=key and class=value and insert value
|
|
1409
1559
|
for (const key in settings) {
|
|
@@ -1477,6 +1627,9 @@ function load(settings, onChange) {
|
|
|
1477
1627
|
$('#show_errors_btn').click(function () {
|
|
1478
1628
|
showMessage(errorData.join('<br>'), 'Stashed error messages');
|
|
1479
1629
|
});
|
|
1630
|
+
$('#download_icons_btn').click(function () {
|
|
1631
|
+
showMessage(downloadIcons());
|
|
1632
|
+
});
|
|
1480
1633
|
$('#fw_check_btn').click(function () {
|
|
1481
1634
|
checkFwUpdate();
|
|
1482
1635
|
});
|
|
@@ -1493,7 +1646,11 @@ function load(settings, onChange) {
|
|
|
1493
1646
|
});
|
|
1494
1647
|
|
|
1495
1648
|
$('#refresh').click(function () {
|
|
1496
|
-
getMap();
|
|
1649
|
+
getMap(false);
|
|
1650
|
+
});
|
|
1651
|
+
$('#regenerate').click(function () {
|
|
1652
|
+
getMap(true);
|
|
1653
|
+
$('#modalviewconfig').modal('close');
|
|
1497
1654
|
});
|
|
1498
1655
|
|
|
1499
1656
|
$('#reset-btn').click(function () {
|
|
@@ -1505,7 +1662,9 @@ function load(settings, onChange) {
|
|
|
1505
1662
|
});
|
|
1506
1663
|
|
|
1507
1664
|
$('#ErrorNotificationBtn').click(function () {
|
|
1508
|
-
if (!isHerdsmanRunning)
|
|
1665
|
+
if (!isHerdsmanRunning) {
|
|
1666
|
+
doTestStart(!isHerdsmanRunning, true);
|
|
1667
|
+
}
|
|
1509
1668
|
})
|
|
1510
1669
|
|
|
1511
1670
|
$('#viewconfig').click(function () {
|
|
@@ -1619,10 +1778,10 @@ function showPairingProcess() {
|
|
|
1619
1778
|
Materialize.updateTextFields();
|
|
1620
1779
|
}
|
|
1621
1780
|
|
|
1622
|
-
function doTestStart(start) {
|
|
1781
|
+
function doTestStart(start, interactive) {
|
|
1623
1782
|
updateStartButton(true);
|
|
1624
1783
|
if (start) {
|
|
1625
|
-
const ovr = { extPanID:$('#extPanID.value').val(),
|
|
1784
|
+
const ovr = interactive ? {} : { extPanID:$('#extPanID.value').val(),
|
|
1626
1785
|
panID: $('#PanID.value').val(),
|
|
1627
1786
|
channel: $('#channel.value').val(),
|
|
1628
1787
|
port: $('#port.value').val(),
|
|
@@ -1633,12 +1792,18 @@ function doTestStart(start) {
|
|
|
1633
1792
|
};
|
|
1634
1793
|
// $('#testStartStart').addClass('disabled');
|
|
1635
1794
|
messages = [];
|
|
1795
|
+
if (interactive) showWaitingDialog('Trying to start the zigbee subsystem manually', 120);
|
|
1636
1796
|
sendTo(namespace, 'testConnect', { start:true, zigbeeOptions:ovr }, function(msg) {
|
|
1637
1797
|
if (msg) {
|
|
1798
|
+
closeWaitingDialog();
|
|
1799
|
+
isHerdsmanRunning = msg.status;
|
|
1800
|
+
updateStartButton(false);
|
|
1638
1801
|
if (msg.status)
|
|
1639
1802
|
$('#testStartStop').removeClass('disabled');
|
|
1640
|
-
else
|
|
1641
|
-
$
|
|
1803
|
+
else {
|
|
1804
|
+
//showMessage(`The zigbee subsystem is not running. Please ensure that the configuration is correct. ${msg.error ? 'Error on start-Attempt ' + msg.error.message : ''}`);
|
|
1805
|
+
$('#testStartStop').removeClass('disabled');
|
|
1806
|
+
}
|
|
1642
1807
|
}
|
|
1643
1808
|
})
|
|
1644
1809
|
}
|
|
@@ -1689,8 +1854,8 @@ function updateStartButton(block) {
|
|
|
1689
1854
|
$('#deleteNVRam-btn').addClass('disabled');
|
|
1690
1855
|
$('#ErrorNotificationBtn').removeClass('hide')
|
|
1691
1856
|
$('#ErrorNotificationBtn').removeClass('blinking')
|
|
1692
|
-
$('#
|
|
1693
|
-
$('#
|
|
1857
|
+
$('#ErrorNotificationBtn').removeClass('red')
|
|
1858
|
+
$('#ErrorNotificationBtn').addClass('orange')
|
|
1694
1859
|
return;
|
|
1695
1860
|
}
|
|
1696
1861
|
if (isHerdsmanRunning)
|
|
@@ -1707,8 +1872,8 @@ function updateStartButton(block) {
|
|
|
1707
1872
|
//$('#pairing').removeClass('hide');
|
|
1708
1873
|
}
|
|
1709
1874
|
else {
|
|
1710
|
-
$('#
|
|
1711
|
-
$('#
|
|
1875
|
+
$('#ErrorNotificationBtn').addClass('red')
|
|
1876
|
+
$('#ErrorNotificationBtn').removeClass('orange')
|
|
1712
1877
|
$('#ErrorNotificationBtn').removeClass('hide')
|
|
1713
1878
|
$('#ErrorNotificationBtn').addClass('blinking');
|
|
1714
1879
|
$('#show_test_run').removeClass('disabled');
|
|
@@ -1862,7 +2027,7 @@ function showNetworkMap(devices, map) {
|
|
|
1862
2027
|
borderWidth: 1,
|
|
1863
2028
|
borderWidthSelected: 4,
|
|
1864
2029
|
};
|
|
1865
|
-
if (dev.info && dev.info.device.
|
|
2030
|
+
if (dev.info && dev.info.device.type == 'Coordinator') {
|
|
1866
2031
|
// node.shape = 'star';
|
|
1867
2032
|
node.image = 'zigbee.png';
|
|
1868
2033
|
node.label = 'Coordinator';
|
|
@@ -2022,7 +2187,7 @@ function showNetworkMap(devices, map) {
|
|
|
2022
2187
|
|
|
2023
2188
|
if (node) {
|
|
2024
2189
|
node.font = {color: '#ff0000'};
|
|
2025
|
-
if (dev.info && dev.info.device.
|
|
2190
|
+
if (dev.info && dev.info.device && dev.info.device.type == 'Coordinator') {
|
|
2026
2191
|
node.font = {color: '#00ff00'};
|
|
2027
2192
|
}
|
|
2028
2193
|
nodesArray.push(node);
|
|
@@ -2187,35 +2352,37 @@ function loadDeveloperTab() {
|
|
|
2187
2352
|
updateSelect('#dev', devices,
|
|
2188
2353
|
function (key, device) {
|
|
2189
2354
|
if (device.hasOwnProperty('info')) {
|
|
2190
|
-
if (device.info.device.
|
|
2355
|
+
if (device.info.device && device.info.device.type === 'Coordinator') {
|
|
2191
2356
|
return null;
|
|
2192
2357
|
}
|
|
2193
|
-
|
|
2358
|
+
if (device.common.type === 'group') return null;
|
|
2359
|
+
return `${device.common.name} (${device.info.device.ieee})`;
|
|
2194
2360
|
} else { // fallback if device in list but not paired
|
|
2195
2361
|
return device.common.name + ' ' + device.native.id;
|
|
2196
2362
|
}
|
|
2197
2363
|
},
|
|
2198
2364
|
function (key, device) {
|
|
2199
|
-
return device.
|
|
2200
|
-
});
|
|
2201
|
-
// add groups to device selector
|
|
2202
|
-
const groupList = [];
|
|
2203
|
-
for (const key in groups) {
|
|
2204
|
-
groupList.push({
|
|
2205
|
-
_id: namespace + '.' + key.toString(16).padStart(16, '0'),
|
|
2206
|
-
groupId: key,
|
|
2207
|
-
groupName: groups[key]
|
|
2365
|
+
return device.native.id;
|
|
2208
2366
|
});
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2367
|
+
/*
|
|
2368
|
+
const groupList = [];
|
|
2369
|
+
for (const key in groups) {
|
|
2370
|
+
groupList.push({
|
|
2371
|
+
id: namespace + '.' + key.toString(16).padStart(16, '0'),
|
|
2372
|
+
groupId: key,
|
|
2373
|
+
groupName: groups[key]
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2376
|
+
updateSelect('#dev', groupList,
|
|
2377
|
+
function (key, device) {
|
|
2378
|
+
return 'Group ' + device.groupId + ': ' + device.groupName;
|
|
2379
|
+
},
|
|
2380
|
+
function (key, device) {
|
|
2381
|
+
return device.id;
|
|
2382
|
+
}, true);
|
|
2217
2383
|
|
|
2218
|
-
|
|
2384
|
+
// fill cid, cmd, type selector
|
|
2385
|
+
*/
|
|
2219
2386
|
populateSelector('#cid', 'cidList');
|
|
2220
2387
|
populateSelector('#cmd', 'cmdListFoundation', this.value);
|
|
2221
2388
|
populateSelector('#type', 'typeList', this.value);
|
|
@@ -2296,10 +2463,11 @@ function loadDeveloperTab() {
|
|
|
2296
2463
|
}
|
|
2297
2464
|
|
|
2298
2465
|
const device = devices.find(obj => {
|
|
2299
|
-
return
|
|
2466
|
+
return this.value ===obj.native.id;
|
|
2300
2467
|
});
|
|
2468
|
+
console.warn(`dev selector: ${this.selectedIndex} ${this.value} ->${JSON.stringify(device)}`)
|
|
2301
2469
|
|
|
2302
|
-
const epList = device ? device.info.
|
|
2470
|
+
const epList = device ? device.info.endpoints : null;
|
|
2303
2471
|
updateSelect('#ep', epList,
|
|
2304
2472
|
function (key, ep) {
|
|
2305
2473
|
return ep.ID;
|
|
@@ -2735,14 +2903,14 @@ function prepareBindingDialog(bindObj) {
|
|
|
2735
2903
|
return 'Select source device';
|
|
2736
2904
|
}
|
|
2737
2905
|
if (device.hasOwnProperty('info')) {
|
|
2738
|
-
if (device.info.device.
|
|
2906
|
+
if (device.info.device && device.info.device.type === 'Coordinator') {
|
|
2739
2907
|
return null;
|
|
2740
2908
|
}
|
|
2741
2909
|
// check for output clusters
|
|
2742
2910
|
let allow = false;
|
|
2743
2911
|
for (const cluster of allowClusters) {
|
|
2744
2912
|
if (device.info.endpoints) for (const ep of device.info.endpoints) {
|
|
2745
|
-
if (ep.
|
|
2913
|
+
if (ep.output_clusters.includes(cluster)) {
|
|
2746
2914
|
allow = true;
|
|
2747
2915
|
break;
|
|
2748
2916
|
}
|
|
@@ -2786,14 +2954,14 @@ function prepareBindingDialog(bindObj) {
|
|
|
2786
2954
|
return 'Select target device';
|
|
2787
2955
|
}
|
|
2788
2956
|
if (device.hasOwnProperty('info')) {
|
|
2789
|
-
if (device.info.device.
|
|
2957
|
+
if (device.info.device && device.info.device.type === 'Coordinator') {
|
|
2790
2958
|
return null;
|
|
2791
2959
|
}
|
|
2792
2960
|
// check for input clusters
|
|
2793
2961
|
let allow = false;
|
|
2794
2962
|
for (const cluster of allowClusters) {
|
|
2795
2963
|
if (device.info.endpoints) for (const ep of device.info.endpoints) {
|
|
2796
|
-
if (ep.
|
|
2964
|
+
if (ep.input_clusters.includes(cluster)) {
|
|
2797
2965
|
allow = true;
|
|
2798
2966
|
break;
|
|
2799
2967
|
}
|
|
@@ -2837,7 +3005,7 @@ function prepareBindingDialog(bindObj) {
|
|
|
2837
3005
|
|
|
2838
3006
|
const epList = device ? device.info.endpoints : [];
|
|
2839
3007
|
const sClusterList = epList.map((ep) => {
|
|
2840
|
-
const clusters = ep.
|
|
3008
|
+
const clusters = ep.output_clusters.map((cl) => {
|
|
2841
3009
|
return allowClusters.includes(cl) ? {ID: ep.ID + '_' + cl, name: allowClustersName[cl]} : null;
|
|
2842
3010
|
}).filter((i) => {
|
|
2843
3011
|
return i != null;
|
|
@@ -2863,7 +3031,7 @@ function prepareBindingDialog(bindObj) {
|
|
|
2863
3031
|
|
|
2864
3032
|
const epList = device ? device.info.endpoints : [];
|
|
2865
3033
|
const tClusterList = epList.map((ep) => {
|
|
2866
|
-
const clusters = ep.
|
|
3034
|
+
const clusters = ep.input_clusters.map((cl) => {
|
|
2867
3035
|
return (allowClusters.includes(cl) && (!sourceCl || sourceCl == cl)) ? {
|
|
2868
3036
|
ID: ep.ID + '_' + cl,
|
|
2869
3037
|
name: allowClustersName[cl]
|
|
@@ -3096,12 +3264,13 @@ function genDevInfo(device) {
|
|
|
3096
3264
|
//console.log(device);
|
|
3097
3265
|
const dev = (device && device.info) ? device.info.device : undefined;
|
|
3098
3266
|
const mapped = (device && device.info) ? device.info.mapped : undefined;
|
|
3267
|
+
const endpoints = (device && device.info) ? device.info.endpoints : [];
|
|
3099
3268
|
if (!dev) return `<div class="truncate">No info</div>`;
|
|
3100
3269
|
const genRow = function (name, value, refresh) {
|
|
3101
3270
|
if (value === undefined) {
|
|
3102
3271
|
return '';
|
|
3103
3272
|
} else {
|
|
3104
|
-
return `<li><span class="label">${name}:</span><span>${value}</span></li>`;
|
|
3273
|
+
return `<li><span class="label">${name.replace('_',' ')}:</span><span>${value}</span></li>`;
|
|
3105
3274
|
}
|
|
3106
3275
|
};
|
|
3107
3276
|
const genRowValues = function (name, value) {
|
|
@@ -3109,66 +3278,68 @@ function genDevInfo(device) {
|
|
|
3109
3278
|
return '';
|
|
3110
3279
|
} else {
|
|
3111
3280
|
let label = `${name}:`;
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3281
|
+
try {
|
|
3282
|
+
return value.map((val) => {
|
|
3283
|
+
const row = `<li><span class="label">${label}</span><span>${val}</span></li>`;
|
|
3284
|
+
label = '';
|
|
3285
|
+
return row;
|
|
3286
|
+
}).join('');
|
|
3287
|
+
}
|
|
3288
|
+
catch {
|
|
3289
|
+
return `<li><span class="label">${label}</span><span>${JSON.stringify(value)}</span></li>`
|
|
3290
|
+
}
|
|
3117
3291
|
}
|
|
3118
3292
|
};
|
|
3119
3293
|
const modelUrl = (!mapped) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${sanitizeModelParameter(mapped.model)}.html" target="_blank" rel="noopener noreferrer">${mapped.model}</a>`;
|
|
3120
|
-
const mappedInfo =
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3294
|
+
const mappedInfo = [];
|
|
3295
|
+
if (mapped) {
|
|
3296
|
+
mappedInfo.push(
|
|
3297
|
+
`<div style="font-size: 0.9em">
|
|
3298
|
+
<ul>`);
|
|
3299
|
+
for (const item in mapped) {
|
|
3300
|
+
if (item == 'model')
|
|
3301
|
+
mappedInfo.push(genRow(item,modelUrl));
|
|
3302
|
+
else
|
|
3303
|
+
mappedInfo.push(genRow(item,mapped[item]));
|
|
3304
|
+
}
|
|
3305
|
+
mappedInfo.push(
|
|
3306
|
+
` </ul>
|
|
3307
|
+
</div>`);
|
|
3308
|
+
}
|
|
3128
3309
|
let epInfo = '';
|
|
3129
|
-
for (const epind in
|
|
3130
|
-
const ep =
|
|
3310
|
+
for (const epind in endpoints) {
|
|
3311
|
+
const ep = endpoints[epind];
|
|
3312
|
+
console.warn(JSON.stringify(ep));
|
|
3131
3313
|
epInfo +=
|
|
3132
3314
|
`<div style="font-size: 0.9em" class="truncate">
|
|
3133
3315
|
<ul>
|
|
3134
3316
|
${genRow('endpoint', ep.ID)}
|
|
3135
|
-
${genRow('profile', ep.
|
|
3136
|
-
${genRowValues('input clusters', ep.
|
|
3137
|
-
${genRowValues('output clusters', ep.
|
|
3317
|
+
${genRow('profile', ep.profile)}
|
|
3318
|
+
${genRowValues('input clusters', ep.input_clusters ? ep.input_clusters.map(findClName) : 'none')}
|
|
3319
|
+
${genRowValues('output clusters', ep.output_clusters ? ep.output_clusters.map(findClName): 'none')}
|
|
3138
3320
|
</ul>
|
|
3139
3321
|
</div>`;
|
|
3140
3322
|
}
|
|
3141
3323
|
const imgSrc = device.icon || device.common.icon;
|
|
3142
3324
|
const imgInfo = (imgSrc) ? `<img src=${imgSrc} width='150px' onerror="this.onerror=null;this.src='img/unavailable.png';"><div class="divider"></div>` : '';
|
|
3143
|
-
const info =
|
|
3325
|
+
const info =[
|
|
3144
3326
|
`<div class="col s12 m6 l6 xl6">
|
|
3145
3327
|
${imgInfo}
|
|
3146
|
-
${mappedInfo}
|
|
3328
|
+
${mappedInfo.join('')}
|
|
3147
3329
|
<div class="divider"></div>
|
|
3148
3330
|
<div style="font-size: 0.9em" class="truncate">
|
|
3149
|
-
<ul
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
${genRow('manuf id', dev._manufacturerID)}
|
|
3155
|
-
${genRow('manufacturer', dev._manufacturerName)}
|
|
3156
|
-
${genRow('power', dev._powerSource)}
|
|
3157
|
-
${genRow('app version', dev._applicationVersion)}
|
|
3158
|
-
${genRow('hard version', dev._hardwareVersion)}
|
|
3159
|
-
${genRow('zcl version', dev._zclVersion)}
|
|
3160
|
-
${genRow('stack version', dev._stackVersion)}
|
|
3161
|
-
${genRow('date code', dev._dateCode)}
|
|
3162
|
-
${genRow('build', dev._softwareBuildID)}
|
|
3163
|
-
${genRow('interviewed', dev._interviewCompleted)}
|
|
3164
|
-
${genRow('configured', (device.isConfigured), true)}
|
|
3331
|
+
<ul>`];
|
|
3332
|
+
for (const item in dev) {
|
|
3333
|
+
info.push(genRow(item, dev[item]));
|
|
3334
|
+
}
|
|
3335
|
+
info.push(` ${genRow('configured', (device.isConfigured), true)}
|
|
3165
3336
|
</ul>
|
|
3166
3337
|
</div>
|
|
3167
3338
|
</div>
|
|
3168
3339
|
<div class="col s12 m6 l6 xl6">
|
|
3169
3340
|
${epInfo}
|
|
3170
|
-
</div
|
|
3171
|
-
return info;
|
|
3341
|
+
</div>`);
|
|
3342
|
+
return info.join('');
|
|
3172
3343
|
}
|
|
3173
3344
|
|
|
3174
3345
|
function showDevInfo(id) {
|
|
@@ -3276,7 +3447,7 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
3276
3447
|
return 'Select model';
|
|
3277
3448
|
}
|
|
3278
3449
|
if (device.hasOwnProperty('info')) {
|
|
3279
|
-
if (device.info.device.
|
|
3450
|
+
if (device.info.device && device.info.device.type == 'Coordinator') {
|
|
3280
3451
|
return null;
|
|
3281
3452
|
}
|
|
3282
3453
|
return device.common.type;
|
|
@@ -3507,17 +3678,18 @@ function getDashCard(dev, groupImage, groupstatus) {
|
|
|
3507
3678
|
rooms = [],
|
|
3508
3679
|
lang = systemLang || 'en';
|
|
3509
3680
|
const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
|
|
3681
|
+
const permitJoinBtn = dev.battery || dev.common.type == 'group' ? '' : `<div class="col tool"><button name="joinCard" class="waves-effect btn-small btn-flat right hoverable green"><i class="material-icons icon-green">leak_add</i></button></div>`;
|
|
3682
|
+
const device_queryBtn = dev.battery || dev.common.type == 'group' ? '' : `<div class="col tool"><button name="deviceQuery" class="waves-effect btn-small btn-flat right hoverable green"><i class="material-icons icon-green">play_for_work</i></button></div>`;
|
|
3510
3683
|
const rid = id.split('.').join('_');
|
|
3511
3684
|
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
|
|
3512
3685
|
const image = `<img src="${img_src}" width="64px" onerror="this.onerror=null;this.src='img/unavailable.png';">`,
|
|
3513
|
-
nwk = (dev.info && dev.info.device) ? dev.info.device.
|
|
3686
|
+
nwk = (dev.info && dev.info.device) ? dev.info.device.nwk : undefined,
|
|
3514
3687
|
battery_cls = getBatteryCls(dev.battery),
|
|
3515
3688
|
lqi_cls = getLQICls(dev.link_quality),
|
|
3516
3689
|
unconnected_icon = (groupImage ? (groupstatus ? '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>' : '<div class="col tool"><i class="material-icons icon-red">cancel</i></div>') :'<div class="col tool"><i class="material-icons icon-red">leak_remove</i></div>'),
|
|
3517
3690
|
battery = (dev.battery && isActive) ? `<div class="col tool"><i id="${rid}_battery_icon" class="material-icons ${battery_cls}">battery_std</i><div id="${rid}_battery" class="center" style="font-size:0.7em">${dev.battery}</div></div>` : '',
|
|
3518
3691
|
lq = (dev.link_quality > 0 && isActive) ? `<div class="col tool"><i id="${rid}_link_quality_icon" class="material-icons ${lqi_cls}">network_check</i><div id="${rid}_link_quality" class="center" style="font-size:0.7em">${dev.link_quality}</div></div>` : (isActive ? unconnected_icon : ''),
|
|
3519
3692
|
//status = (dev.link_quality > 0 && isActive) ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : (groupImage || !isActive ? '' : `<div class="col tool"><i class="material-icons icon-black">leak_remove</i></div>`),
|
|
3520
|
-
//permitJoinBtn = (isActive && dev.info && dev.info.device._type === 'Router') ? '<button name="join" class="btn-floating btn-small waves-effect waves-light right hoverable green"><i class="material-icons tiny">leak_add</i></button>' : '',
|
|
3521
3693
|
//infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '',
|
|
3522
3694
|
idleTime = (dev.link_quality_lc > 0 && isActive) ? `<div class="col tool"><i id="${rid}_link_quality_lc_icon" class="material-icons idletime">access_time</i><div id="${rid}_link_quality_lc" class="center" style="font-size:0.7em">${getIdleTime(dev.link_quality_lc)}</div></div>` : '';
|
|
3523
3695
|
const info = (dev.statesDef) ? dev.statesDef.map((stateDef) => {
|
|
@@ -3567,13 +3739,19 @@ function getDashCard(dev, groupImage, groupstatus) {
|
|
|
3567
3739
|
}).join('') : '';
|
|
3568
3740
|
const dashCard = `
|
|
3569
3741
|
<div class="card-content zcard ${isActive ? '' : 'bg_red'}">
|
|
3570
|
-
<div
|
|
3742
|
+
<div style="cursor: pointer">
|
|
3743
|
+
<span class="top right small" style="border-radius: 50%">
|
|
3744
|
+
${device_queryBtn}
|
|
3745
|
+
${permitJoinBtn}
|
|
3746
|
+
</span>
|
|
3747
|
+
<div class="flip">
|
|
3571
3748
|
<span class="top right small" style="border-radius: 50%">
|
|
3572
3749
|
${idleTime}
|
|
3573
3750
|
${battery}
|
|
3574
3751
|
${lq}
|
|
3575
3752
|
</span>
|
|
3576
|
-
|
|
3753
|
+
<span class="card-title truncate">${title}</span>
|
|
3754
|
+
</div>
|
|
3577
3755
|
</div>
|
|
3578
3756
|
<i class="left">${image}</i>
|
|
3579
3757
|
<div style="min-height:88px; font-size: 0.8em; height: 130px; overflow-y: auto" class="truncate">
|
|
@@ -3708,7 +3886,7 @@ function reconfigureDevice(id) {
|
|
|
3708
3886
|
}
|
|
3709
3887
|
}
|
|
3710
3888
|
});
|
|
3711
|
-
showWaitingDialog('Device is being
|
|
3889
|
+
showWaitingDialog('Device is being reconfigured', 30);
|
|
3712
3890
|
}
|
|
3713
3891
|
|
|
3714
3892
|
const warnLevel = {
|