iobroker.zigbee 1.7.5 → 1.8.0
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/LICENSE +1 -1
- package/README.md +22 -29
- package/admin/admin.js +494 -469
- package/admin/i18n/de/translations.json +108 -0
- package/admin/i18n/en/translations.json +108 -0
- package/admin/i18n/es/translations.json +102 -0
- package/admin/i18n/fr/translations.json +108 -0
- package/admin/i18n/it/translations.json +102 -0
- package/admin/i18n/nl/translations.json +108 -0
- package/admin/i18n/pl/translations.json +108 -0
- package/admin/i18n/pt/translations.json +102 -0
- package/admin/i18n/ru/translations.json +108 -0
- package/admin/i18n/uk/translations.json +108 -0
- package/admin/i18n/zh-cn/translations.json +102 -0
- package/admin/index_m.html +1 -1
- package/admin/tab_m.html +44 -3
- package/admin/words.js +107 -108
- package/io-package.json +326 -357
- package/lib/backup.js +2 -2
- package/lib/binding.js +23 -24
- package/lib/colors.js +16 -14
- package/lib/commands.js +89 -82
- package/lib/developer.js +6 -7
- package/lib/devices.js +145 -154
- package/lib/exclude.js +30 -36
- package/lib/exposes.js +106 -111
- package/lib/groups.js +53 -54
- package/lib/json.js +3 -4
- package/lib/networkmap.js +2 -2
- package/lib/ota.js +23 -15
- package/lib/rgb.js +47 -44
- package/lib/seriallist.js +21 -10
- package/lib/states.js +488 -498
- package/lib/statescontroller.js +170 -164
- package/lib/utils.js +22 -21
- package/lib/zbBaseExtension.js +4 -4
- package/lib/zbDelayedAction.js +5 -13
- package/lib/zbDeviceAvailability.js +47 -44
- package/lib/zbDeviceConfigure.js +18 -23
- package/lib/zbDeviceEvent.js +3 -4
- package/lib/zigbeecontroller.js +97 -100
- package/main.js +149 -133
- package/package.json +33 -19
- package/.eslintignore +0 -2
- package/.eslintrc.json +0 -37
- package/.github/FUNDING.yml +0 -3
- package/.github/stale.yml +0 -13
- package/.github/workflows/test-and-release.yml +0 -151
- package/.travis/wiki.sh +0 -28
- package/admin/adapter-settings.js +0 -244
package/admin/admin.js
CHANGED
|
@@ -38,7 +38,7 @@ function getDeviceByID(ID) {
|
|
|
38
38
|
return devices.find((devInfo) => {
|
|
39
39
|
try {
|
|
40
40
|
return devInfo._id == ID;
|
|
41
|
-
}
|
|
41
|
+
} catch (e) {
|
|
42
42
|
//console.log("No dev with ieee " + ieeeAddr);
|
|
43
43
|
}
|
|
44
44
|
});
|
|
@@ -48,17 +48,18 @@ function getDevice(ieeeAddr) {
|
|
|
48
48
|
return devices.find((devInfo) => {
|
|
49
49
|
try {
|
|
50
50
|
return devInfo.info.device._ieeeAddr == ieeeAddr;
|
|
51
|
-
}
|
|
51
|
+
} catch (e) {
|
|
52
52
|
//console.log("No dev with ieee " + ieeeAddr);
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
|
|
56
57
|
// eslint-disable-next-line no-unused-vars
|
|
57
58
|
function getDeviceByNetwork(nwk) {
|
|
58
59
|
return devices.find((devInfo) => {
|
|
59
60
|
try {
|
|
60
61
|
return devInfo.info.device._networkAddress == nwk;
|
|
61
|
-
}
|
|
62
|
+
} catch (e) {
|
|
62
63
|
//console.log("No dev with nwkAddr " + nwk);
|
|
63
64
|
}
|
|
64
65
|
});
|
|
@@ -125,12 +126,12 @@ function getCoordinatorCard(dev) {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
function getGroupCard(dev) {
|
|
128
|
-
const id = (dev._id ? dev._id: ''),
|
|
129
|
+
const id = (dev._id ? dev._id : ''),
|
|
129
130
|
title = dev.common.name,
|
|
130
131
|
lq = '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>',
|
|
131
132
|
rooms = [],
|
|
132
|
-
numid = parseInt(id.replace(namespace+'.group_', '')),
|
|
133
|
-
lang = systemLang
|
|
133
|
+
numid = parseInt(id.replace(namespace + '.group_', '')),
|
|
134
|
+
lang = systemLang || 'en';
|
|
134
135
|
for (const r in dev.rooms) {
|
|
135
136
|
if (dev.rooms[r].hasOwnProperty(lang)) {
|
|
136
137
|
rooms.push(dev.rooms[r][lang]);
|
|
@@ -143,19 +144,20 @@ function getGroupCard(dev) {
|
|
|
143
144
|
let memberCount = 0;
|
|
144
145
|
let info = `<div style="min-height:88px; font-size: 0.8em; height: 98px; overflow-y: auto" class="truncate">
|
|
145
146
|
<ul>`;
|
|
146
|
-
|
|
147
|
+
info = info.concat(`<li><span class="labelinfo">Group ${numid}</span></li>`);
|
|
147
148
|
if (dev.memberinfo === undefined) {
|
|
148
149
|
info = info.concat(`<li><span class="labelinfo">No devices in group</span></li>`);
|
|
149
150
|
} else {
|
|
150
|
-
for (let m=0;m < dev.memberinfo.length; m++) {
|
|
151
|
+
for (let m = 0; m < dev.memberinfo.length; m++) {
|
|
151
152
|
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>`);
|
|
152
153
|
}
|
|
153
|
-
memberCount = (dev.memberinfo.length<8?dev.memberinfo.length:7);
|
|
154
|
-
}
|
|
154
|
+
memberCount = (dev.memberinfo.length < 8 ? dev.memberinfo.length : 7);
|
|
155
|
+
}
|
|
156
|
+
;
|
|
155
157
|
info = info.concat(` </ul>
|
|
156
158
|
</div>`);
|
|
157
159
|
const image = `<img src="img/group_${memberCount}.png" width="80px" onerror="this.onerror=null;this.src='img/unavailable.png';">`;
|
|
158
|
-
const dashCard = getDashCard(dev
|
|
160
|
+
const dashCard = getDashCard(dev, `img/group_${memberCount}.png`);
|
|
159
161
|
const card = `<div id="${id}" class="device group">
|
|
160
162
|
<div class="card hoverable flipable">
|
|
161
163
|
<div class="front face">${dashCard}</div>
|
|
@@ -202,7 +204,7 @@ function getCard(dev) {
|
|
|
202
204
|
img_src = dev.icon || dev.common.icon,
|
|
203
205
|
rooms = [],
|
|
204
206
|
isActive = (dev.common.deactivated ? false : true),
|
|
205
|
-
lang = systemLang
|
|
207
|
+
lang = systemLang || 'en';
|
|
206
208
|
for (const r in dev.rooms) {
|
|
207
209
|
if (dev.rooms[r].hasOwnProperty(lang)) {
|
|
208
210
|
rooms.push(dev.rooms[r][lang]);
|
|
@@ -216,25 +218,25 @@ function getCard(dev) {
|
|
|
216
218
|
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
|
|
217
219
|
const image = `<img src="${img_src}" width="80px" onerror="this.onerror=null;this.src='img/unavailable.png';">`,
|
|
218
220
|
nwk = (dev.info && dev.info.device) ? dev.info.device._networkAddress : undefined,
|
|
219
|
-
battery_cls = (isActive ? getBatteryCls(dev.battery):''),
|
|
221
|
+
battery_cls = (isActive ? getBatteryCls(dev.battery) : ''),
|
|
220
222
|
lqi_cls = getLQICls(dev.link_quality),
|
|
221
223
|
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>` : '',
|
|
222
224
|
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>` : '',
|
|
223
|
-
status = (dev.link_quality > 0 && isActive) ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : (isActive ? `<div class="col tool"><i class="material-icons icon-black">leak_remove</i></div
|
|
225
|
+
status = (dev.link_quality > 0 && isActive) ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : (isActive ? `<div class="col tool"><i class="material-icons icon-black">leak_remove</i></div>` : ''),
|
|
224
226
|
info = `<div style="min-height:88px; font-size: 0.8em" class="truncate">
|
|
225
227
|
<ul>
|
|
226
|
-
<li><span class="labelinfo">ieee:</span><span>0x${id.replace(namespace+'.', '')}</span></li>
|
|
227
|
-
<li><span class="labelinfo">nwk:</span><span>${(nwk) ? nwk.toString()+' (0x'+nwk.toString(16)+')' : ''}</span></li>
|
|
228
|
+
<li><span class="labelinfo">ieee:</span><span>0x${id.replace(namespace + '.', '')}</span></li>
|
|
229
|
+
<li><span class="labelinfo">nwk:</span><span>${(nwk) ? nwk.toString() + ' (0x' + nwk.toString(16) + ')' : ''}</span></li>
|
|
228
230
|
<li><span class="labelinfo">model:</span><span>${modelUrl}</span></li>
|
|
229
231
|
<li><span class="labelinfo">groups:</span><span>${dev.groupNames || ''}</span></li>
|
|
230
232
|
</ul>
|
|
231
233
|
</div>`,
|
|
232
234
|
permitJoinBtn = (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>' : '',
|
|
233
|
-
deactBtn = `<button name="swapactive" class="right btn-flat btn-small tooltipped" title="${(isActive?'Deactivate':'Activate')}"><i class="material-icons icon-${(isActive?'red':'green')}">power_settings_new</i></button>`,
|
|
235
|
+
deactBtn = `<button name="swapactive" class="right btn-flat btn-small tooltipped" title="${(isActive ? 'Deactivate' : 'Activate')}"><i class="material-icons icon-${(isActive ? 'red' : 'green')}">power_settings_new</i></button>`,
|
|
234
236
|
infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '';
|
|
235
237
|
const dashCard = getDashCard(dev);
|
|
236
238
|
const card = `<div id="${id}" class="device">
|
|
237
|
-
<div class="card hoverable flipable ${isActive?'':'bg_red'}">
|
|
239
|
+
<div class="card hoverable flipable ${isActive ? '' : 'bg_red'}">
|
|
238
240
|
<div class="front face">${dashCard}</div>
|
|
239
241
|
<div class="back face">
|
|
240
242
|
<div class="card-content zcard">
|
|
@@ -274,6 +276,7 @@ function getCard(dev) {
|
|
|
274
276
|
</div>`;
|
|
275
277
|
return card;
|
|
276
278
|
}
|
|
279
|
+
|
|
277
280
|
/*
|
|
278
281
|
function openReval(e, id, name){
|
|
279
282
|
const $card = $(e.target).closest('.card');
|
|
@@ -301,7 +304,7 @@ function openReval(e, id, name){
|
|
|
301
304
|
});
|
|
302
305
|
}
|
|
303
306
|
*/
|
|
304
|
-
function closeReval(e, id){
|
|
307
|
+
function closeReval(e, id) {
|
|
305
308
|
const $cardReveal = $(e.target).closest('.card-reveal');
|
|
306
309
|
const $revealName = $cardReveal[0].getAttribute('name');
|
|
307
310
|
if ($revealName == 'edit' && id) {
|
|
@@ -320,21 +323,21 @@ function closeReval(e, id){
|
|
|
320
323
|
translateY: 0,
|
|
321
324
|
duration: 225,
|
|
322
325
|
easing: 'easeInOutQuad',
|
|
323
|
-
complete: function(anim) {
|
|
326
|
+
complete: function (anim) {
|
|
324
327
|
const el = anim.animatables[0].target;
|
|
325
|
-
$(el).css({
|
|
328
|
+
$(el).css({display: 'none'});
|
|
326
329
|
$card.css('overflow', $card.data('initialOverflow'));
|
|
327
330
|
}
|
|
328
331
|
});
|
|
329
332
|
}
|
|
330
333
|
|
|
331
334
|
function deleteConfirmation(id, name) {
|
|
332
|
-
const text = translateWord('Do you really want to delete device') + ' "'+name+'" ('+id+')?';
|
|
335
|
+
const text = translateWord('Do you really want to delete device') + ' "' + name + '" (' + id + ')?';
|
|
333
336
|
$('#modaldelete').find('p').text(text);
|
|
334
337
|
$('#force').prop('checked', false);
|
|
335
338
|
$('#forcediv').removeClass('hide');
|
|
336
|
-
$(
|
|
337
|
-
$(
|
|
339
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
340
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
338
341
|
const force = $('#force').prop('checked');
|
|
339
342
|
deleteDevice(id, force);
|
|
340
343
|
});
|
|
@@ -347,8 +350,8 @@ function cleanConfirmation() {
|
|
|
347
350
|
$('#modalclean').find('p').text(text);
|
|
348
351
|
$('#cforce').prop('checked', false);
|
|
349
352
|
$('#cforcediv').removeClass('hide');
|
|
350
|
-
$(
|
|
351
|
-
$(
|
|
353
|
+
$('#modalclean a.btn[name=\'yes\']').unbind('click');
|
|
354
|
+
$('#modalclean a.btn[name=\'yes\']').click(() => {
|
|
352
355
|
const force = $('#cforce').prop('checked');
|
|
353
356
|
cleanDeviceStates(force);
|
|
354
357
|
});
|
|
@@ -356,78 +359,75 @@ function cleanConfirmation() {
|
|
|
356
359
|
Materialize.updateTextFields();
|
|
357
360
|
}
|
|
358
361
|
|
|
359
|
-
function EndPointIDfromEndPoint(ep)
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
return
|
|
363
|
-
return 'unidentified';
|
|
362
|
+
function EndPointIDfromEndPoint(ep) {
|
|
363
|
+
if (ep && ep.deviceIeeeAddress && ep.ID)
|
|
364
|
+
return `${ep.deviceIeeeAddress}:${ep.ID}`;
|
|
365
|
+
return 'unidentified';
|
|
364
366
|
}
|
|
365
367
|
|
|
366
368
|
function editName(id, name) {
|
|
367
|
-
|
|
369
|
+
console.log('editName called with ' + name);
|
|
368
370
|
const dev = devices.find((d) => d._id == id);
|
|
369
|
-
$('#modaledit').find(
|
|
371
|
+
$('#modaledit').find('input[id=\'d_name\']').val(name);
|
|
370
372
|
// if (dev.info && dev.info.device._type == 'Router') {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
+
const groupables = [];
|
|
374
|
+
if (dev && dev.info && dev.info.endpoints) {
|
|
373
375
|
for (const ep of dev.info.endpoints) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
376
|
+
if (ep.inputClusters.includes(4)) {
|
|
377
|
+
groupables.push({epid: EndPointIDfromEndPoint(ep), ep: ep, memberOf: []});
|
|
378
|
+
}
|
|
377
379
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
+
}
|
|
381
|
+
const numEP = groupables.length;
|
|
380
382
|
// console.log('groupables: '+JSON.stringify(groupables));
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
$('#modaledit').find('.row.epid0').addClass('hide');
|
|
384
|
+
$('#modaledit').find('.row.epid1').addClass('hide');
|
|
385
|
+
$('#modaledit').find('.row.epid2').addClass('hide');
|
|
386
|
+
$('#modaledit').find('.row.epid3').addClass('hide');
|
|
387
|
+
if (numEP > 0) {
|
|
386
388
|
// go through all the groups. Find the ones to list for each groupable
|
|
387
389
|
if (numEP == 1) {
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
$('#modaledit').find('.endpointid').removeClass('hide');
|
|
390
|
+
$('#modaledit').find('.endpointid').addClass('hide');
|
|
391
|
+
} else {
|
|
392
|
+
$('#modaledit').find('.endpointid').removeClass('hide');
|
|
392
393
|
}
|
|
393
394
|
for (const d of devices) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
395
|
+
if (d && d.common && d.common.type == 'group') {
|
|
396
|
+
if (d.hasOwnProperty('memberinfo')) {
|
|
397
|
+
for (const member of d.memberinfo) {
|
|
398
|
+
const epid = EndPointIDfromEndPoint(member.ep);
|
|
399
|
+
for (var i = 0; i < groupables.length; i++) {
|
|
400
|
+
if (groupables[i].epid == epid) {
|
|
401
|
+
groupables[i].memberOf.push(d.native.id.replace('group_', ''));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
402
405
|
}
|
|
403
|
-
}
|
|
404
406
|
}
|
|
405
|
-
}
|
|
406
407
|
}
|
|
407
|
-
console.log(
|
|
408
|
-
for (var i = 0;i<groupables.length;i++)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
list2select('#d_groups_ep'+i, groups, groupables[i].memberOf || []);
|
|
408
|
+
console.log('groupables: ' + JSON.stringify(groupables));
|
|
409
|
+
for (var i = 0; i < groupables.length; i++) {
|
|
410
|
+
if (i > 1) {
|
|
411
|
+
$('#modaledit').find('translate.device_with_endpoint').innerHtml = name + ' ' + groupables[i].epid;
|
|
412
|
+
}
|
|
413
|
+
$('#modaledit').find('.row.epid' + i).removeClass('hide');
|
|
414
|
+
list2select('#d_groups_ep' + i, groups, groupables[i].memberOf || []);
|
|
415
415
|
}
|
|
416
|
-
|
|
416
|
+
}
|
|
417
417
|
// } else {
|
|
418
418
|
// $('#modaledit').find('.input-field.endpoints').addClass('hide');
|
|
419
419
|
// $('#modaledit').find('.input-field.groups').addClass('hide');
|
|
420
420
|
// }
|
|
421
|
-
$(
|
|
422
|
-
$(
|
|
423
|
-
const newName = $('#modaledit').find(
|
|
421
|
+
$('#modaledit a.btn[name=\'save\']').unbind('click');
|
|
422
|
+
$('#modaledit a.btn[name=\'save\']').click(() => {
|
|
423
|
+
const newName = $('#modaledit').find('input[id=\'d_name\']').val();
|
|
424
424
|
const groupsbyid = {};
|
|
425
|
-
if (groupables.length
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
425
|
+
if (groupables.length > 0) {
|
|
426
|
+
for (var i = 0; i < groupables.length; i++) {
|
|
427
|
+
const ng = $('#d_groups_ep' + i).val();
|
|
428
|
+
if (ng.toString() != groupables[i].memberOf.toString())
|
|
429
|
+
groupsbyid[groupables[i].ep.ID] = GenerateGroupChange(groupables[i].memberOf, ng);
|
|
430
|
+
}
|
|
431
431
|
}
|
|
432
432
|
console.log('grpid ' + JSON.stringify(groupsbyid));
|
|
433
433
|
updateDev(id, newName, groupsbyid);
|
|
@@ -436,14 +436,13 @@ function editName(id, name) {
|
|
|
436
436
|
Materialize.updateTextFields();
|
|
437
437
|
}
|
|
438
438
|
|
|
439
|
-
function GenerateGroupChange(oldmembers, newmembers)
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
return grpchng;
|
|
439
|
+
function GenerateGroupChange(oldmembers, newmembers) {
|
|
440
|
+
let grpchng = [];
|
|
441
|
+
for (const oldg of oldmembers)
|
|
442
|
+
if (!newmembers.includes(oldg)) grpchng.push('-' + oldg);
|
|
443
|
+
for (const newg of newmembers)
|
|
444
|
+
if (!oldmembers.includes(newg)) grpchng.push(newg);
|
|
445
|
+
return grpchng;
|
|
447
446
|
}
|
|
448
447
|
|
|
449
448
|
function deleteDevice(id, force) {
|
|
@@ -474,6 +473,7 @@ function cleanDeviceStates(force) {
|
|
|
474
473
|
});
|
|
475
474
|
showWaitingDialog('Device is being removed', 10);
|
|
476
475
|
}
|
|
476
|
+
|
|
477
477
|
function renameDevice(id, name) {
|
|
478
478
|
sendTo(namespace, 'renameDevice', {id: id, name: name}, function (msg) {
|
|
479
479
|
if (msg) {
|
|
@@ -490,7 +490,7 @@ function showDevices() {
|
|
|
490
490
|
let html = '';
|
|
491
491
|
const lang = systemLang || 'en';
|
|
492
492
|
// sort by rooms
|
|
493
|
-
devices.sort((a, b)=>{
|
|
493
|
+
devices.sort((a, b) => {
|
|
494
494
|
const roomsA = [], roomsB = [];
|
|
495
495
|
for (const r in a.rooms) {
|
|
496
496
|
if (a.rooms[r].hasOwnProperty(lang)) {
|
|
@@ -517,29 +517,28 @@ function showDevices() {
|
|
|
517
517
|
}
|
|
518
518
|
return 0;
|
|
519
519
|
});
|
|
520
|
-
for (let i=0;i < devices.length; i++) {
|
|
520
|
+
for (let i = 0; i < devices.length; i++) {
|
|
521
521
|
const d = devices[i];
|
|
522
522
|
if (!d.info) {
|
|
523
|
-
if (d.common && d.common.type == 'group')
|
|
524
|
-
{
|
|
523
|
+
if (d.common && d.common.type == 'group') {
|
|
525
524
|
const card = getGroupCard(d);
|
|
526
525
|
html += card;
|
|
527
526
|
continue;
|
|
528
527
|
}
|
|
529
|
-
}
|
|
528
|
+
}
|
|
529
|
+
;
|
|
530
530
|
if (d.info && d.info.device._type == 'Coordinator') {
|
|
531
531
|
const card = getCoordinatorCard(d);
|
|
532
532
|
html += card;
|
|
533
533
|
} else {
|
|
534
|
-
|
|
534
|
+
//if (d.groups && d.info && d.info.device._type == "Router") {
|
|
535
535
|
if (d.groups) {
|
|
536
536
|
// devGroups[d._id] = d.groups;
|
|
537
537
|
if (typeof d.groups.map == 'function') {
|
|
538
|
-
d.groupNames = d.groups.map(item=>{
|
|
538
|
+
d.groupNames = d.groups.map(item => {
|
|
539
539
|
return groups[item] || '';
|
|
540
540
|
}).join(', ');
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
541
|
+
} else {
|
|
543
542
|
d.groupNames = '..';
|
|
544
543
|
}
|
|
545
544
|
}
|
|
@@ -551,13 +550,13 @@ function showDevices() {
|
|
|
551
550
|
hookControls();
|
|
552
551
|
|
|
553
552
|
// update rooms filter
|
|
554
|
-
const allRooms = new Set(devices.map((item)=>item.rooms).flat().map((room)=>{
|
|
553
|
+
const allRooms = new Set(devices.map((item) => item.rooms).flat().map((room) => {
|
|
555
554
|
if (room && room.hasOwnProperty(lang)) {
|
|
556
555
|
return room[lang];
|
|
557
556
|
} else {
|
|
558
557
|
return room;
|
|
559
558
|
}
|
|
560
|
-
}).filter((item)=>item != undefined));
|
|
559
|
+
}).filter((item) => item != undefined));
|
|
561
560
|
const roomSelector = $('#room-filter');
|
|
562
561
|
roomSelector.empty();
|
|
563
562
|
roomSelector.append(`<li class="device-order-item" data-type="All" tabindex="0"><a class="translate" data-lang="All">All</a></li>`);
|
|
@@ -568,69 +567,69 @@ function showDevices() {
|
|
|
568
567
|
$('#room-filter-btn').text($(this).text());
|
|
569
568
|
doFilter();
|
|
570
569
|
});
|
|
571
|
-
$(
|
|
572
|
-
const card = $(this).parents(
|
|
573
|
-
card.toggleClass(
|
|
570
|
+
$('.flip').click(function () {
|
|
571
|
+
const card = $(this).parents('.card');
|
|
572
|
+
card.toggleClass('flipped');
|
|
574
573
|
});
|
|
575
574
|
$('#rotate_btn').click(function () {
|
|
576
|
-
$('.card.flipable').toggleClass(
|
|
575
|
+
$('.card.flipable').toggleClass('flipped');
|
|
577
576
|
});
|
|
578
577
|
|
|
579
|
-
shuffleInstance = new Shuffle($(
|
|
578
|
+
shuffleInstance = new Shuffle($('#devices'), {
|
|
580
579
|
itemSelector: '.device',
|
|
581
580
|
sizer: '.js-shuffle-sizer',
|
|
582
581
|
});
|
|
583
582
|
doFilter();
|
|
584
583
|
|
|
585
|
-
const getDevName = function(dev_block) {
|
|
584
|
+
const getDevName = function (dev_block) {
|
|
586
585
|
return dev_block.find('#dName').text();
|
|
587
586
|
};
|
|
588
|
-
const getDevId = function(dev_block) {
|
|
587
|
+
const getDevId = function (dev_block) {
|
|
589
588
|
return dev_block.attr('id');
|
|
590
589
|
};
|
|
591
|
-
$(
|
|
590
|
+
$('.card-reveal-buttons button[name=\'delete\']').click(function () {
|
|
592
591
|
const dev_block = $(this).parents('div.device');
|
|
593
592
|
deleteConfirmation(getDevId(dev_block), getDevName(dev_block));
|
|
594
593
|
});
|
|
595
|
-
$(
|
|
594
|
+
$('.card-reveal-buttons button[name=\'deletegrp\']').click(function () {
|
|
596
595
|
const dev_block = $(this).parents('div.device');
|
|
597
|
-
const id = dev_block.attr('id').replace(namespace+'.group_', '');
|
|
596
|
+
const id = dev_block.attr('id').replace(namespace + '.group_', '');
|
|
598
597
|
deleteGroupConfirmation(id, getDevName(dev_block));
|
|
599
598
|
});
|
|
600
|
-
$(
|
|
599
|
+
$('.card-reveal-buttons button[name=\'edit\']').click(function () {
|
|
601
600
|
const dev_block = $(this).parents('div.device'),
|
|
602
601
|
id = getDevId(dev_block),
|
|
603
602
|
name = getDevName(dev_block);
|
|
604
603
|
editName(id, name);
|
|
605
604
|
});
|
|
606
|
-
$(
|
|
605
|
+
$('.card-reveal-buttons button[name=\'editgrp\']').click(function () {
|
|
607
606
|
const dev_block = $(this).parents('div.device'),
|
|
608
|
-
id = dev_block.attr('id').replace(namespace+'.group_', ''),
|
|
607
|
+
id = dev_block.attr('id').replace(namespace + '.group_', ''),
|
|
609
608
|
name = getDevName(dev_block);
|
|
610
609
|
editGroupName(id, name, false);
|
|
611
610
|
});
|
|
612
|
-
$(
|
|
611
|
+
$('button.btn-floating[name=\'join\']').click(function () {
|
|
613
612
|
const dev_block = $(this).parents('div.device');
|
|
614
613
|
if (!$('#pairing').hasClass('pulse'))
|
|
615
614
|
joinProcess(getDevId(dev_block));
|
|
616
615
|
showPairingProcess();
|
|
617
616
|
});
|
|
618
|
-
$(
|
|
617
|
+
$('.card-reveal-buttons button[name=\'info\']').click(function () {
|
|
619
618
|
const dev_block = $(this).parents('div.device');
|
|
620
619
|
showDevInfo(getDevId(dev_block));
|
|
621
620
|
});
|
|
622
|
-
$(
|
|
621
|
+
$('a.btn[name=\'done\']').click((e) => {
|
|
623
622
|
const dev_block = $(this).parents('div.device');
|
|
624
623
|
closeReval(e, getDevId(dev_block), getDevName(dev_block));
|
|
625
624
|
});
|
|
626
|
-
$(
|
|
625
|
+
$('a.btn-flat[name=\'close\']').click((e) => {
|
|
627
626
|
closeReval(e);
|
|
628
627
|
});
|
|
629
|
-
$(
|
|
628
|
+
$('.card-reveal-buttons button[name=\'reconfigure\']').click(function () {
|
|
630
629
|
const dev_block = $(this).parents('div.device');
|
|
631
630
|
reconfigureDlg(getDevId(dev_block));
|
|
632
631
|
});
|
|
633
|
-
$(
|
|
632
|
+
$('.card-reveal-buttons button[name=\'swapactive\']').click(function () {
|
|
634
633
|
const dev_block = $(this).parents('div.device');
|
|
635
634
|
swapActive(getDevId(dev_block));
|
|
636
635
|
});
|
|
@@ -641,10 +640,10 @@ function showDevices() {
|
|
|
641
640
|
|
|
642
641
|
function checkFwUpdate() {
|
|
643
642
|
const deviceCards = getDeviceCards();
|
|
644
|
-
const getFwInfoNode = function(deviceCard) {
|
|
643
|
+
const getFwInfoNode = function (deviceCard) {
|
|
645
644
|
return deviceCard.find('.fw_info');
|
|
646
645
|
};
|
|
647
|
-
const createBtn = function(icon, hint, disabled, color) {
|
|
646
|
+
const createBtn = function (icon, hint, disabled, color) {
|
|
648
647
|
const disabledAttr = disabled ? '[disabled]="true"' : '';
|
|
649
648
|
if (!color) {
|
|
650
649
|
color = !disabled ? 'icon-green' : '';
|
|
@@ -652,14 +651,14 @@ function checkFwUpdate() {
|
|
|
652
651
|
return `<button name="fw_update" class="left btn-flat btn-small" title="${hint}" ${disabledAttr}>
|
|
653
652
|
<i class="material-icons ${color}">${icon}</i></button>`;
|
|
654
653
|
};
|
|
655
|
-
const callback = function(msg) {
|
|
654
|
+
const callback = function (msg) {
|
|
656
655
|
if (msg) {
|
|
657
656
|
const deviceCard = getDeviceCard(msg.device);
|
|
658
657
|
const devId = getDevId(deviceCard.attr('id'));
|
|
659
658
|
const fwInfoNode = getFwInfoNode(deviceCard);
|
|
660
659
|
if (msg.status == 'available') {
|
|
661
660
|
fwInfoNode.html(createBtn('system_update', 'Click to start firmware update', false));
|
|
662
|
-
$(fwInfoNode).find(
|
|
661
|
+
$(fwInfoNode).find('button[name=\'fw_update\']').click(() => {
|
|
663
662
|
fwInfoNode.html(createBtn('check_circle', 'Firmware update started, check progress in logs.', true, 'icon-blue'));
|
|
664
663
|
sendTo(namespace, 'startOta', {devId: devId}, (msg) => {
|
|
665
664
|
fwInfoNode.html(createBtn('check_circle', 'Finished, see logs.', true));
|
|
@@ -669,13 +668,13 @@ function checkFwUpdate() {
|
|
|
669
668
|
} else if (msg.status == 'not_available') {
|
|
670
669
|
fwInfoNode.html(createBtn('check_circle', 'Up-to-date', true));
|
|
671
670
|
} else if (msg.status == 'fail') {
|
|
672
|
-
fwInfoNode.html(createBtn('check_circle', 'Firmware check failed, '+msg.msg, true, 'icon-red'));
|
|
671
|
+
fwInfoNode.html(createBtn('check_circle', 'Firmware check failed, ' + msg.msg, true, 'icon-red'));
|
|
673
672
|
} else {
|
|
674
673
|
fwInfoNode.html(createBtn('not_interested', 'No firmware update available', true));
|
|
675
674
|
}
|
|
676
675
|
}
|
|
677
676
|
};
|
|
678
|
-
for (let i=0;i < deviceCards.length; i++) {
|
|
677
|
+
for (let i = 0; i < deviceCards.length; i++) {
|
|
679
678
|
const deviceCard = $(deviceCards[i]);
|
|
680
679
|
const devId = getDevId(deviceCard.attr('id'));
|
|
681
680
|
getFwInfoNode(deviceCard).html('<span class="left" style="padding-top:8px">checking...</span>');
|
|
@@ -746,7 +745,7 @@ function getDevices() {
|
|
|
746
745
|
}
|
|
747
746
|
|
|
748
747
|
function getDeviceCards() {
|
|
749
|
-
return $('#devices .device').not(
|
|
748
|
+
return $('#devices .device').not('.group');
|
|
750
749
|
}
|
|
751
750
|
|
|
752
751
|
function getDeviceCard(devId) {
|
|
@@ -810,35 +809,35 @@ function load(settings, onChange) {
|
|
|
810
809
|
// Signal to admin, that no changes yet
|
|
811
810
|
onChange(false);
|
|
812
811
|
|
|
813
|
-
$('#state_cleanup_btn').click(function() {
|
|
812
|
+
$('#state_cleanup_btn').click(function () {
|
|
814
813
|
cleanConfirmation();
|
|
815
814
|
});
|
|
816
|
-
$('#fw_check_btn').click(function() {
|
|
815
|
+
$('#fw_check_btn').click(function () {
|
|
817
816
|
checkFwUpdate();
|
|
818
817
|
});
|
|
819
|
-
$('#touchlink_btn').click(function() {
|
|
818
|
+
$('#touchlink_btn').click(function () {
|
|
820
819
|
touchlinkReset();
|
|
821
820
|
showPairingProcess();
|
|
822
821
|
});
|
|
823
|
-
$('#pairing').click(function() {
|
|
822
|
+
$('#pairing').click(function () {
|
|
824
823
|
if (!$('#pairing').hasClass('pulse'))
|
|
825
824
|
letsPairing();
|
|
826
825
|
showPairingProcess();
|
|
827
826
|
});
|
|
828
827
|
|
|
829
|
-
$('#refresh').click(function() {
|
|
828
|
+
$('#refresh').click(function () {
|
|
830
829
|
getMap();
|
|
831
830
|
});
|
|
832
831
|
|
|
833
|
-
$('#reset-btn').click(function() {
|
|
832
|
+
$('#reset-btn').click(function () {
|
|
834
833
|
resetConfirmation();
|
|
835
834
|
});
|
|
836
835
|
|
|
837
|
-
$('#viewconfig').click(function() {
|
|
836
|
+
$('#viewconfig').click(function () {
|
|
838
837
|
showViewConfig();
|
|
839
838
|
});
|
|
840
839
|
|
|
841
|
-
$('#scan').click(function() {
|
|
840
|
+
$('#scan').click(function () {
|
|
842
841
|
showChannels();
|
|
843
842
|
});
|
|
844
843
|
|
|
@@ -847,18 +846,18 @@ function load(settings, onChange) {
|
|
|
847
846
|
showGroups();
|
|
848
847
|
});
|
|
849
848
|
|
|
850
|
-
$('#add_group').click(function() {
|
|
849
|
+
$('#add_group').click(function () {
|
|
851
850
|
// showGroupList(true);
|
|
852
|
-
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
|
|
853
|
-
editGroupName(maxind+1, 'Group ' + maxind+1, true);
|
|
851
|
+
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
852
|
+
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
854
853
|
});
|
|
855
|
-
$('#add_grp_btn').click(function() {
|
|
854
|
+
$('#add_grp_btn').click(function () {
|
|
856
855
|
// showGroupList(true);
|
|
857
|
-
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
|
|
858
|
-
editGroupName(maxind+1, 'Group ' + maxind+1, true);
|
|
856
|
+
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
857
|
+
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
859
858
|
});
|
|
860
859
|
|
|
861
|
-
$(document).ready(function() {
|
|
860
|
+
$(document).ready(function () {
|
|
862
861
|
$('.modal').modal({
|
|
863
862
|
startingTop: '30%',
|
|
864
863
|
endingTop: '10%',
|
|
@@ -882,7 +881,7 @@ function load(settings, onChange) {
|
|
|
882
881
|
$('#pairing').attr('data-tooltip', transText);
|
|
883
882
|
}
|
|
884
883
|
|
|
885
|
-
$('ul.tabs').on('click', 'a', function(e) {
|
|
884
|
+
$('ul.tabs').on('click', 'a', function (e) {
|
|
886
885
|
if ($(e.target).attr('id') == 'tabmap') {
|
|
887
886
|
redrawMap();
|
|
888
887
|
}
|
|
@@ -891,11 +890,11 @@ function load(settings, onChange) {
|
|
|
891
890
|
}
|
|
892
891
|
});
|
|
893
892
|
|
|
894
|
-
$('#add_exclude').click(function() {
|
|
893
|
+
$('#add_exclude').click(function () {
|
|
895
894
|
addExcludeDialog();
|
|
896
895
|
});
|
|
897
896
|
|
|
898
|
-
$('#add_binding').click(function() {
|
|
897
|
+
$('#add_binding').click(function () {
|
|
899
898
|
addBindingDialog();
|
|
900
899
|
});
|
|
901
900
|
|
|
@@ -934,7 +933,7 @@ function save(callback) {
|
|
|
934
933
|
const $this = $(this);
|
|
935
934
|
if (savedSettings.indexOf($this.attr('id')) === -1) return;
|
|
936
935
|
if ($this.hasClass('validate') && $this.hasClass('invalid')) {
|
|
937
|
-
showMessage('Invalid input for '
|
|
936
|
+
showMessage('Invalid input for ' + $this.attr('id'), _('Error'));
|
|
938
937
|
return;
|
|
939
938
|
}
|
|
940
939
|
if ($this.attr('type') === 'checkbox') {
|
|
@@ -948,7 +947,7 @@ function save(callback) {
|
|
|
948
947
|
|
|
949
948
|
|
|
950
949
|
function getDevId(adapterDevId) {
|
|
951
|
-
return adapterDevId.split('.').slice(0,3).join('.');
|
|
950
|
+
return adapterDevId.split('.').slice(0, 3).join('.');
|
|
952
951
|
}
|
|
953
952
|
|
|
954
953
|
// subscribe to changes
|
|
@@ -975,7 +974,7 @@ socket.on('stateChange', function (id, state) {
|
|
|
975
974
|
} else {
|
|
976
975
|
$('#pairing').addClass('pulse');
|
|
977
976
|
$('#pairing').html(state.val);
|
|
978
|
-
const percent = 100-100*state.val/($('#countDown').val() || 60);
|
|
977
|
+
const percent = 100 - 100 * state.val / ($('#countDown').val() || 60);
|
|
979
978
|
$('#progress_line').css('width', `${percent}%`);
|
|
980
979
|
}
|
|
981
980
|
} else if (id.match(/\.info\.pairingMessage$/)) {
|
|
@@ -1021,6 +1020,7 @@ socket.on('objectChange', function (id, obj) {
|
|
|
1021
1020
|
}
|
|
1022
1021
|
}
|
|
1023
1022
|
});
|
|
1023
|
+
|
|
1024
1024
|
/*
|
|
1025
1025
|
socket.emit('getObject', 'system.config', function (err, res) {
|
|
1026
1026
|
if (!err && res && res.common) {
|
|
@@ -1033,45 +1033,47 @@ socket.emit('getObject', 'system.config', function (err, res) {
|
|
|
1033
1033
|
function putEventToNode(devId) {
|
|
1034
1034
|
if (network) {
|
|
1035
1035
|
const nodesArray = Object.values(network.body.data.nodes._data);
|
|
1036
|
-
const node = nodesArray.find((node) => {
|
|
1036
|
+
const node = nodesArray.find((node) => {
|
|
1037
|
+
return node.id == devId;
|
|
1038
|
+
});
|
|
1037
1039
|
if (node) {
|
|
1038
1040
|
const exists = networkEvents.find((event) => {
|
|
1039
1041
|
return event.node == node.id;
|
|
1040
1042
|
});
|
|
1041
1043
|
if (!exists) {
|
|
1042
1044
|
networkEvents.push({node: node.id, radius: 0, forward: true});
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1045
|
+
// } else {
|
|
1046
|
+
// exists.radius = 0;
|
|
1047
|
+
// exists.forward = true;
|
|
1046
1048
|
}
|
|
1047
1049
|
}
|
|
1048
1050
|
}
|
|
1049
1051
|
}
|
|
1050
1052
|
|
|
1051
|
-
function showNetworkMap(devices, map){
|
|
1053
|
+
function showNetworkMap(devices, map) {
|
|
1052
1054
|
// create an object with nodes
|
|
1053
1055
|
const nodes = {};
|
|
1054
1056
|
// create an array with edges
|
|
1055
1057
|
const edges = [];
|
|
1056
1058
|
|
|
1057
1059
|
if (map.lqis == undefined || map.lqis.length === 0) { // first init
|
|
1058
|
-
$('#filterParent, #filterSibl, #filterPrvChild, #filterMesh').change(function() {
|
|
1060
|
+
$('#filterParent, #filterSibl, #filterPrvChild, #filterMesh').change(function () {
|
|
1059
1061
|
updateMapFilter();
|
|
1060
1062
|
});
|
|
1061
1063
|
}
|
|
1062
1064
|
|
|
1063
|
-
const createNode = function(dev, mapEntry) {
|
|
1065
|
+
const createNode = function (dev, mapEntry) {
|
|
1064
1066
|
if (dev.common && dev.common.type == 'group') return undefined;
|
|
1065
1067
|
const extInfo = (mapEntry && mapEntry.networkAddress) ? `\n (nwkAddr: 0x${mapEntry.networkAddress.toString(16)} | ${mapEntry.networkAddress})` : '';
|
|
1066
1068
|
const node = {
|
|
1067
1069
|
id: dev._id,
|
|
1068
|
-
label: (dev.link_quality >0 ? dev.common.name
|
|
1069
|
-
title: dev._id.replace(namespace+'.', '') + extInfo,
|
|
1070
|
+
label: (dev.link_quality > 0 ? dev.common.name : `${dev.common.name}\n(disconnected)`),
|
|
1071
|
+
title: dev._id.replace(namespace + '.', '') + extInfo,
|
|
1070
1072
|
shape: 'circularImage',
|
|
1071
1073
|
image: dev.icon,
|
|
1072
1074
|
imagePadding: {top: 5, bottom: 5, left: 5, right: 5},
|
|
1073
1075
|
color: {background: 'white', highlight: {background: 'white'}},
|
|
1074
|
-
font: {color:'#007700'},
|
|
1076
|
+
font: {color: '#007700'},
|
|
1075
1077
|
borderWidth: 1,
|
|
1076
1078
|
borderWidthSelected: 4,
|
|
1077
1079
|
};
|
|
@@ -1085,7 +1087,7 @@ function showNetworkMap(devices, map){
|
|
|
1085
1087
|
};
|
|
1086
1088
|
|
|
1087
1089
|
if (map.lqis) {
|
|
1088
|
-
map.lqis.forEach((mapEntry)=>{
|
|
1090
|
+
map.lqis.forEach((mapEntry) => {
|
|
1089
1091
|
const dev = getDevice(mapEntry.ieeeAddr);
|
|
1090
1092
|
if (!dev) {
|
|
1091
1093
|
//console.log("No dev with ieee "+mapEntry.ieeeAddr);
|
|
@@ -1098,8 +1100,7 @@ function showNetworkMap(devices, map){
|
|
|
1098
1100
|
if (node) {
|
|
1099
1101
|
nodes[mapEntry.ieeeAddr] = node;
|
|
1100
1102
|
}
|
|
1101
|
-
}
|
|
1102
|
-
else {
|
|
1103
|
+
} else {
|
|
1103
1104
|
node = nodes[mapEntry.ieeeAddr];
|
|
1104
1105
|
}
|
|
1105
1106
|
if (node) {
|
|
@@ -1117,7 +1118,7 @@ function showNetworkMap(devices, map){
|
|
|
1117
1118
|
|
|
1118
1119
|
if (mapEntry.relationship === 0 || mapEntry.relationship === 1) { // 0 - parent, 1 - child
|
|
1119
1120
|
// // parent/child
|
|
1120
|
-
if (mapEntry.status !== 'online'
|
|
1121
|
+
if (mapEntry.status !== 'online') {
|
|
1121
1122
|
label = label + ' (off)';
|
|
1122
1123
|
linkColor = '#ff0000';
|
|
1123
1124
|
}
|
|
@@ -1134,8 +1135,8 @@ function showNetworkMap(devices, map){
|
|
|
1134
1135
|
if (reverse) {
|
|
1135
1136
|
// update reverse edge
|
|
1136
1137
|
edge = reverse;
|
|
1137
|
-
edge.label += '\n'+label;
|
|
1138
|
-
edge.arrows.from = {
|
|
1138
|
+
edge.label += '\n' + label;
|
|
1139
|
+
edge.arrows.from = {enabled: false, scaleFactor: 0.5}; // start hidden if node is not selected
|
|
1139
1140
|
if (mapEntry.relationship == 1) { //
|
|
1140
1141
|
edge.color.color = linkColor;
|
|
1141
1142
|
edge.color.highlight = linkColor;
|
|
@@ -1150,7 +1151,7 @@ function showNetworkMap(devices, map){
|
|
|
1150
1151
|
size: 0, // start hidden
|
|
1151
1152
|
color: linkColor
|
|
1152
1153
|
},
|
|
1153
|
-
arrows: {
|
|
1154
|
+
arrows: {to: {enabled: false, scaleFactor: 0.5}},
|
|
1154
1155
|
//arrowStrikethrough: false,
|
|
1155
1156
|
color: {
|
|
1156
1157
|
color: linkColor,
|
|
@@ -1164,7 +1165,7 @@ function showNetworkMap(devices, map){
|
|
|
1164
1165
|
values.fromArrow = values.fromArrowScale != 1 ? true : false; // simplified, arrow existing if scale is not default value
|
|
1165
1166
|
},
|
|
1166
1167
|
label: () => {
|
|
1167
|
-
|
|
1168
|
+
// see onMapSelect workaround
|
|
1168
1169
|
// values.size = 10;
|
|
1169
1170
|
}
|
|
1170
1171
|
},
|
|
@@ -1230,15 +1231,16 @@ function showNetworkMap(devices, map){
|
|
|
1230
1231
|
const nodesArray = Object.values(nodes);
|
|
1231
1232
|
// add devices without network links to map
|
|
1232
1233
|
devices.forEach((dev) => {
|
|
1233
|
-
const node = nodesArray.find((node) => {
|
|
1234
|
+
const node = nodesArray.find((node) => {
|
|
1235
|
+
return node.id == dev._id;
|
|
1236
|
+
});
|
|
1234
1237
|
if (!node) {
|
|
1235
1238
|
const node = createNode(dev);
|
|
1236
1239
|
|
|
1237
|
-
if (node)
|
|
1238
|
-
|
|
1239
|
-
node.font = {color:'#ff0000'};
|
|
1240
|
+
if (node) {
|
|
1241
|
+
node.font = {color: '#ff0000'};
|
|
1240
1242
|
if (dev.info && dev.info.device._type == 'Coordinator') {
|
|
1241
|
-
node.font = {color:'#000000'};
|
|
1243
|
+
node.font = {color: '#000000'};
|
|
1242
1244
|
}
|
|
1243
1245
|
nodesArray.push(node);
|
|
1244
1246
|
}
|
|
@@ -1260,7 +1262,7 @@ function showNetworkMap(devices, map){
|
|
|
1260
1262
|
shape: 'box'
|
|
1261
1263
|
},
|
|
1262
1264
|
layout: {
|
|
1263
|
-
improvedLayout:true,
|
|
1265
|
+
improvedLayout: true,
|
|
1264
1266
|
}
|
|
1265
1267
|
};
|
|
1266
1268
|
|
|
@@ -1271,13 +1273,14 @@ function showNetworkMap(devices, map){
|
|
|
1271
1273
|
// may be moved to edge.chosen.label if fixed
|
|
1272
1274
|
function doSelection(select, edges, data) {
|
|
1273
1275
|
edges.forEach((edgeId => {
|
|
1274
|
-
const
|
|
1276
|
+
const id = (typeof edgeId === 'string') ? edgeId : edgeId.id;
|
|
1277
|
+
const options = data.edges._data.get(id);
|
|
1275
1278
|
if (select) {
|
|
1276
1279
|
options.font.size = 15;
|
|
1277
1280
|
} else {
|
|
1278
1281
|
options.font.size = 0;
|
|
1279
1282
|
}
|
|
1280
|
-
network.clustering.updateEdge(
|
|
1283
|
+
network.clustering.updateEdge(id, options);
|
|
1281
1284
|
}));
|
|
1282
1285
|
}
|
|
1283
1286
|
|
|
@@ -1309,25 +1312,26 @@ function showNetworkMap(devices, map){
|
|
|
1309
1312
|
if (networkEvents.length > 0) {
|
|
1310
1313
|
network.redraw();
|
|
1311
1314
|
const toDelete = [];
|
|
1312
|
-
networkEvents.forEach((event, index)=>{
|
|
1315
|
+
networkEvents.forEach((event, index) => {
|
|
1313
1316
|
if (event.radius >= 1) {
|
|
1314
1317
|
toDelete.push(index);
|
|
1315
1318
|
} else {
|
|
1316
1319
|
event.radius += 0.08;
|
|
1317
1320
|
}
|
|
1318
1321
|
});
|
|
1319
|
-
toDelete.forEach((index)=>{
|
|
1322
|
+
toDelete.forEach((index) => {
|
|
1320
1323
|
networkEvents.splice(index, 1);
|
|
1321
1324
|
});
|
|
1322
1325
|
}
|
|
1323
1326
|
}
|
|
1324
|
-
|
|
1327
|
+
|
|
1328
|
+
network.on('beforeDrawing', function (ctx) {
|
|
1325
1329
|
if (networkEvents.length > 0) {
|
|
1326
|
-
networkEvents.forEach((event)=>{
|
|
1330
|
+
networkEvents.forEach((event) => {
|
|
1327
1331
|
const inode = event.node;
|
|
1328
1332
|
const nodePosition = network.getPositions();
|
|
1329
1333
|
event.radius = (event.radius > 1) ? 1 : event.radius;
|
|
1330
|
-
const cap = Math.cos(event.radius*Math.PI/2);
|
|
1334
|
+
const cap = Math.cos(event.radius * Math.PI / 2);
|
|
1331
1335
|
const colorCircle = `rgba(0, 255, 255, ${cap.toFixed(2)})`;
|
|
1332
1336
|
const colorBorder = `rgba(0, 255, 255, ${cap.toFixed(2)})`;
|
|
1333
1337
|
ctx.strokeStyle = colorCircle;
|
|
@@ -1344,11 +1348,11 @@ function showNetworkMap(devices, map){
|
|
|
1344
1348
|
function redrawMap() {
|
|
1345
1349
|
if (network != undefined && devices.length > 0) {
|
|
1346
1350
|
const width = ($('.adapter-body').width() || $('#main').width()) - 20,
|
|
1347
|
-
height = ($('.adapter-body').height() || ($('#main').height())) -120;
|
|
1351
|
+
height = ($('.adapter-body').height() || ($('#main').height())) - 120;
|
|
1348
1352
|
network.setSize(width, height);
|
|
1349
1353
|
network.redraw();
|
|
1350
1354
|
network.fit();
|
|
1351
|
-
network.moveTo({offset:{x:0.5 * width, y:0.5 * height}});
|
|
1355
|
+
network.moveTo({offset: {x: 0.5 * width, y: 0.5 * height}});
|
|
1352
1356
|
}
|
|
1353
1357
|
}
|
|
1354
1358
|
|
|
@@ -1362,9 +1366,9 @@ function updateMapFilter() {
|
|
|
1362
1366
|
const invisColor = $('#filterMesh').is(':checked') ? 0.2 : 0;
|
|
1363
1367
|
mapEdges.forEach((edge) => {
|
|
1364
1368
|
if (((edge.relationship === 0 || edge.relationship === 1) && showParent)
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1369
|
+
|| (edge.relationship === 2 && showSibl)
|
|
1370
|
+
|| (edge.relationship === 3 && showParent) // ignore relationship "unknown"
|
|
1371
|
+
|| (edge.relationship === 4 && showPrvChild)) {
|
|
1368
1372
|
edge.color.opacity = 1.0;
|
|
1369
1373
|
} else {
|
|
1370
1374
|
edge.color.opacity = invisColor;
|
|
@@ -1388,13 +1392,15 @@ function getComPorts(onChange) {
|
|
|
1388
1392
|
// }, 1000);
|
|
1389
1393
|
// return;
|
|
1390
1394
|
// }
|
|
1391
|
-
if (!list)
|
|
1395
|
+
if (!list) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1392
1398
|
const element = $('#ports');
|
|
1393
1399
|
for (let j = 0; j < list.length; j++) {
|
|
1394
|
-
element.append('<li><a href="#!">' + list[j].comName +'</a></li>');
|
|
1400
|
+
element.append('<li><a href="#!" data-value="' + list[j].comName + '">' + list[j].comName + (list[j].label ? (' [' + list[j].label + ']') : '') + '</a></li>');
|
|
1395
1401
|
}
|
|
1396
|
-
$('#ports a').click(function() {
|
|
1397
|
-
$('#port').val($(this).
|
|
1402
|
+
$('#ports a').click(function () {
|
|
1403
|
+
$('#port').val($(this).data('value'));
|
|
1398
1404
|
Materialize.updateTextFields();
|
|
1399
1405
|
onChange();
|
|
1400
1406
|
});
|
|
@@ -1404,29 +1410,33 @@ function getComPorts(onChange) {
|
|
|
1404
1410
|
function loadDeveloperTab() {
|
|
1405
1411
|
// fill device selector
|
|
1406
1412
|
updateSelect('#dev', devices,
|
|
1407
|
-
function(key, device) {
|
|
1413
|
+
function (key, device) {
|
|
1408
1414
|
if (device.hasOwnProperty('info')) {
|
|
1409
|
-
if (device.info.device._type
|
|
1415
|
+
if (device.info.device._type === 'Coordinator') {
|
|
1410
1416
|
return null;
|
|
1411
1417
|
}
|
|
1412
1418
|
return `${device.common.name} (${device.info.name})`;
|
|
1413
1419
|
} else { // fallback if device in list but not paired
|
|
1414
|
-
device.common.name + ' ' +device.native.id;
|
|
1420
|
+
return device.common.name + ' ' + device.native.id;
|
|
1415
1421
|
}
|
|
1416
1422
|
},
|
|
1417
|
-
function(key, device) {
|
|
1423
|
+
function (key, device) {
|
|
1418
1424
|
return device._id;
|
|
1419
1425
|
});
|
|
1420
1426
|
// add groups to device selector
|
|
1421
1427
|
const groupList = [];
|
|
1422
1428
|
for (const key in groups) {
|
|
1423
|
-
groupList.push({
|
|
1429
|
+
groupList.push({
|
|
1430
|
+
_id: namespace + '.' + key.toString(16).padStart(16, '0'),
|
|
1431
|
+
groupId: key,
|
|
1432
|
+
groupName: groups[key]
|
|
1433
|
+
});
|
|
1424
1434
|
}
|
|
1425
1435
|
updateSelect('#dev', groupList,
|
|
1426
|
-
function(key, device) {
|
|
1427
|
-
return 'Group '+device.groupId+': '+device.groupName;
|
|
1436
|
+
function (key, device) {
|
|
1437
|
+
return 'Group ' + device.groupId + ': ' + device.groupName;
|
|
1428
1438
|
},
|
|
1429
|
-
function(key, device) {
|
|
1439
|
+
function (key, device) {
|
|
1430
1440
|
return device._id;
|
|
1431
1441
|
}, true);
|
|
1432
1442
|
|
|
@@ -1436,10 +1446,10 @@ function loadDeveloperTab() {
|
|
|
1436
1446
|
populateSelector('#type', 'typeList', this.value);
|
|
1437
1447
|
|
|
1438
1448
|
if (responseCodes == false) {
|
|
1439
|
-
const getValue = function() { // convert to number if needed
|
|
1449
|
+
const getValue = function () { // convert to number if needed
|
|
1440
1450
|
let attrData = $('#value-input').val();
|
|
1441
1451
|
if (attrData.startsWith('"') && attrData.endsWith('"')) {
|
|
1442
|
-
attrData = attrData.substr(1, attrData.length -2);
|
|
1452
|
+
attrData = attrData.substr(1, attrData.length - 2);
|
|
1443
1453
|
} else {
|
|
1444
1454
|
const numValue = Number(attrData);
|
|
1445
1455
|
attrData = !isNaN(numValue) ? numValue : attrData;
|
|
@@ -1464,35 +1474,38 @@ function loadDeveloperTab() {
|
|
|
1464
1474
|
return data;
|
|
1465
1475
|
};
|
|
1466
1476
|
|
|
1467
|
-
const prepareExpertData = function() {
|
|
1477
|
+
const prepareExpertData = function () {
|
|
1468
1478
|
try {
|
|
1469
1479
|
return JSON.parse($('#expert-json').val());
|
|
1470
1480
|
} catch (exception) {
|
|
1471
1481
|
showDevRunInfo('JSON error', exception, 'yellow');
|
|
1472
1482
|
}
|
|
1473
1483
|
};
|
|
1474
|
-
const setExpertData = function(prop, value, removeIfEmpty = true) {
|
|
1484
|
+
const setExpertData = function (prop, value, removeIfEmpty = true) {
|
|
1475
1485
|
if (!$('#expert-mode').is(':checked')) {
|
|
1476
1486
|
return;
|
|
1477
1487
|
}
|
|
1478
|
-
if (!removeIfEmpty && value == null) {
|
|
1488
|
+
if (!removeIfEmpty && value == null) {
|
|
1489
|
+
value = '';
|
|
1490
|
+
}
|
|
1479
1491
|
let data;
|
|
1480
1492
|
if (prop) {
|
|
1481
1493
|
data = prepareExpertData();
|
|
1482
1494
|
// https://stackoverflow.com/a/6394168/6937282
|
|
1483
|
-
const assignVal = function index(obj,is, value) {
|
|
1495
|
+
const assignVal = function index(obj, is, value) {
|
|
1484
1496
|
if (typeof is == 'string') {
|
|
1485
|
-
return index(obj,is.split('.'), value);
|
|
1486
|
-
} else if (is.length
|
|
1497
|
+
return index(obj, is.split('.'), value);
|
|
1498
|
+
} else if (is.length === 1 && value !== undefined) {
|
|
1487
1499
|
if (value == null) {
|
|
1488
1500
|
return delete obj[is[0]];
|
|
1489
1501
|
} else {
|
|
1490
1502
|
return obj[is[0]] = value;
|
|
1491
1503
|
}
|
|
1492
|
-
} else if (is.length
|
|
1504
|
+
} else if (!is.length) {
|
|
1493
1505
|
return obj;
|
|
1494
|
-
} else
|
|
1495
|
-
return index(obj[is[0]],is.slice(1), value);
|
|
1506
|
+
} else {
|
|
1507
|
+
return index(obj[is[0]], is.slice(1), value);
|
|
1508
|
+
}
|
|
1496
1509
|
};
|
|
1497
1510
|
assignVal(data, prop, value);
|
|
1498
1511
|
} else {
|
|
@@ -1502,7 +1515,7 @@ function loadDeveloperTab() {
|
|
|
1502
1515
|
};
|
|
1503
1516
|
|
|
1504
1517
|
// init event listener only at first load
|
|
1505
|
-
$('#dev-selector').change(function() {
|
|
1518
|
+
$('#dev-selector').change(function () {
|
|
1506
1519
|
if (this.selectedIndex <= 0) {
|
|
1507
1520
|
return;
|
|
1508
1521
|
}
|
|
@@ -1513,48 +1526,48 @@ function loadDeveloperTab() {
|
|
|
1513
1526
|
|
|
1514
1527
|
const epList = device ? device.info.device._endpoints : null;
|
|
1515
1528
|
updateSelect('#ep', epList,
|
|
1516
|
-
function(key, ep) {
|
|
1529
|
+
function (key, ep) {
|
|
1517
1530
|
return ep.ID;
|
|
1518
1531
|
},
|
|
1519
|
-
function(key, ep) {
|
|
1532
|
+
function (key, ep) {
|
|
1520
1533
|
return ep.ID;
|
|
1521
1534
|
});
|
|
1522
1535
|
setExpertData('devId', this.value);
|
|
1523
1536
|
setExpertData('ep', $('#ep-selector').val(), false);
|
|
1524
1537
|
});
|
|
1525
1538
|
|
|
1526
|
-
$('#ep-selector').change(function() {
|
|
1539
|
+
$('#ep-selector').change(function () {
|
|
1527
1540
|
setExpertData('ep', this.value);
|
|
1528
1541
|
});
|
|
1529
1542
|
|
|
1530
|
-
$('#cid-selector').change(function() {
|
|
1543
|
+
$('#cid-selector').change(function () {
|
|
1531
1544
|
populateSelector('#attrid', 'attrIdList', this.value);
|
|
1532
|
-
if ($('#cmd-type-selector').val()
|
|
1545
|
+
if ($('#cmd-type-selector').val() === 'functional') {
|
|
1533
1546
|
const cid = $('#cid-selector option:selected').val();
|
|
1534
1547
|
populateSelector('#cmd', 'cmdListFunctional', cid);
|
|
1535
1548
|
}
|
|
1536
1549
|
setExpertData('cid', this.value);
|
|
1537
1550
|
});
|
|
1538
1551
|
|
|
1539
|
-
$('#cmd-type-selector').change(function() {
|
|
1540
|
-
if (this.value
|
|
1552
|
+
$('#cmd-type-selector').change(function () {
|
|
1553
|
+
if (this.value === 'foundation') {
|
|
1541
1554
|
populateSelector('#cmd', 'cmdListFoundation');
|
|
1542
|
-
} else if (this.value
|
|
1555
|
+
} else if (this.value === 'functional') {
|
|
1543
1556
|
const cid = $('#cid-selector option:selected').val();
|
|
1544
1557
|
populateSelector('#cmd', 'cmdListFunctional', cid);
|
|
1545
1558
|
}
|
|
1546
1559
|
setExpertData('cmdType', this.value);
|
|
1547
1560
|
});
|
|
1548
1561
|
|
|
1549
|
-
$('#cmd-selector').change(function() {
|
|
1562
|
+
$('#cmd-selector').change(function () {
|
|
1550
1563
|
setExpertData('cmd', this.value);
|
|
1551
1564
|
});
|
|
1552
|
-
$('#attrid-selector').change(function() {
|
|
1553
|
-
setExpertData('zclData', {[this.value]:{}});
|
|
1565
|
+
$('#attrid-selector').change(function () {
|
|
1566
|
+
setExpertData('zclData', {[this.value]: {}});
|
|
1554
1567
|
});
|
|
1555
1568
|
|
|
1556
1569
|
// value selector checkbox
|
|
1557
|
-
$('#value-needed').change(function() {
|
|
1570
|
+
$('#value-needed').change(function () {
|
|
1558
1571
|
const attr = $('#attrid-selector').val();
|
|
1559
1572
|
let attrData = null;
|
|
1560
1573
|
if (this.checked === true) {
|
|
@@ -1563,17 +1576,17 @@ function loadDeveloperTab() {
|
|
|
1563
1576
|
} else {
|
|
1564
1577
|
$('#value-input').attr('disabled', 'disabled');
|
|
1565
1578
|
}
|
|
1566
|
-
setExpertData('zclData.'+attr, attrData);
|
|
1579
|
+
setExpertData('zclData.' + attr, attrData);
|
|
1567
1580
|
$('#type-selector').select();
|
|
1568
1581
|
Materialize.updateTextFields();
|
|
1569
1582
|
});
|
|
1570
1583
|
|
|
1571
|
-
$('#value-input').keyup(function() {
|
|
1584
|
+
$('#value-input').keyup(function () {
|
|
1572
1585
|
const attr = $('#attrid-selector').val();
|
|
1573
|
-
setExpertData('zclData.'+attr, getValue());
|
|
1586
|
+
setExpertData('zclData.' + attr, getValue());
|
|
1574
1587
|
});
|
|
1575
1588
|
|
|
1576
|
-
$('#expert-mode').change(function() {
|
|
1589
|
+
$('#expert-mode').change(function () {
|
|
1577
1590
|
if (this.checked === true) {
|
|
1578
1591
|
setExpertData();
|
|
1579
1592
|
$('#expert-json-box').css('display', 'inline-block');
|
|
@@ -1584,7 +1597,7 @@ function loadDeveloperTab() {
|
|
|
1584
1597
|
Materialize.updateTextFields();
|
|
1585
1598
|
});
|
|
1586
1599
|
|
|
1587
|
-
$('#dev-send-btn').click(function() {
|
|
1600
|
+
$('#dev-send-btn').click(function () {
|
|
1588
1601
|
let data;
|
|
1589
1602
|
if ($('#expert-mode').is(':checked')) {
|
|
1590
1603
|
data = prepareExpertData();
|
|
@@ -1592,7 +1605,7 @@ function loadDeveloperTab() {
|
|
|
1592
1605
|
data = prepareData();
|
|
1593
1606
|
}
|
|
1594
1607
|
sendToZigbee(data.devId, data.ep, data.cid, data.cmd, data.cmdType, data.zclData, data.cfg, function (reply) {
|
|
1595
|
-
console.log('Reply from zigbee: '+ JSON.stringify(reply));
|
|
1608
|
+
console.log('Reply from zigbee: ' + JSON.stringify(reply));
|
|
1596
1609
|
if (reply.hasOwnProperty('localErr')) {
|
|
1597
1610
|
showDevRunInfo(reply.localErr, reply.errMsg, 'yellow');
|
|
1598
1611
|
} else if (reply.hasOwnProperty('localStatus')) {
|
|
@@ -1633,25 +1646,34 @@ function loadDeveloperTab() {
|
|
|
1633
1646
|
*/
|
|
1634
1647
|
function sendToZigbee(id, ep, cid, cmd, cmdType, zclData, cfg, callback) {
|
|
1635
1648
|
if (!id) {
|
|
1636
|
-
if (callback) {
|
|
1649
|
+
if (callback) {
|
|
1650
|
+
callback({localErr: 'Incomplete', errMsg: 'Please select Device and Endpoint!'});
|
|
1651
|
+
}
|
|
1637
1652
|
return;
|
|
1638
1653
|
}
|
|
1639
1654
|
if (!cid || !cmd || !cmdType) {
|
|
1640
|
-
if (callback) {
|
|
1655
|
+
if (callback) {
|
|
1656
|
+
callback({
|
|
1657
|
+
localErr: 'Incomplete',
|
|
1658
|
+
errMsg: 'Please choose ClusterId, Command, CommandType and AttributeId!'
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1641
1661
|
return;
|
|
1642
1662
|
}
|
|
1643
1663
|
const data = {id: id, ep: ep, cid: cid, cmd: cmd, cmdType: cmdType, zclData: zclData, cfg: cfg};
|
|
1644
|
-
if (callback) {
|
|
1664
|
+
if (callback) {
|
|
1665
|
+
callback({localStatus: 'Send', errMsg: 'Waiting for reply...'});
|
|
1666
|
+
}
|
|
1645
1667
|
|
|
1646
|
-
const sendTimeout = setTimeout(function() {
|
|
1668
|
+
const sendTimeout = setTimeout(function () {
|
|
1647
1669
|
if (callback) {
|
|
1648
1670
|
callback({localErr: 'Timeout', errMsg: 'We did not receive any response.'});
|
|
1649
1671
|
}
|
|
1650
1672
|
}, 15000);
|
|
1651
1673
|
|
|
1652
|
-
console.log('Send to zigbee, id '+id+ ',ep '+ep+', cid '+cid+', cmd '+cmd+', cmdType '+cmdType+', zclData '+JSON.stringify(zclData));
|
|
1674
|
+
console.log('Send to zigbee, id ' + id + ',ep ' + ep + ', cid ' + cid + ', cmd ' + cmd + ', cmdType ' + cmdType + ', zclData ' + JSON.stringify(zclData));
|
|
1653
1675
|
|
|
1654
|
-
sendTo(namespace, 'sendToZigbee', data, function(reply) {
|
|
1676
|
+
sendTo(namespace, 'sendToZigbee', data, function (reply) {
|
|
1655
1677
|
clearTimeout(sendTimeout);
|
|
1656
1678
|
if (callback) {
|
|
1657
1679
|
callback(reply);
|
|
@@ -1664,11 +1686,10 @@ function sendToZigbee(id, ep, cid, cmd, cmdType, zclData, cfg, callback) {
|
|
|
1664
1686
|
*/
|
|
1665
1687
|
function showDevRunInfo(result, text, level) {
|
|
1666
1688
|
const card = $('#devActResult');
|
|
1667
|
-
if (level
|
|
1668
|
-
card.removeClass(
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
card.removeClass( 'yellow-text' ).addClass( 'white-text' );
|
|
1689
|
+
if (level === 'yellow') {
|
|
1690
|
+
card.removeClass('white-text').addClass('yellow-text');
|
|
1691
|
+
} else {
|
|
1692
|
+
card.removeClass('yellow-text').addClass('white-text');
|
|
1672
1693
|
}
|
|
1673
1694
|
$('#devActResult').text(result);
|
|
1674
1695
|
$('#devInfoMsg').text(text);
|
|
@@ -1676,13 +1697,13 @@ function showDevRunInfo(result, text, level) {
|
|
|
1676
1697
|
|
|
1677
1698
|
function addDevLog(reply) {
|
|
1678
1699
|
const statusCode = reply.statusCode;
|
|
1679
|
-
let logHtml = '<span>'+JSON.stringify(reply.msg)+'</span><br>';
|
|
1700
|
+
let logHtml = '<span>' + JSON.stringify(reply.msg) + '</span><br>';
|
|
1680
1701
|
if (responseCodes != undefined) {
|
|
1681
1702
|
const status = Object.keys(responseCodes).find(key => responseCodes[key] === statusCode);
|
|
1682
1703
|
if (statusCode == 0) {
|
|
1683
|
-
logHtml = '<span class="green-text">'+status+'</span> '+logHtml;
|
|
1704
|
+
logHtml = '<span class="green-text">' + status + '</span> ' + logHtml;
|
|
1684
1705
|
} else {
|
|
1685
|
-
logHtml = '<span class="yellow-text">'+status+'</span> '+logHtml;
|
|
1706
|
+
logHtml = '<span class="yellow-text">' + status + '</span> ' + logHtml;
|
|
1686
1707
|
}
|
|
1687
1708
|
}
|
|
1688
1709
|
const logView = $('#dev_result_log');
|
|
@@ -1694,7 +1715,7 @@ function addDevLog(reply) {
|
|
|
1694
1715
|
* Query adapter and update select with result
|
|
1695
1716
|
*/
|
|
1696
1717
|
function populateSelector(selectId, key, cid) {
|
|
1697
|
-
$(selectId+'>option:enabled').remove(); // remove existing elements
|
|
1718
|
+
$(selectId + '>option:enabled').remove(); // remove existing elements
|
|
1698
1719
|
$(selectId).select();
|
|
1699
1720
|
if (cid == '-2') {
|
|
1700
1721
|
updateSelect(selectId, null);
|
|
@@ -1705,7 +1726,7 @@ function populateSelector(selectId, key, cid) {
|
|
|
1705
1726
|
if (key === 'attrIdList') {
|
|
1706
1727
|
updateSelect(selectId, list,
|
|
1707
1728
|
(attrName, attr) => {
|
|
1708
|
-
return attrName + ' ('+attr.ID +', type '+attr.type+')';
|
|
1729
|
+
return attrName + ' (' + attr.ID + ', type ' + attr.type + ')';
|
|
1709
1730
|
},
|
|
1710
1731
|
(attrName) => {
|
|
1711
1732
|
return attrName;
|
|
@@ -1713,7 +1734,7 @@ function populateSelector(selectId, key, cid) {
|
|
|
1713
1734
|
} else if (key === 'typeList') {
|
|
1714
1735
|
updateSelect(selectId, list,
|
|
1715
1736
|
(name, val) => {
|
|
1716
|
-
return name +' ('+val+')';
|
|
1737
|
+
return name + ' (' + val + ')';
|
|
1717
1738
|
},
|
|
1718
1739
|
(name, val) => {
|
|
1719
1740
|
return val;
|
|
@@ -1721,7 +1742,7 @@ function populateSelector(selectId, key, cid) {
|
|
|
1721
1742
|
} else {
|
|
1722
1743
|
updateSelect(selectId, list,
|
|
1723
1744
|
(propName, propInfo) => {
|
|
1724
|
-
return propName +' ('+propInfo.ID+')';
|
|
1745
|
+
return propName + ' (' + propInfo.ID + ')';
|
|
1725
1746
|
},
|
|
1726
1747
|
(propName) => {
|
|
1727
1748
|
return propName;
|
|
@@ -1731,32 +1752,31 @@ function populateSelector(selectId, key, cid) {
|
|
|
1731
1752
|
}
|
|
1732
1753
|
|
|
1733
1754
|
function updateSelect(id, list, getText, getId, append = false) {
|
|
1734
|
-
const selectId = id+'-selector';
|
|
1755
|
+
const selectId = id + '-selector';
|
|
1735
1756
|
const mySelect = $(selectId);
|
|
1736
1757
|
if (!append) {
|
|
1737
|
-
$(selectId+'>:not(:first[disabled])').remove(); // remove existing elements, except first if disabled, (is 'Select...' info)
|
|
1758
|
+
$(selectId + '>:not(:first[disabled])').remove(); // remove existing elements, except first if disabled, (is 'Select...' info)
|
|
1738
1759
|
mySelect.select();
|
|
1739
1760
|
}
|
|
1740
1761
|
if (list == null && !append) {
|
|
1741
1762
|
const infoOption = new Option('Nothing available');
|
|
1742
1763
|
infoOption.disabled = true;
|
|
1743
|
-
mySelect.append(
|
|
1744
|
-
}
|
|
1745
|
-
else {
|
|
1764
|
+
mySelect.append(infoOption);
|
|
1765
|
+
} else {
|
|
1746
1766
|
const keys = Object.keys(list); // is index in case of array
|
|
1747
|
-
for (let i=0; i<keys.length; i++) {
|
|
1767
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1748
1768
|
const key = keys[i];
|
|
1749
1769
|
const item = list[key];
|
|
1750
1770
|
const optionText = getText(key, item);
|
|
1751
1771
|
if (optionText == null) {
|
|
1752
1772
|
continue;
|
|
1753
1773
|
}
|
|
1754
|
-
mySelect.append(
|
|
1774
|
+
mySelect.append(new Option(optionText, getId(key, item)));
|
|
1755
1775
|
}
|
|
1756
1776
|
}
|
|
1757
1777
|
|
|
1758
|
-
if ($(id+'-c-input').length > 0) {
|
|
1759
|
-
mySelect.append(
|
|
1778
|
+
if ($(id + '-c-input').length > 0) {
|
|
1779
|
+
mySelect.append(new Option('CUSTOM', -2));
|
|
1760
1780
|
}
|
|
1761
1781
|
// update select element (Materialize)
|
|
1762
1782
|
mySelect.select();
|
|
@@ -1785,17 +1805,17 @@ function showGroups() {
|
|
|
1785
1805
|
const element = $('#groups_table');
|
|
1786
1806
|
for (const j in groups) {
|
|
1787
1807
|
if (groups.hasOwnProperty(j)) {
|
|
1788
|
-
element.append(`<tr id="group_${j}" class="group"><td>${j}</td><td><div>${groups[j]}<span class="right"
|
|
1789
|
-
|
|
1790
|
-
|
|
1808
|
+
element.append(`<tr id="group_${j}" class="group"><td>${j}</td><td><div>${groups[j]}<span class="right">` +
|
|
1809
|
+
`<a id="${j}" name="groupedit" class="waves-effect green btn-floating"><i class="material-icons">edit</i></a>` +
|
|
1810
|
+
`<a id="${j}" name="groupdelete" class="waves-effect red btn-floating"><i class="material-icons">delete</i></a></span></div></td></tr>`);
|
|
1791
1811
|
}
|
|
1792
1812
|
}
|
|
1793
|
-
$(
|
|
1813
|
+
$('a.btn-floating[name=\'groupedit\']').click(function () {
|
|
1794
1814
|
const index = $(this).attr('id'),
|
|
1795
1815
|
name = groups[index];
|
|
1796
1816
|
editGroupName(index, name, false);
|
|
1797
1817
|
});
|
|
1798
|
-
$(
|
|
1818
|
+
$('a.btn-floating[name=\'groupdelete\']').click(function () {
|
|
1799
1819
|
const index = $(this).attr('id'),
|
|
1800
1820
|
name = groups[index];
|
|
1801
1821
|
deleteGroupConfirmation(index, name);
|
|
@@ -1807,53 +1827,51 @@ function editGroupName(id, name, isnew) {
|
|
|
1807
1827
|
//console.log('devices: '+ JSON.stringify(devices));
|
|
1808
1828
|
const groupables = [];
|
|
1809
1829
|
for (const d of devices) {
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
//console.log('device ' + JSON.stringify(d));
|
|
1830
|
+
if (d && d.info && d.info.endpoints) {
|
|
1831
|
+
for (const ep of d.info.endpoints) {
|
|
1832
|
+
if (ep.inputClusters.includes(4)) {
|
|
1833
|
+
groupables.push(ep);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
//console.log('device ' + JSON.stringify(d));
|
|
1819
1838
|
}
|
|
1820
1839
|
|
|
1821
1840
|
//var text = 'Enter new name for "'+name+'" ('+id+')?';
|
|
1822
1841
|
if (isnew) {
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
$('#groupedit').find('.input-field.groupid').addClass('hide');
|
|
1842
|
+
$('#groupedit').find('.editgroup').addClass('hide');
|
|
1843
|
+
$('#groupedit').find('.addgroup').removeClass('hide');
|
|
1844
|
+
$('#groupedit').find('.input-field.members').addClass('hide');
|
|
1845
|
+
$('#groupedit').find('.input-field.groupid').removeClass('hide');
|
|
1846
|
+
} else {
|
|
1847
|
+
$('#groupedit').find('.editgroup').removeClass('hide');
|
|
1848
|
+
$('#groupedit').find('.addgroup').addClass('hide');
|
|
1849
|
+
$('#groupedit').find('.input-field.members').removeClass('hide');
|
|
1850
|
+
$('#groupedit').find('.input-field.groupid').addClass('hide');
|
|
1833
1851
|
}
|
|
1834
|
-
$('#groupedit').find(
|
|
1835
|
-
$('#groupedit').find(
|
|
1836
|
-
$(
|
|
1837
|
-
$(
|
|
1838
|
-
const newId = $('#groupedit').find(
|
|
1839
|
-
newName = $('#groupedit').find(
|
|
1852
|
+
$('#groupedit').find('input[id=\'g_index\']').val(id);
|
|
1853
|
+
$('#groupedit').find('input[id=\'g_name\']').val(name);
|
|
1854
|
+
$('#groupedit a.btn[name=\'save\']').unbind('click');
|
|
1855
|
+
$('#groupedit a.btn[name=\'save\']').click(() => {
|
|
1856
|
+
const newId = $('#groupedit').find('input[id=\'g_index\']').val(),
|
|
1857
|
+
newName = $('#groupedit').find('input[id=\'g_name\']').val();
|
|
1840
1858
|
updateGroup(id, newId, newName);
|
|
1841
|
-
//
|
|
1842
|
-
//
|
|
1859
|
+
// showGroups();
|
|
1860
|
+
// getDevices();
|
|
1843
1861
|
});
|
|
1844
1862
|
$('#groupedit').modal('open');
|
|
1845
1863
|
Materialize.updateTextFields();
|
|
1846
1864
|
}
|
|
1847
1865
|
|
|
1848
1866
|
function deleteGroupConfirmation(id, name) {
|
|
1849
|
-
const text = translateWord('Do you really whant to delete group') + ' "'+name+'" ('+id+')?';
|
|
1867
|
+
const text = translateWord('Do you really whant to delete group') + ' "' + name + '" (' + id + ')?';
|
|
1850
1868
|
$('#modaldelete').find('p').text(text);
|
|
1851
1869
|
$('#forcediv').addClass('hide');
|
|
1852
|
-
$(
|
|
1853
|
-
$(
|
|
1870
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
1871
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
1854
1872
|
deleteGroup(id);
|
|
1855
|
-
//
|
|
1856
|
-
//
|
|
1873
|
+
// showGroups();
|
|
1874
|
+
// getDevices();
|
|
1857
1875
|
});
|
|
1858
1876
|
$('#modaldelete').modal('open');
|
|
1859
1877
|
}
|
|
@@ -1861,8 +1879,8 @@ function deleteGroupConfirmation(id, name) {
|
|
|
1861
1879
|
function updateGroup(id, newId, newName) {
|
|
1862
1880
|
delete groups[id];
|
|
1863
1881
|
groups[newId] = newName;
|
|
1864
|
-
sendTo(namespace, 'renameGroup', {
|
|
1865
|
-
if (msg &&
|
|
1882
|
+
sendTo(namespace, 'renameGroup', {id: newId, name: newName}, function (msg) {
|
|
1883
|
+
if (msg && msg.error) {
|
|
1866
1884
|
showMessage(msg.error, _('Error'));
|
|
1867
1885
|
}
|
|
1868
1886
|
getDevices();
|
|
@@ -1871,8 +1889,8 @@ function updateGroup(id, newId, newName) {
|
|
|
1871
1889
|
|
|
1872
1890
|
function deleteGroup(id) {
|
|
1873
1891
|
delete groups[id];
|
|
1874
|
-
sendTo(namespace, 'deleteGroup', id
|
|
1875
|
-
if (msg &&
|
|
1892
|
+
sendTo(namespace, 'deleteGroup', id, function (msg) {
|
|
1893
|
+
if (msg && msg.error) {
|
|
1876
1894
|
showMessage(msg.error, _('Error'));
|
|
1877
1895
|
}
|
|
1878
1896
|
getDevices();
|
|
@@ -1880,58 +1898,55 @@ function deleteGroup(id) {
|
|
|
1880
1898
|
}
|
|
1881
1899
|
|
|
1882
1900
|
function updateDev(id, newName, newGroups) {
|
|
1883
|
-
const dev = devices.find((d) => d._id
|
|
1884
|
-
if (dev && dev.common.name
|
|
1901
|
+
const dev = devices.find((d) => d._id === id);
|
|
1902
|
+
if (dev && dev.common.name !== newName) {
|
|
1885
1903
|
renameDevice(id, newName);
|
|
1886
1904
|
}
|
|
1887
|
-
const keys = Object.keys(newGroups)
|
|
1888
|
-
if (keys && keys.length)
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
});
|
|
1901
|
-
showWaitingDialog('Updating group memberships', 10);
|
|
1905
|
+
const keys = Object.keys(newGroups);
|
|
1906
|
+
if (keys && keys.length) {
|
|
1907
|
+
sendTo(namespace, 'updateGroupMembership', {id: id, groups: newGroups}, function (msg) {
|
|
1908
|
+
closeWaitingDialog();
|
|
1909
|
+
if (msg && msg.error) {
|
|
1910
|
+
showMessage(msg.error, _('Error'));
|
|
1911
|
+
} else {
|
|
1912
|
+
// save dev-groups on success
|
|
1913
|
+
dev.groups = newGroups;
|
|
1914
|
+
}
|
|
1915
|
+
showDevices();
|
|
1916
|
+
});
|
|
1917
|
+
showWaitingDialog('Updating group memberships', 10);
|
|
1902
1918
|
|
|
1903
1919
|
}
|
|
1904
|
-
/*
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1920
|
+
/*
|
|
1921
|
+
if (dev.info.device._type == 'Router') {
|
|
1922
|
+
const oldGroups = devGroups[id] || [];
|
|
1923
|
+
if (oldGroups.toString() != newGroups.toString()) {
|
|
1924
|
+
devGroups[id] = newGroups;
|
|
1925
|
+
sendTo(namespace, 'updateGroupMembership', { id: id, groups: newGroups }, function (msg) {
|
|
1926
|
+
if (msg && msg.error) {
|
|
1927
|
+
showMessage(msg.error, _('Error'));
|
|
1928
|
+
}
|
|
1929
|
+
else {
|
|
1930
|
+
// save dev-groups on success
|
|
1931
|
+
dev.groups = newGroups;
|
|
1932
|
+
}
|
|
1933
|
+
showDevices();
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1919
1936
|
}
|
|
1920
|
-
|
|
1921
|
-
*/
|
|
1937
|
+
*/
|
|
1922
1938
|
}
|
|
1923
1939
|
|
|
1924
1940
|
function resetConfirmation() {
|
|
1925
1941
|
$('#modalreset').modal('open');
|
|
1926
1942
|
const btn = $('#modalreset .modal-content a.btn');
|
|
1927
1943
|
btn.unbind('click');
|
|
1928
|
-
btn.click(function(e) {
|
|
1944
|
+
btn.click(function (e) {
|
|
1929
1945
|
sendTo(namespace, 'reset', {mode: e.target.id}, function (err) {
|
|
1930
1946
|
if (err) {
|
|
1931
1947
|
console.log(err);
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
console.log('Reseted');
|
|
1948
|
+
} else {
|
|
1949
|
+
console.log('Reset done');
|
|
1935
1950
|
}
|
|
1936
1951
|
});
|
|
1937
1952
|
});
|
|
@@ -1941,7 +1956,7 @@ function showViewConfig() {
|
|
|
1941
1956
|
$('#modalviewconfig').modal('open');
|
|
1942
1957
|
}
|
|
1943
1958
|
|
|
1944
|
-
function prepareBindingDialog(bindObj){
|
|
1959
|
+
function prepareBindingDialog(bindObj) {
|
|
1945
1960
|
const binddevices = devices.slice();
|
|
1946
1961
|
binddevices.unshift('');
|
|
1947
1962
|
const bind_source = (bindObj) ? [bindObj.bind_source] : [''];
|
|
@@ -1952,12 +1967,12 @@ function prepareBindingDialog(bindObj){
|
|
|
1952
1967
|
const allowClustersName = {5: 'genScenes', 6: 'genOnOff', 8: 'genLevelCtrl', 768: 'lightingColorCtrl'};
|
|
1953
1968
|
// fill device selector
|
|
1954
1969
|
list2select('#bind_source', binddevices, bind_source,
|
|
1955
|
-
function(key, device) {
|
|
1970
|
+
function (key, device) {
|
|
1956
1971
|
if (device == '') {
|
|
1957
1972
|
return 'Select source device';
|
|
1958
1973
|
}
|
|
1959
1974
|
if (device.hasOwnProperty('info')) {
|
|
1960
|
-
if (device.info.device._type
|
|
1975
|
+
if (device.info.device._type === 'Coordinator') {
|
|
1961
1976
|
return null;
|
|
1962
1977
|
}
|
|
1963
1978
|
// check for output clusters
|
|
@@ -1977,19 +1992,18 @@ function prepareBindingDialog(bindObj){
|
|
|
1977
1992
|
return null;
|
|
1978
1993
|
}
|
|
1979
1994
|
return device.common.name;
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
device.common.name + ' ' +device.native.id;
|
|
1995
|
+
} else { // fallback if device in list but not paired
|
|
1996
|
+
return device.common.name + ' ' + device.native.id;
|
|
1983
1997
|
}
|
|
1984
1998
|
},
|
|
1985
|
-
function(key, device) {
|
|
1999
|
+
function (key, device) {
|
|
1986
2000
|
if (device == '') {
|
|
1987
2001
|
return '';
|
|
1988
2002
|
} else {
|
|
1989
2003
|
return device._id;
|
|
1990
2004
|
}
|
|
1991
2005
|
},
|
|
1992
|
-
function(key, device) {
|
|
2006
|
+
function (key, device) {
|
|
1993
2007
|
if (device == '') {
|
|
1994
2008
|
return 'disabled';
|
|
1995
2009
|
} else if (device.icon) {
|
|
@@ -2004,12 +2018,12 @@ function prepareBindingDialog(bindObj){
|
|
|
2004
2018
|
bindtargets.push({'_id': key, 'groupId': key, 'groupName': groups[key]});
|
|
2005
2019
|
}
|
|
2006
2020
|
list2select('#bind_target', bindtargets, bind_target,
|
|
2007
|
-
function(key, device) {
|
|
2021
|
+
function (key, device) {
|
|
2008
2022
|
if (device == '') {
|
|
2009
2023
|
return 'Select target device';
|
|
2010
2024
|
}
|
|
2011
2025
|
if (device.hasOwnProperty('info')) {
|
|
2012
|
-
if (device.info.device._type
|
|
2026
|
+
if (device.info.device._type === 'Coordinator') {
|
|
2013
2027
|
return null;
|
|
2014
2028
|
}
|
|
2015
2029
|
// check for input clusters
|
|
@@ -2035,14 +2049,14 @@ function prepareBindingDialog(bindObj){
|
|
|
2035
2049
|
}
|
|
2036
2050
|
}
|
|
2037
2051
|
},
|
|
2038
|
-
function(key, device) {
|
|
2052
|
+
function (key, device) {
|
|
2039
2053
|
if (device == '') {
|
|
2040
2054
|
return '';
|
|
2041
2055
|
} else {
|
|
2042
2056
|
return device._id;
|
|
2043
2057
|
}
|
|
2044
2058
|
},
|
|
2045
|
-
function(key, device) {
|
|
2059
|
+
function (key, device) {
|
|
2046
2060
|
if (device == '') {
|
|
2047
2061
|
return 'disabled';
|
|
2048
2062
|
} else if (device.icon) {
|
|
@@ -2061,13 +2075,17 @@ function prepareBindingDialog(bindObj){
|
|
|
2061
2075
|
const epList = device ? device.info.endpoints : [];
|
|
2062
2076
|
const sClusterList = epList.map((ep) => {
|
|
2063
2077
|
const clusters = ep.outputClusters.map((cl) => {
|
|
2064
|
-
return allowClusters.includes(cl) ? {ID: ep.ID+'_'+cl, name: allowClustersName[cl]} : null;
|
|
2065
|
-
}).filter((i) => {
|
|
2066
|
-
|
|
2067
|
-
|
|
2078
|
+
return allowClusters.includes(cl) ? {ID: ep.ID + '_' + cl, name: allowClustersName[cl]} : null;
|
|
2079
|
+
}).filter((i) => {
|
|
2080
|
+
return i != null;
|
|
2081
|
+
});
|
|
2082
|
+
return clusters.length == 0 ? null : [{ID: ep.ID, name: 'all'}, clusters];
|
|
2083
|
+
}).flat(2).filter((i) => {
|
|
2084
|
+
return i != null;
|
|
2085
|
+
});
|
|
2068
2086
|
list2select('#bind_source_ep', sClusterList, (selected) ? [selected] : [],
|
|
2069
2087
|
(key, ep) => {
|
|
2070
|
-
return ep.ID+' '+ep.name;
|
|
2088
|
+
return ep.ID + ' ' + ep.name;
|
|
2071
2089
|
},
|
|
2072
2090
|
(key, ep) => {
|
|
2073
2091
|
return ep.ID;
|
|
@@ -2083,13 +2101,20 @@ function prepareBindingDialog(bindObj){
|
|
|
2083
2101
|
const epList = device ? device.info.endpoints : [];
|
|
2084
2102
|
const tClusterList = epList.map((ep) => {
|
|
2085
2103
|
const clusters = ep.inputClusters.map((cl) => {
|
|
2086
|
-
return (allowClusters.includes(cl) && (!sourceCl || sourceCl == cl)) ? {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2104
|
+
return (allowClusters.includes(cl) && (!sourceCl || sourceCl == cl)) ? {
|
|
2105
|
+
ID: ep.ID + '_' + cl,
|
|
2106
|
+
name: allowClustersName[cl]
|
|
2107
|
+
} : null;
|
|
2108
|
+
}).filter((i) => {
|
|
2109
|
+
return i != null;
|
|
2110
|
+
});
|
|
2111
|
+
return !clusters.length ? null : [{ID: ep.ID, name: 'all'}, clusters];
|
|
2112
|
+
}).flat(2).filter(i => {
|
|
2113
|
+
return i != null;
|
|
2114
|
+
});
|
|
2090
2115
|
list2select('#bind_target_ep', tClusterList, (selected) ? [selected] : [],
|
|
2091
2116
|
(key, ep) => {
|
|
2092
|
-
return ep.ID+' '+ep.name;
|
|
2117
|
+
return ep.ID + ' ' + ep.name;
|
|
2093
2118
|
},
|
|
2094
2119
|
(key, ep) => {
|
|
2095
2120
|
return ep.ID;
|
|
@@ -2097,7 +2122,7 @@ function prepareBindingDialog(bindObj){
|
|
|
2097
2122
|
);
|
|
2098
2123
|
};
|
|
2099
2124
|
|
|
2100
|
-
$('#bind_source').change(function() {
|
|
2125
|
+
$('#bind_source').change(function () {
|
|
2101
2126
|
if (this.selectedIndex <= 0) {
|
|
2102
2127
|
return;
|
|
2103
2128
|
}
|
|
@@ -2109,7 +2134,7 @@ function prepareBindingDialog(bindObj){
|
|
|
2109
2134
|
configureSourceEp();
|
|
2110
2135
|
}
|
|
2111
2136
|
|
|
2112
|
-
$('#bind_target').change(function() {
|
|
2137
|
+
$('#bind_target').change(function () {
|
|
2113
2138
|
if (this.selectedIndex <= 0) {
|
|
2114
2139
|
return;
|
|
2115
2140
|
}
|
|
@@ -2122,7 +2147,7 @@ function prepareBindingDialog(bindObj){
|
|
|
2122
2147
|
configureTargetEp();
|
|
2123
2148
|
}
|
|
2124
2149
|
|
|
2125
|
-
$('#bind_source_ep').change(function() {
|
|
2150
|
+
$('#bind_source_ep').change(function () {
|
|
2126
2151
|
$('#bind_target').trigger('change');
|
|
2127
2152
|
});
|
|
2128
2153
|
|
|
@@ -2131,8 +2156,8 @@ function prepareBindingDialog(bindObj){
|
|
|
2131
2156
|
}
|
|
2132
2157
|
|
|
2133
2158
|
function addBindingDialog() {
|
|
2134
|
-
$(
|
|
2135
|
-
$(
|
|
2159
|
+
$('#bindingmodaledit a.btn[name=\'save\']').unbind('click');
|
|
2160
|
+
$('#bindingmodaledit a.btn[name=\'save\']').click(() => {
|
|
2136
2161
|
const //bind_id = $('#bindingmodaledit').find("input[id='bind_id']").val(),
|
|
2137
2162
|
bind_source = $('#bindingmodaledit').find('#bind_source option:selected').val(),
|
|
2138
2163
|
bind_source_ep = $('#bindingmodaledit').find('#bind_source_ep option:selected').val(),
|
|
@@ -2156,10 +2181,8 @@ function addBinding(bind_source, bind_source_ep, bind_target, bind_target_ep, un
|
|
|
2156
2181
|
unbind_from_coordinator
|
|
2157
2182
|
}, function (msg) {
|
|
2158
2183
|
closeWaitingDialog();
|
|
2159
|
-
if (msg) {
|
|
2160
|
-
|
|
2161
|
-
showMessage(msg.error, _('Error'));
|
|
2162
|
-
}
|
|
2184
|
+
if (msg && msg.error) {
|
|
2185
|
+
showMessage(msg.error, _('Error'));
|
|
2163
2186
|
}
|
|
2164
2187
|
getBinding();
|
|
2165
2188
|
});
|
|
@@ -2176,10 +2199,8 @@ function editBinding(bind_id, bind_source, bind_source_ep, bind_target, bind_tar
|
|
|
2176
2199
|
unbind_from_coordinator
|
|
2177
2200
|
}, function (msg) {
|
|
2178
2201
|
closeWaitingDialog();
|
|
2179
|
-
if (msg) {
|
|
2180
|
-
|
|
2181
|
-
showMessage(msg.error, _('Error'));
|
|
2182
|
-
}
|
|
2202
|
+
if (msg && msg.error) {
|
|
2203
|
+
showMessage(msg.error, _('Error'));
|
|
2183
2204
|
}
|
|
2184
2205
|
getBinding();
|
|
2185
2206
|
});
|
|
@@ -2187,8 +2208,8 @@ function editBinding(bind_id, bind_source, bind_source_ep, bind_target, bind_tar
|
|
|
2187
2208
|
}
|
|
2188
2209
|
|
|
2189
2210
|
function editBindingDialog(bindObj) {
|
|
2190
|
-
$(
|
|
2191
|
-
$(
|
|
2211
|
+
$('#bindingmodaledit a.btn[name=\'save\']').unbind('click');
|
|
2212
|
+
$('#bindingmodaledit a.btn[name=\'save\']').click(() => {
|
|
2192
2213
|
const //bind_id = $('#bindingmodaledit').find("input[id='bind_id']").val(),
|
|
2193
2214
|
bind_source = $('#bindingmodaledit').find('#bind_source option:selected').val(),
|
|
2194
2215
|
bind_source_ep = $('#bindingmodaledit').find('#bind_source_ep option:selected').val(),
|
|
@@ -2224,9 +2245,9 @@ function showBinding() {
|
|
|
2224
2245
|
<i class="right">${target_icon}</i>
|
|
2225
2246
|
<div style="min-height:72px; font-size: 0.8em" class="truncate">
|
|
2226
2247
|
<ul>
|
|
2227
|
-
<li><span class="label">source:</span><span>0x${bind_source.replace(namespace+'.', '')}</span></li>
|
|
2248
|
+
<li><span class="label">source:</span><span>0x${bind_source.replace(namespace + '.', '')}</span></li>
|
|
2228
2249
|
<li><span class="label">endpoint:</span><span>${bind_source_ep}</span></li>
|
|
2229
|
-
<li><span class="label">target:</span><span>0x${bind_target.replace(namespace+'.', '')}</span></li>
|
|
2250
|
+
<li><span class="label">target:</span><span>0x${bind_target.replace(namespace + '.', '')}</span></li>
|
|
2230
2251
|
<li><span class="label">endpoint:</span><span>${bind_target_ep}</span></li>
|
|
2231
2252
|
</ul>
|
|
2232
2253
|
</div>
|
|
@@ -2248,11 +2269,11 @@ function showBinding() {
|
|
|
2248
2269
|
element.append(card);
|
|
2249
2270
|
});
|
|
2250
2271
|
|
|
2251
|
-
$(
|
|
2272
|
+
$('#binding button[name=\'delete\']').click(function () {
|
|
2252
2273
|
const bind_id = $(this).parents('.binding')[0].id;
|
|
2253
2274
|
deleteBindingConfirmation(bind_id);
|
|
2254
2275
|
});
|
|
2255
|
-
$(
|
|
2276
|
+
$('#binding button[name=\'edit\']').click(function () {
|
|
2256
2277
|
const bind_id = $(this).parents('.binding')[0].id;
|
|
2257
2278
|
const bindObj = binding.find((b) => b.id == bind_id);
|
|
2258
2279
|
if (bindObj) {
|
|
@@ -2279,8 +2300,8 @@ function deleteBindingConfirmation(id) {
|
|
|
2279
2300
|
$('#modaldelete').find('p').text(text);
|
|
2280
2301
|
//$('#forcediv').removeClass('hide');
|
|
2281
2302
|
$('#forcediv').addClass('hide');
|
|
2282
|
-
$(
|
|
2283
|
-
$(
|
|
2303
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
2304
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
2284
2305
|
deleteBinding(id);
|
|
2285
2306
|
});
|
|
2286
2307
|
$('#modaldelete').modal('open');
|
|
@@ -2313,14 +2334,14 @@ function genDevInfo(device) {
|
|
|
2313
2334
|
const dev = (device && device.info) ? device.info.device : undefined;
|
|
2314
2335
|
const mapped = (device && device.info) ? device.info.mapped : undefined;
|
|
2315
2336
|
if (!dev) return `<div class="truncate">No info</div>`;
|
|
2316
|
-
const genRow = function(name, value, refresh) {
|
|
2337
|
+
const genRow = function (name, value, refresh) {
|
|
2317
2338
|
if (value === undefined) {
|
|
2318
2339
|
return '';
|
|
2319
2340
|
} else {
|
|
2320
2341
|
return `<li><span class="label">${name}:</span><span>${value}</span></li>`;
|
|
2321
2342
|
}
|
|
2322
2343
|
};
|
|
2323
|
-
const genRowValues = function(name, value) {
|
|
2344
|
+
const genRowValues = function (name, value) {
|
|
2324
2345
|
if (value === undefined) {
|
|
2325
2346
|
return '';
|
|
2326
2347
|
} else {
|
|
@@ -2355,7 +2376,7 @@ function genDevInfo(device) {
|
|
|
2355
2376
|
</div>`;
|
|
2356
2377
|
}
|
|
2357
2378
|
const imgSrc = device.icon || device.common.icon;
|
|
2358
|
-
const imgInfo = (imgSrc) ? `<img src=${imgSrc} width='150px' onerror="this.onerror=null;this.src='img/unavailable.png';"><div class="divider"></div
|
|
2379
|
+
const imgInfo = (imgSrc) ? `<img src=${imgSrc} width='150px' onerror="this.onerror=null;this.src='img/unavailable.png';"><div class="divider"></div>` : '';
|
|
2359
2380
|
const info =
|
|
2360
2381
|
`<div class="col s12 m6 l6 xl6">
|
|
2361
2382
|
${imgInfo}
|
|
@@ -2387,29 +2408,28 @@ function genDevInfo(device) {
|
|
|
2387
2408
|
return info;
|
|
2388
2409
|
}
|
|
2389
2410
|
|
|
2390
|
-
function showDevInfo(id){
|
|
2411
|
+
function showDevInfo(id) {
|
|
2391
2412
|
const info = genDevInfo(getDeviceByID(id));
|
|
2392
2413
|
$('#devinfo').html(info);
|
|
2393
2414
|
$('#modaldevinfo').modal('open');
|
|
2394
2415
|
}
|
|
2395
2416
|
|
|
2396
|
-
function showGroupList(show){
|
|
2417
|
+
function showGroupList(show) {
|
|
2397
2418
|
const htmlsections = [];
|
|
2398
2419
|
for (const groupid in devGroups) {
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
htmlsections.push(`
|
|
2420
|
+
const dev = devGroups[groupid];
|
|
2421
|
+
const grpname = (dev.common && dev.common.name ? dev.common.name : 'Group ' + groupid);
|
|
2422
|
+
const selectables = [];
|
|
2423
|
+
const members = [];
|
|
2424
|
+
if (dev && dev.memberinfo) {
|
|
2425
|
+
selectables.push(`<select id="members_${groupid}" multiple>`);
|
|
2426
|
+
for (let m = 0; m < dev.memberinfo.length; m++) {
|
|
2427
|
+
members.push(`${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (${dev.memberinfo[m].ieee})`);
|
|
2428
|
+
selectables.push(`<option value="${m}">${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (...${dev.memberinfo[m].ieee.slice(-4)})</option>`);
|
|
2429
|
+
}
|
|
2430
|
+
selectables.push('</select>');
|
|
2431
|
+
}
|
|
2432
|
+
htmlsections.push(`
|
|
2413
2433
|
<div class="row">
|
|
2414
2434
|
<div class="col s4 m4 l4">
|
|
2415
2435
|
<h5>${grpname}<h5>
|
|
@@ -2422,38 +2442,38 @@ function showGroupList(show){
|
|
|
2422
2442
|
}
|
|
2423
2443
|
|
|
2424
2444
|
$('#grouplist').html(htmlsections.join(''));
|
|
2425
|
-
$('#add').click(function() {
|
|
2426
|
-
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
|
|
2427
|
-
editGroupName(maxind+1, 'Group ' + maxind+1, true);
|
|
2445
|
+
$('#add').click(function () {
|
|
2446
|
+
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
2447
|
+
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
2428
2448
|
showGroupList(false);
|
|
2429
2449
|
});
|
|
2430
2450
|
|
|
2431
|
-
$(
|
|
2432
|
-
$(
|
|
2451
|
+
$('#modalgrouplist a.btn[name=\'save\']').unbind('click');
|
|
2452
|
+
$('#modalgrouplist a.btn[name=\'save\']').click(() => {
|
|
2433
2453
|
});
|
|
2434
2454
|
if (show) $('#modalgrouplist').modal('open');
|
|
2435
2455
|
}
|
|
2436
2456
|
|
|
2437
2457
|
let waitingTimeout, waitingInt;
|
|
2438
2458
|
|
|
2439
|
-
function showWaitingDialog(text, timeout){
|
|
2459
|
+
function showWaitingDialog(text, timeout) {
|
|
2440
2460
|
let countDown = timeout;
|
|
2441
|
-
waitingInt = setInterval(function() {
|
|
2461
|
+
waitingInt = setInterval(function () {
|
|
2442
2462
|
countDown -= 1;
|
|
2443
|
-
const percent = 100-100*countDown/timeout;
|
|
2463
|
+
const percent = 100 - 100 * countDown / timeout;
|
|
2444
2464
|
$('#waiting_progress_line').css('width', `${percent}%`);
|
|
2445
2465
|
}, 1000);
|
|
2446
|
-
waitingTimeout = setTimeout(function() {
|
|
2466
|
+
waitingTimeout = setTimeout(function () {
|
|
2447
2467
|
$('#waiting_progress_line').css('width', `0%`);
|
|
2448
2468
|
clearTimeout(waitingInt);
|
|
2449
2469
|
clearTimeout(waitingTimeout);
|
|
2450
2470
|
$('#modalWaiting').modal('close');
|
|
2451
|
-
}, timeout*1000);
|
|
2471
|
+
}, timeout * 1000);
|
|
2452
2472
|
$('#waiting_message').text(text);
|
|
2453
2473
|
$('#modalWaiting').modal('open');
|
|
2454
2474
|
}
|
|
2455
2475
|
|
|
2456
|
-
function closeWaitingDialog(){
|
|
2476
|
+
function closeWaitingDialog() {
|
|
2457
2477
|
if (waitingInt) clearTimeout(waitingInt);
|
|
2458
2478
|
if (waitingTimeout) clearTimeout(waitingTimeout);
|
|
2459
2479
|
$('#modalWaiting').modal('close');
|
|
@@ -2470,7 +2490,7 @@ function showChannels() {
|
|
|
2470
2490
|
$('#modalchannels').modal('open');
|
|
2471
2491
|
let info = '';
|
|
2472
2492
|
for (let ch = 11; ch < 27; ch++) {
|
|
2473
|
-
const value = msg.energyvalues[ch-11];
|
|
2493
|
+
const value = msg.energyvalues[ch - 11];
|
|
2474
2494
|
info +=
|
|
2475
2495
|
`<div style="padding-top: 10px">
|
|
2476
2496
|
<span class="">№ ${ch}: ${value}%</span>
|
|
@@ -2528,7 +2548,7 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
2528
2548
|
|
|
2529
2549
|
list2select('#exclude_target', onlyOneTargets, exclude_target,
|
|
2530
2550
|
|
|
2531
|
-
function(key, device) {
|
|
2551
|
+
function (key, device) {
|
|
2532
2552
|
if (device == '') {
|
|
2533
2553
|
return 'Select model';
|
|
2534
2554
|
}
|
|
@@ -2541,14 +2561,14 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
2541
2561
|
return device.common.type;
|
|
2542
2562
|
}
|
|
2543
2563
|
},
|
|
2544
|
-
function(key, device) {
|
|
2564
|
+
function (key, device) {
|
|
2545
2565
|
if (device == '') {
|
|
2546
2566
|
return '';
|
|
2547
2567
|
} else {
|
|
2548
2568
|
return device._id;
|
|
2549
2569
|
}
|
|
2550
2570
|
},
|
|
2551
|
-
function(key, device) {
|
|
2571
|
+
function (key, device) {
|
|
2552
2572
|
if (device == '') {
|
|
2553
2573
|
return 'disabled';
|
|
2554
2574
|
} else if (device.icon) {
|
|
@@ -2562,8 +2582,8 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
2562
2582
|
}
|
|
2563
2583
|
|
|
2564
2584
|
function addExcludeDialog() {
|
|
2565
|
-
$(
|
|
2566
|
-
$(
|
|
2585
|
+
$('#excludemodaledit a.btn[name=\'save\']').unbind('click');
|
|
2586
|
+
$('#excludemodaledit a.btn[name=\'save\']').click(() => {
|
|
2567
2587
|
const exclude_id = $('#excludemodaledit').find('#exclude_target option:selected').val();
|
|
2568
2588
|
|
|
2569
2589
|
const ids = devices.map(el => el._id);
|
|
@@ -2646,7 +2666,7 @@ function showExclude() {
|
|
|
2646
2666
|
element.append(card);
|
|
2647
2667
|
});
|
|
2648
2668
|
|
|
2649
|
-
$(
|
|
2669
|
+
$('#exclude button[name=\'delete\']').click(function () {
|
|
2650
2670
|
const exclude_id = $(this).parents('.exclude')[0].id;
|
|
2651
2671
|
deleteExcludeConfirmation(exclude_id);
|
|
2652
2672
|
deleteExclude(exclude_id);
|
|
@@ -2654,14 +2674,13 @@ function showExclude() {
|
|
|
2654
2674
|
}
|
|
2655
2675
|
|
|
2656
2676
|
|
|
2657
|
-
|
|
2658
2677
|
function deleteExcludeConfirmation(id) {
|
|
2659
2678
|
const text = translateWord('Do you really want to delete exclude?');
|
|
2660
2679
|
$('#modaldelete').find('p').text(text);
|
|
2661
2680
|
//$('#forcediv').removeClass('hide');
|
|
2662
2681
|
$('#forcediv').addClass('hide');
|
|
2663
|
-
$(
|
|
2664
|
-
$(
|
|
2682
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
2683
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
2665
2684
|
deleteExclude(id);
|
|
2666
2685
|
});
|
|
2667
2686
|
$('#modaldelete').modal('open');
|
|
@@ -2702,7 +2721,7 @@ function doFilter(inputText) {
|
|
|
2702
2721
|
} else {
|
|
2703
2722
|
return room;
|
|
2704
2723
|
}
|
|
2705
|
-
}).filter((item)=>item != undefined).map((item)=>item.toLowerCase().trim());
|
|
2724
|
+
}).filter((item) => item != undefined).map((item) => item.toLowerCase().trim());
|
|
2706
2725
|
valid = rooms.includes(roomFilter);
|
|
2707
2726
|
} else {
|
|
2708
2727
|
valid = false;
|
|
@@ -2719,9 +2738,9 @@ function doFilter(inputText) {
|
|
|
2719
2738
|
function doSort() {
|
|
2720
2739
|
if (shuffleInstance) {
|
|
2721
2740
|
const sortOrder = $('#device-order-btn').text().toLowerCase();
|
|
2722
|
-
if (sortOrder
|
|
2741
|
+
if (sortOrder === 'default') {
|
|
2723
2742
|
shuffleInstance.sort({});
|
|
2724
|
-
} else if (sortOrder
|
|
2743
|
+
} else if (sortOrder === 'a-z') {
|
|
2725
2744
|
shuffleInstance.sort({
|
|
2726
2745
|
by: sortByTitle
|
|
2727
2746
|
});
|
|
@@ -2735,12 +2754,12 @@ function sortByTitle(element) {
|
|
|
2735
2754
|
|
|
2736
2755
|
function getDashCard(dev, groupImage) {
|
|
2737
2756
|
const title = dev.common.name,
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2757
|
+
id = dev._id,
|
|
2758
|
+
type = dev.common.type,
|
|
2759
|
+
img_src = (groupImage ? groupImage : dev.icon || dev.common.icon),
|
|
2760
|
+
isActive = !dev.common.deactivated,
|
|
2761
|
+
rooms = [],
|
|
2762
|
+
lang = systemLang || 'en';
|
|
2744
2763
|
const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
|
|
2745
2764
|
const rid = id.split('.').join('_');
|
|
2746
2765
|
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
|
|
@@ -2749,38 +2768,46 @@ function getDashCard(dev, groupImage) {
|
|
|
2749
2768
|
battery_cls = getBatteryCls(dev.battery),
|
|
2750
2769
|
lqi_cls = getLQICls(dev.link_quality),
|
|
2751
2770
|
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>` : '',
|
|
2752
|
-
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 ? '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>':''),
|
|
2753
|
-
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>`),
|
|
2754
|
-
permitJoinBtn = (isActive && dev.info && dev.info.device._type
|
|
2771
|
+
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 ? '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>' : ''),
|
|
2772
|
+
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>`),
|
|
2773
|
+
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>' : '',
|
|
2755
2774
|
infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '',
|
|
2756
2775
|
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>` : '';
|
|
2757
|
-
const info = (dev.statesDef) ? dev.statesDef.map((stateDef)=>{
|
|
2776
|
+
const info = (dev.statesDef) ? dev.statesDef.map((stateDef) => {
|
|
2758
2777
|
const id = stateDef.id;
|
|
2759
2778
|
const sid = id.split('.').join('_');
|
|
2760
2779
|
let val = stateDef.val || '';
|
|
2761
|
-
if (stateDef.role
|
|
2762
|
-
val = `<span class="switch"><label><input type="checkbox" ${(val) ?
|
|
2763
|
-
} else if (stateDef.role
|
|
2764
|
-
val = `<span class="range-field dash"><input type="range" min="0" max="100" ${(val != undefined) ? `value="${val}"` :
|
|
2765
|
-
} else if (stateDef.role
|
|
2766
|
-
val = `<span class="range-field dash"><input type="range" min="150" max="500" ${(val != undefined) ? `value="${val}"` :
|
|
2767
|
-
} else if (stateDef.type
|
|
2780
|
+
if (stateDef.role === 'switch' && stateDef.write) {
|
|
2781
|
+
val = `<span class="switch"><label><input type="checkbox" ${(val) ? 'checked' : ''}><span class="lever"></span></label></span>`;
|
|
2782
|
+
} else if (stateDef.role === 'level.dimmer' && stateDef.write) {
|
|
2783
|
+
val = `<span class="range-field dash"><input type="range" min="0" max="100" ${(val != undefined) ? `value="${val}"` : ''} /></span>`;
|
|
2784
|
+
} else if (stateDef.role === 'level.color.temperature' && stateDef.write) {
|
|
2785
|
+
val = `<span class="range-field dash"><input type="range" min="150" max="500" ${(val != undefined) ? `value="${val}"` : ''} /></span>`;
|
|
2786
|
+
} else if (stateDef.type === 'boolean') {
|
|
2768
2787
|
const disabled = (stateDef.write) ? '' : 'disabled="disabled"';
|
|
2769
|
-
val = `<label class="dash"><input type="checkbox" ${(val == true) ?
|
|
2788
|
+
val = `<label class="dash"><input type="checkbox" ${(val == true) ? 'checked=\'checked\'' : ''} ${disabled}/><span></span></label>`;
|
|
2770
2789
|
} else if (stateDef.states && stateDef.write) {
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
const
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2790
|
+
let options;
|
|
2791
|
+
if (typeof stateDef.states == 'string') {
|
|
2792
|
+
const sts = stateDef.states.split(';');
|
|
2793
|
+
options = sts.map((item) => {
|
|
2794
|
+
const v = item.split(':');
|
|
2795
|
+
return `<option value="${v[0]}" ${(val == v[0]) ? 'selected' : ''}>${v[1]}</option>`;
|
|
2796
|
+
});
|
|
2797
|
+
} else {
|
|
2798
|
+
options = [];
|
|
2799
|
+
for (const [key, value] of Object.entries(stateDef.states)) {
|
|
2800
|
+
options.push(`<option value="${key}" ${(val == key) ? 'selected' : ''}>${value}</option>`);
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
val = `<select class="browser-default enum" style="height: 16px; padding: 0; width: auto; display: inline-block">${options.join('')}</select>`;
|
|
2777
2804
|
} else {
|
|
2778
2805
|
val = `<span class="dash value">${val} ${(stateDef.unit) ? stateDef.unit : ''}</span>`;
|
|
2779
2806
|
}
|
|
2780
2807
|
return `<li><span class="label dash truncate">${stateDef.name}</span><span id=${sid} oid=${id} class="state">${val}</span></li>`;
|
|
2781
2808
|
}).join('') : '';
|
|
2782
2809
|
const dashCard = `
|
|
2783
|
-
<div class="card-content zcard ${isActive?'':'bg_red'}">
|
|
2810
|
+
<div class="card-content zcard ${isActive ? '' : 'bg_red'}">
|
|
2784
2811
|
<div class="flip" style="cursor: pointer">
|
|
2785
2812
|
<span class="top right small" style="border-radius: 50%">
|
|
2786
2813
|
${idleTime}
|
|
@@ -2793,7 +2820,7 @@ function getDashCard(dev, groupImage) {
|
|
|
2793
2820
|
<i class="left">${image}</i>
|
|
2794
2821
|
<div style="min-height:88px; font-size: 0.8em; height: 130px; overflow-y: auto" class="truncate">
|
|
2795
2822
|
<ul>
|
|
2796
|
-
${(isActive?info:'Device deactivated')}
|
|
2823
|
+
${(isActive ? info : 'Device deactivated')}
|
|
2797
2824
|
</ul>
|
|
2798
2825
|
</div>
|
|
2799
2826
|
<div class="footer right-align"></div>
|
|
@@ -2806,19 +2833,19 @@ function setDashStates(id, state) {
|
|
|
2806
2833
|
const devId = getDevId(id);
|
|
2807
2834
|
const dev = getDeviceByID(devId);
|
|
2808
2835
|
if (dev) {
|
|
2809
|
-
const stateDef = dev.statesDef.find((stateDef)=> stateDef.id == id);
|
|
2836
|
+
const stateDef = dev.statesDef.find((stateDef) => stateDef.id == id);
|
|
2810
2837
|
if (stateDef) {
|
|
2811
2838
|
const sid = id.split('.').join('_');
|
|
2812
|
-
if (stateDef.role
|
|
2813
|
-
$(`#${sid}`).find(
|
|
2814
|
-
} else if (stateDef.role
|
|
2815
|
-
$(`#${sid}`).find(
|
|
2816
|
-
} else if (stateDef.role
|
|
2817
|
-
$(`#${sid}`).find(
|
|
2839
|
+
if (stateDef.role === 'switch' && stateDef.write) {
|
|
2840
|
+
$(`#${sid}`).find('input[type=\'checkbox\']').prop('checked', state.val);
|
|
2841
|
+
} else if (stateDef.role === 'level.dimmer' && stateDef.write) {
|
|
2842
|
+
$(`#${sid}`).find('input[type=\'range\']').prop('value', state.val);
|
|
2843
|
+
} else if (stateDef.role === 'level.color.temperature' && stateDef.write) {
|
|
2844
|
+
$(`#${sid}`).find('input[type=\'range\']').prop('value', state.val);
|
|
2818
2845
|
} else if (stateDef.states && stateDef.write) {
|
|
2819
2846
|
$(`#${sid}`).find(`select option[value=${state.val}]`).prop('selected', true);
|
|
2820
|
-
} else if (stateDef.type
|
|
2821
|
-
$(`#${sid}`).find(
|
|
2847
|
+
} else if (stateDef.type === 'boolean') {
|
|
2848
|
+
$(`#${sid}`).find('input[type=\'checkbox\']').prop('checked', state.val);
|
|
2822
2849
|
} else {
|
|
2823
2850
|
$(`#${sid}`).find('.value').text(`${state.val} ${(stateDef.unit) ? stateDef.unit : ''}`);
|
|
2824
2851
|
}
|
|
@@ -2827,23 +2854,23 @@ function setDashStates(id, state) {
|
|
|
2827
2854
|
}
|
|
2828
2855
|
|
|
2829
2856
|
function hookControls() {
|
|
2830
|
-
$(
|
|
2857
|
+
$('input[type=\'checkbox\']').change(function (event) {
|
|
2831
2858
|
const val = $(this).is(':checked');
|
|
2832
|
-
const id = $(this).parents(
|
|
2859
|
+
const id = $(this).parents('.state').attr('oid');
|
|
2833
2860
|
sendTo(namespace, 'setState', {id: id, val: val}, function (data) {
|
|
2834
2861
|
//console.log(data);
|
|
2835
2862
|
});
|
|
2836
2863
|
});
|
|
2837
|
-
$(
|
|
2864
|
+
$('input[type=\'range\']').change(function (event) {
|
|
2838
2865
|
const val = $(this).val();
|
|
2839
|
-
const id = $(this).parents(
|
|
2866
|
+
const id = $(this).parents('.state').attr('oid');
|
|
2840
2867
|
sendTo(namespace, 'setState', {id: id, val: val}, function (data) {
|
|
2841
2868
|
//console.log(data);
|
|
2842
2869
|
});
|
|
2843
2870
|
});
|
|
2844
|
-
$(
|
|
2871
|
+
$('.state select').on('change', function () {
|
|
2845
2872
|
const val = $(this).val();
|
|
2846
|
-
const id = $(this).parents(
|
|
2873
|
+
const id = $(this).parents('.state').attr('oid');
|
|
2847
2874
|
sendTo(namespace, 'setState', {id: id, val: val}, function (data) {
|
|
2848
2875
|
//console.log(data);
|
|
2849
2876
|
});
|
|
@@ -2851,12 +2878,12 @@ function hookControls() {
|
|
|
2851
2878
|
}
|
|
2852
2879
|
|
|
2853
2880
|
function getIdleTime(value) {
|
|
2854
|
-
return (value) ? moment(new Date(value)).fromNow(true) :
|
|
2881
|
+
return (value) ? moment(new Date(value)).fromNow(true) : '';
|
|
2855
2882
|
}
|
|
2856
2883
|
|
|
2857
2884
|
function updateCardTimer() {
|
|
2858
2885
|
if (devices) {
|
|
2859
|
-
devices.forEach((dev)=>{
|
|
2886
|
+
devices.forEach((dev) => {
|
|
2860
2887
|
const id = dev._id;
|
|
2861
2888
|
if (id) {
|
|
2862
2889
|
const rid = id.split('.').join('_');
|
|
@@ -2873,9 +2900,7 @@ function updateDevice(id) {
|
|
|
2873
2900
|
showMessage(devs.error, _('Error'));
|
|
2874
2901
|
} else {
|
|
2875
2902
|
removeDevice(id);
|
|
2876
|
-
devs.forEach((dev)
|
|
2877
|
-
devices.push(dev);
|
|
2878
|
-
})
|
|
2903
|
+
devs.forEach(dev => devices.push(dev));
|
|
2879
2904
|
showDevices();
|
|
2880
2905
|
}
|
|
2881
2906
|
}
|
|
@@ -2893,21 +2918,21 @@ function removeDevice(id) {
|
|
|
2893
2918
|
}
|
|
2894
2919
|
|
|
2895
2920
|
function swapActive(id) {
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2921
|
+
const dev = getDeviceByID(id);
|
|
2922
|
+
if (dev && dev.common) {
|
|
2923
|
+
dev.common.deactivated = !(dev.common.deactivated);
|
|
2924
|
+
sendTo(namespace, 'setDeviceActivated', {id: id, deactivated: dev.common.deactivated}, function () {
|
|
2925
|
+
showDevices();
|
|
2926
|
+
});
|
|
2927
|
+
}
|
|
2903
2928
|
}
|
|
2904
2929
|
|
|
2905
2930
|
function reconfigureDlg(id) {
|
|
2906
2931
|
const text = translateWord(`Do you really want to reconfigure device?`);
|
|
2907
2932
|
$('#modalreconfigure').find('p').text(text);
|
|
2908
|
-
$(
|
|
2909
|
-
$(
|
|
2910
|
-
reconfigureDevice(id
|
|
2933
|
+
$('#modalreconfigure a.btn[name=\'yes\']').unbind('click');
|
|
2934
|
+
$('#modalreconfigure a.btn[name=\'yes\']').click(() => {
|
|
2935
|
+
reconfigureDevice(id/*, force*/);
|
|
2911
2936
|
});
|
|
2912
2937
|
$('#modalreconfigure').modal('open');
|
|
2913
2938
|
Materialize.updateTextFields();
|