iobroker.zigbee 1.8.3 → 1.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/admin/adapter-settings.js +244 -0
- package/admin/admin.js +520 -494
- package/admin/index_m.html +1171 -1001
- package/admin/tab_m.html +44 -2
- package/docs/de/img/CC2531.png +0 -0
- package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
- package/docs/de/img/CC2591.png +0 -0
- package/docs/de/img/boards.jpg +0 -0
- package/docs/de/img/cc26x2r.PNG +0 -0
- package/docs/de/img/results.jpg +0 -0
- package/docs/de/img/sku_429478_2.png +0 -0
- package/docs/de/img/sku_429601_2.png +0 -0
- package/docs/de/readme.md +27 -0
- package/docs/en/img/CC2531.png +0 -0
- package/docs/en/img/CC2591.png +0 -0
- package/docs/en/img/deconz.png +0 -0
- package/docs/en/img/sku_429478_2.png +0 -0
- package/docs/en/img/sku_429601_2.png +0 -0
- package/docs/en/readme.md +30 -0
- package/docs/flashing_via_arduino_(en).md +110 -0
- package/docs/ru/img/CC2531.png +0 -0
- package/docs/ru/img/CC2591.png +0 -0
- package/docs/ru/img/sku_429478_2.png +0 -0
- package/docs/ru/img/sku_429601_2.png +0 -0
- package/docs/ru/readme.md +28 -0
- package/docs/tutorial/CC2530_20190425.zip +0 -0
- package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
- package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
- package/docs/tutorial/CC2531_20190425.zip +0 -0
- package/docs/tutorial/adm5_1.PNG +0 -0
- package/docs/tutorial/adm5_2.PNG +0 -0
- package/docs/tutorial/cat.PNG +0 -0
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/inst.PNG +0 -0
- package/docs/tutorial/reflash-finish.PNG +0 -0
- package/docs/tutorial/reflash-step0.png +0 -0
- package/docs/tutorial/reflash-step1.PNG +0 -0
- package/docs/tutorial/reflash-step2.PNG +0 -0
- package/docs/tutorial/settings.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/docs/tutorial/zigbee.png +0 -0
- package/docs/tutorial/zigbee15.png +0 -0
- package/io-package.json +34 -33
- package/lib/backup.js +2 -2
- package/lib/binding.js +32 -37
- package/lib/colors.js +163 -158
- package/lib/commands.js +100 -91
- package/lib/developer.js +9 -12
- package/lib/devices.js +168 -178
- package/lib/exclude.js +30 -36
- package/lib/exposes.js +168 -143
- package/lib/groups.js +81 -83
- package/lib/json.js +5 -6
- package/lib/networkmap.js +2 -3
- package/lib/ota.js +34 -18
- package/lib/rgb.js +114 -72
- package/lib/seriallist.js +25 -20
- package/lib/statescontroller.js +206 -183
- package/lib/utils.js +29 -23
- package/lib/zbBaseExtension.js +4 -4
- package/lib/zbDelayedAction.js +5 -13
- package/lib/zbDeviceAvailability.js +69 -65
- package/lib/zbDeviceConfigure.js +9 -21
- package/lib/zbDeviceEvent.js +3 -4
- package/lib/zigbeecontroller.js +133 -128
- package/main.js +169 -154
- package/package.json +28 -14
- package/.eslintignore +0 -2
- package/.eslintrc.json +0 -37
- package/.github/FUNDING.yml +0 -3
- package/.github/auto-merge.yml +0 -17
- package/.github/dependabot.yml +0 -24
- package/.github/stale.yml +0 -13
- package/.github/workflows/codeql.yml +0 -41
- package/.github/workflows/dependabot-automerge.yml +0 -22
- package/.github/workflows/test-and-release.yml +0 -149
- package/.releaseconfig.json +0 -3
- package/.travis/wiki.sh +0 -28
- package/.travis.yml +0 -41
- package/gulpfile.js +0 -464
- package/test/integration.js +0 -5
- package/test/mocha.custom.opts +0 -2
- package/test/mocha.setup.js +0 -14
- package/test/package.js +0 -5
- package/test/unit.js +0 -5
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,70 @@ 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
|
-
$(
|
|
601
|
-
const dev_block = $(this).parents('div.device')
|
|
602
|
-
|
|
603
|
-
|
|
599
|
+
$('.card-reveal-buttons button[name=\'edit\']').click(function () {
|
|
600
|
+
const dev_block = $(this).parents('div.device');
|
|
601
|
+
const id = getDevId(dev_block);
|
|
602
|
+
const name = getDevName(dev_block);
|
|
604
603
|
editName(id, name);
|
|
605
604
|
});
|
|
606
|
-
$(
|
|
607
|
-
const dev_block = $(this).parents('div.device')
|
|
608
|
-
|
|
609
|
-
|
|
605
|
+
$('.card-reveal-buttons button[name=\'editgrp\']').click(function () {
|
|
606
|
+
const dev_block = $(this).parents('div.device');
|
|
607
|
+
const id = dev_block.attr('id').replace(namespace + '.group_', '');
|
|
608
|
+
const 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
|
-
if (!$('#pairing').hasClass('pulse'))
|
|
613
|
+
if (!$('#pairing').hasClass('pulse')) {
|
|
615
614
|
joinProcess(getDevId(dev_block));
|
|
615
|
+
}
|
|
616
616
|
showPairingProcess();
|
|
617
617
|
});
|
|
618
|
-
$(
|
|
618
|
+
$('.card-reveal-buttons button[name=\'info\']').click(function () {
|
|
619
619
|
const dev_block = $(this).parents('div.device');
|
|
620
620
|
showDevInfo(getDevId(dev_block));
|
|
621
621
|
});
|
|
622
|
-
$(
|
|
622
|
+
$('a.btn[name=\'done\']').click((e) => {
|
|
623
623
|
const dev_block = $(this).parents('div.device');
|
|
624
624
|
closeReval(e, getDevId(dev_block), getDevName(dev_block));
|
|
625
625
|
});
|
|
626
|
-
$(
|
|
626
|
+
$('a.btn-flat[name=\'close\']').click((e) => {
|
|
627
627
|
closeReval(e);
|
|
628
628
|
});
|
|
629
|
-
$(
|
|
629
|
+
$('.card-reveal-buttons button[name=\'reconfigure\']').click(function () {
|
|
630
630
|
const dev_block = $(this).parents('div.device');
|
|
631
631
|
reconfigureDlg(getDevId(dev_block));
|
|
632
632
|
});
|
|
633
|
-
$(
|
|
633
|
+
$('.card-reveal-buttons button[name=\'swapactive\']').click(function () {
|
|
634
634
|
const dev_block = $(this).parents('div.device');
|
|
635
635
|
swapActive(getDevId(dev_block));
|
|
636
636
|
});
|
|
@@ -641,10 +641,10 @@ function showDevices() {
|
|
|
641
641
|
|
|
642
642
|
function checkFwUpdate() {
|
|
643
643
|
const deviceCards = getDeviceCards();
|
|
644
|
-
const getFwInfoNode = function(deviceCard) {
|
|
644
|
+
const getFwInfoNode = function (deviceCard) {
|
|
645
645
|
return deviceCard.find('.fw_info');
|
|
646
646
|
};
|
|
647
|
-
const createBtn = function(icon, hint, disabled, color) {
|
|
647
|
+
const createBtn = function (icon, hint, disabled, color) {
|
|
648
648
|
const disabledAttr = disabled ? '[disabled]="true"' : '';
|
|
649
649
|
if (!color) {
|
|
650
650
|
color = !disabled ? 'icon-green' : '';
|
|
@@ -652,14 +652,14 @@ function checkFwUpdate() {
|
|
|
652
652
|
return `<button name="fw_update" class="left btn-flat btn-small" title="${hint}" ${disabledAttr}>
|
|
653
653
|
<i class="material-icons ${color}">${icon}</i></button>`;
|
|
654
654
|
};
|
|
655
|
-
const callback = function(msg) {
|
|
655
|
+
const callback = function (msg) {
|
|
656
656
|
if (msg) {
|
|
657
657
|
const deviceCard = getDeviceCard(msg.device);
|
|
658
658
|
const devId = getDevId(deviceCard.attr('id'));
|
|
659
659
|
const fwInfoNode = getFwInfoNode(deviceCard);
|
|
660
660
|
if (msg.status == 'available') {
|
|
661
661
|
fwInfoNode.html(createBtn('system_update', 'Click to start firmware update', false));
|
|
662
|
-
$(fwInfoNode).find(
|
|
662
|
+
$(fwInfoNode).find('button[name=\'fw_update\']').click(() => {
|
|
663
663
|
fwInfoNode.html(createBtn('check_circle', 'Firmware update started, check progress in logs.', true, 'icon-blue'));
|
|
664
664
|
sendTo(namespace, 'startOta', {devId: devId}, (msg) => {
|
|
665
665
|
fwInfoNode.html(createBtn('check_circle', 'Finished, see logs.', true));
|
|
@@ -669,13 +669,13 @@ function checkFwUpdate() {
|
|
|
669
669
|
} else if (msg.status == 'not_available') {
|
|
670
670
|
fwInfoNode.html(createBtn('check_circle', 'Up-to-date', true));
|
|
671
671
|
} else if (msg.status == 'fail') {
|
|
672
|
-
fwInfoNode.html(createBtn('check_circle', 'Firmware check failed, '+msg.msg, true, 'icon-red'));
|
|
672
|
+
fwInfoNode.html(createBtn('check_circle', 'Firmware check failed, ' + msg.msg, true, 'icon-red'));
|
|
673
673
|
} else {
|
|
674
674
|
fwInfoNode.html(createBtn('not_interested', 'No firmware update available', true));
|
|
675
675
|
}
|
|
676
676
|
}
|
|
677
677
|
};
|
|
678
|
-
for (let i=0;i < deviceCards.length; i++) {
|
|
678
|
+
for (let i = 0; i < deviceCards.length; i++) {
|
|
679
679
|
const deviceCard = $(deviceCards[i]);
|
|
680
680
|
const devId = getDevId(deviceCard.attr('id'));
|
|
681
681
|
getFwInfoNode(deviceCard).html('<span class="left" style="padding-top:8px">checking...</span>');
|
|
@@ -686,10 +686,8 @@ function checkFwUpdate() {
|
|
|
686
686
|
function letsPairing() {
|
|
687
687
|
messages = [];
|
|
688
688
|
sendTo(namespace, 'letsPairing', {}, function (msg) {
|
|
689
|
-
if (msg) {
|
|
690
|
-
|
|
691
|
-
showMessage(msg.error, _('Error'));
|
|
692
|
-
}
|
|
689
|
+
if (msg && msg.error) {
|
|
690
|
+
showMessage(msg.error, _('Error'));
|
|
693
691
|
}
|
|
694
692
|
});
|
|
695
693
|
}
|
|
@@ -697,10 +695,8 @@ function letsPairing() {
|
|
|
697
695
|
function touchlinkReset() {
|
|
698
696
|
messages = [];
|
|
699
697
|
sendTo(namespace, 'touchlinkReset', {}, function (msg) {
|
|
700
|
-
if (msg) {
|
|
701
|
-
|
|
702
|
-
showMessage(msg.error, _('Error'));
|
|
703
|
-
}
|
|
698
|
+
if (msg && msg.error) {
|
|
699
|
+
showMessage(msg.error, _('Error'));
|
|
704
700
|
}
|
|
705
701
|
});
|
|
706
702
|
}
|
|
@@ -708,10 +704,8 @@ function touchlinkReset() {
|
|
|
708
704
|
function joinProcess(devId) {
|
|
709
705
|
messages = [];
|
|
710
706
|
sendTo(namespace, 'letsPairing', {id: devId}, function (msg) {
|
|
711
|
-
if (msg) {
|
|
712
|
-
|
|
713
|
-
showMessage(msg.error, _('Error'));
|
|
714
|
-
}
|
|
707
|
+
if (msg && msg.error) {
|
|
708
|
+
showMessage(msg.error, _('Error'));
|
|
715
709
|
}
|
|
716
710
|
});
|
|
717
711
|
}
|
|
@@ -728,7 +722,6 @@ function getCoordinatorInfo() {
|
|
|
728
722
|
});
|
|
729
723
|
}
|
|
730
724
|
|
|
731
|
-
|
|
732
725
|
function getDevices() {
|
|
733
726
|
getCoordinatorInfo();
|
|
734
727
|
sendTo(namespace, 'getDevices', {}, function (msg) {
|
|
@@ -746,7 +739,7 @@ function getDevices() {
|
|
|
746
739
|
}
|
|
747
740
|
|
|
748
741
|
function getDeviceCards() {
|
|
749
|
-
return $('#devices .device').not(
|
|
742
|
+
return $('#devices .device').not('.group');
|
|
750
743
|
}
|
|
751
744
|
|
|
752
745
|
function getDeviceCard(devId) {
|
|
@@ -774,17 +767,32 @@ function getMap() {
|
|
|
774
767
|
// the function loadSettings has to exist ...
|
|
775
768
|
// eslint-disable-next-line no-unused-vars
|
|
776
769
|
function load(settings, onChange) {
|
|
777
|
-
if (settings.panID === undefined)
|
|
778
|
-
|
|
770
|
+
if (settings.panID === undefined) {
|
|
771
|
+
settings.panID = 6754;
|
|
772
|
+
}
|
|
773
|
+
if (settings.extPanID === undefined) {
|
|
774
|
+
settings.extPanID = 'DDDDDDDDDDDDDDDD';
|
|
775
|
+
}
|
|
779
776
|
// fix for previous wrong value
|
|
780
|
-
if (settings.extPanID === 'DDDDDDDDDDDDDDD')
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
777
|
+
if (settings.extPanID === 'DDDDDDDDDDDDDDD') {
|
|
778
|
+
settings.extPanID = 'DDDDDDDDDDDDDDDD';
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (settings.precfgkey === undefined) {
|
|
782
|
+
settings.precfgkey = '01030507090B0D0F00020406080A0C0D';
|
|
783
|
+
}
|
|
784
|
+
if (settings.channel === undefined) {
|
|
785
|
+
settings.channel = 11;
|
|
786
|
+
}
|
|
787
|
+
if (settings.disablePing === undefined) {
|
|
788
|
+
settings.disablePing = false;
|
|
789
|
+
}
|
|
790
|
+
|
|
785
791
|
// example: select elements with id=key and class=value and insert value
|
|
786
792
|
for (const key in settings) {
|
|
787
|
-
if (savedSettings.indexOf(key) === -1)
|
|
793
|
+
if (savedSettings.indexOf(key) === -1) {
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
788
796
|
// example: select elements with id=key and class=value and insert value
|
|
789
797
|
const value = $('#' + key + '.value');
|
|
790
798
|
if (value.attr('type') === 'checkbox') {
|
|
@@ -810,35 +818,36 @@ function load(settings, onChange) {
|
|
|
810
818
|
// Signal to admin, that no changes yet
|
|
811
819
|
onChange(false);
|
|
812
820
|
|
|
813
|
-
$('#state_cleanup_btn').click(function() {
|
|
821
|
+
$('#state_cleanup_btn').click(function () {
|
|
814
822
|
cleanConfirmation();
|
|
815
823
|
});
|
|
816
|
-
$('#fw_check_btn').click(function() {
|
|
824
|
+
$('#fw_check_btn').click(function () {
|
|
817
825
|
checkFwUpdate();
|
|
818
826
|
});
|
|
819
|
-
$('#touchlink_btn').click(function() {
|
|
827
|
+
$('#touchlink_btn').click(function () {
|
|
820
828
|
touchlinkReset();
|
|
821
829
|
showPairingProcess();
|
|
822
830
|
});
|
|
823
|
-
$('#pairing').click(function() {
|
|
824
|
-
if (!$('#pairing').hasClass('pulse'))
|
|
831
|
+
$('#pairing').click(function () {
|
|
832
|
+
if (!$('#pairing').hasClass('pulse')) {
|
|
825
833
|
letsPairing();
|
|
834
|
+
}
|
|
826
835
|
showPairingProcess();
|
|
827
836
|
});
|
|
828
837
|
|
|
829
|
-
$('#refresh').click(function() {
|
|
838
|
+
$('#refresh').click(function () {
|
|
830
839
|
getMap();
|
|
831
840
|
});
|
|
832
841
|
|
|
833
|
-
$('#reset-btn').click(function() {
|
|
842
|
+
$('#reset-btn').click(function () {
|
|
834
843
|
resetConfirmation();
|
|
835
844
|
});
|
|
836
845
|
|
|
837
|
-
$('#viewconfig').click(function() {
|
|
846
|
+
$('#viewconfig').click(function () {
|
|
838
847
|
showViewConfig();
|
|
839
848
|
});
|
|
840
849
|
|
|
841
|
-
$('#scan').click(function() {
|
|
850
|
+
$('#scan').click(function () {
|
|
842
851
|
showChannels();
|
|
843
852
|
});
|
|
844
853
|
|
|
@@ -847,18 +856,18 @@ function load(settings, onChange) {
|
|
|
847
856
|
showGroups();
|
|
848
857
|
});
|
|
849
858
|
|
|
850
|
-
$('#add_group').click(function() {
|
|
859
|
+
$('#add_group').click(function () {
|
|
851
860
|
// 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);
|
|
861
|
+
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
862
|
+
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
854
863
|
});
|
|
855
|
-
$('#add_grp_btn').click(function() {
|
|
864
|
+
$('#add_grp_btn').click(function () {
|
|
856
865
|
// 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);
|
|
866
|
+
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
867
|
+
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
859
868
|
});
|
|
860
869
|
|
|
861
|
-
$(document).ready(function() {
|
|
870
|
+
$(document).ready(function () {
|
|
862
871
|
$('.modal').modal({
|
|
863
872
|
startingTop: '30%',
|
|
864
873
|
endingTop: '10%',
|
|
@@ -882,7 +891,7 @@ function load(settings, onChange) {
|
|
|
882
891
|
$('#pairing').attr('data-tooltip', transText);
|
|
883
892
|
}
|
|
884
893
|
|
|
885
|
-
$('ul.tabs').on('click', 'a', function(e) {
|
|
894
|
+
$('ul.tabs').on('click', 'a', function (e) {
|
|
886
895
|
if ($(e.target).attr('id') == 'tabmap') {
|
|
887
896
|
redrawMap();
|
|
888
897
|
}
|
|
@@ -891,11 +900,11 @@ function load(settings, onChange) {
|
|
|
891
900
|
}
|
|
892
901
|
});
|
|
893
902
|
|
|
894
|
-
$('#add_exclude').click(function() {
|
|
903
|
+
$('#add_exclude').click(function () {
|
|
895
904
|
addExcludeDialog();
|
|
896
905
|
});
|
|
897
906
|
|
|
898
|
-
$('#add_binding').click(function() {
|
|
907
|
+
$('#add_binding').click(function () {
|
|
899
908
|
addBindingDialog();
|
|
900
909
|
});
|
|
901
910
|
|
|
@@ -934,7 +943,7 @@ function save(callback) {
|
|
|
934
943
|
const $this = $(this);
|
|
935
944
|
if (savedSettings.indexOf($this.attr('id')) === -1) return;
|
|
936
945
|
if ($this.hasClass('validate') && $this.hasClass('invalid')) {
|
|
937
|
-
showMessage('Invalid input for '
|
|
946
|
+
showMessage('Invalid input for ' + $this.attr('id'), _('Error'));
|
|
938
947
|
return;
|
|
939
948
|
}
|
|
940
949
|
if ($this.attr('type') === 'checkbox') {
|
|
@@ -948,7 +957,7 @@ function save(callback) {
|
|
|
948
957
|
|
|
949
958
|
|
|
950
959
|
function getDevId(adapterDevId) {
|
|
951
|
-
return adapterDevId.split('.').slice(0,3).join('.');
|
|
960
|
+
return adapterDevId.split('.').slice(0, 3).join('.');
|
|
952
961
|
}
|
|
953
962
|
|
|
954
963
|
// subscribe to changes
|
|
@@ -975,7 +984,7 @@ socket.on('stateChange', function (id, state) {
|
|
|
975
984
|
} else {
|
|
976
985
|
$('#pairing').addClass('pulse');
|
|
977
986
|
$('#pairing').html(state.val);
|
|
978
|
-
const percent = 100-100*state.val/($('#countDown').val() || 60);
|
|
987
|
+
const percent = 100 - 100 * state.val / ($('#countDown').val() || 60);
|
|
979
988
|
$('#progress_line').css('width', `${percent}%`);
|
|
980
989
|
}
|
|
981
990
|
} else if (id.match(/\.info\.pairingMessage$/)) {
|
|
@@ -1021,6 +1030,7 @@ socket.on('objectChange', function (id, obj) {
|
|
|
1021
1030
|
}
|
|
1022
1031
|
}
|
|
1023
1032
|
});
|
|
1033
|
+
|
|
1024
1034
|
/*
|
|
1025
1035
|
socket.emit('getObject', 'system.config', function (err, res) {
|
|
1026
1036
|
if (!err && res && res.common) {
|
|
@@ -1033,45 +1043,47 @@ socket.emit('getObject', 'system.config', function (err, res) {
|
|
|
1033
1043
|
function putEventToNode(devId) {
|
|
1034
1044
|
if (network) {
|
|
1035
1045
|
const nodesArray = Object.values(network.body.data.nodes._data);
|
|
1036
|
-
const node = nodesArray.find((node) => {
|
|
1046
|
+
const node = nodesArray.find((node) => {
|
|
1047
|
+
return node.id == devId;
|
|
1048
|
+
});
|
|
1037
1049
|
if (node) {
|
|
1038
1050
|
const exists = networkEvents.find((event) => {
|
|
1039
1051
|
return event.node == node.id;
|
|
1040
1052
|
});
|
|
1041
1053
|
if (!exists) {
|
|
1042
1054
|
networkEvents.push({node: node.id, radius: 0, forward: true});
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1055
|
+
// } else {
|
|
1056
|
+
// exists.radius = 0;
|
|
1057
|
+
// exists.forward = true;
|
|
1046
1058
|
}
|
|
1047
1059
|
}
|
|
1048
1060
|
}
|
|
1049
1061
|
}
|
|
1050
1062
|
|
|
1051
|
-
function showNetworkMap(devices, map){
|
|
1063
|
+
function showNetworkMap(devices, map) {
|
|
1052
1064
|
// create an object with nodes
|
|
1053
1065
|
const nodes = {};
|
|
1054
1066
|
// create an array with edges
|
|
1055
1067
|
const edges = [];
|
|
1056
1068
|
|
|
1057
1069
|
if (map.lqis == undefined || map.lqis.length === 0) { // first init
|
|
1058
|
-
$('#filterParent, #filterSibl, #filterPrvChild, #filterMesh').change(function() {
|
|
1070
|
+
$('#filterParent, #filterSibl, #filterPrvChild, #filterMesh').change(function () {
|
|
1059
1071
|
updateMapFilter();
|
|
1060
1072
|
});
|
|
1061
1073
|
}
|
|
1062
1074
|
|
|
1063
|
-
const createNode = function(dev, mapEntry) {
|
|
1075
|
+
const createNode = function (dev, mapEntry) {
|
|
1064
1076
|
if (dev.common && dev.common.type == 'group') return undefined;
|
|
1065
1077
|
const extInfo = (mapEntry && mapEntry.networkAddress) ? `\n (nwkAddr: 0x${mapEntry.networkAddress.toString(16)} | ${mapEntry.networkAddress})` : '';
|
|
1066
1078
|
const node = {
|
|
1067
1079
|
id: dev._id,
|
|
1068
|
-
label: (dev.link_quality >0 ? dev.common.name
|
|
1069
|
-
title: dev._id.replace(namespace+'.', '') + extInfo,
|
|
1080
|
+
label: (dev.link_quality > 0 ? dev.common.name : `${dev.common.name}\n(disconnected)`),
|
|
1081
|
+
title: dev._id.replace(namespace + '.', '') + extInfo,
|
|
1070
1082
|
shape: 'circularImage',
|
|
1071
1083
|
image: dev.icon,
|
|
1072
1084
|
imagePadding: {top: 5, bottom: 5, left: 5, right: 5},
|
|
1073
1085
|
color: {background: 'white', highlight: {background: 'white'}},
|
|
1074
|
-
font: {color:'#007700'},
|
|
1086
|
+
font: {color: '#007700'},
|
|
1075
1087
|
borderWidth: 1,
|
|
1076
1088
|
borderWidthSelected: 4,
|
|
1077
1089
|
};
|
|
@@ -1085,7 +1097,7 @@ function showNetworkMap(devices, map){
|
|
|
1085
1097
|
};
|
|
1086
1098
|
|
|
1087
1099
|
if (map.lqis) {
|
|
1088
|
-
map.lqis.forEach((mapEntry)=>{
|
|
1100
|
+
map.lqis.forEach((mapEntry) => {
|
|
1089
1101
|
const dev = getDevice(mapEntry.ieeeAddr);
|
|
1090
1102
|
if (!dev) {
|
|
1091
1103
|
//console.log("No dev with ieee "+mapEntry.ieeeAddr);
|
|
@@ -1098,8 +1110,7 @@ function showNetworkMap(devices, map){
|
|
|
1098
1110
|
if (node) {
|
|
1099
1111
|
nodes[mapEntry.ieeeAddr] = node;
|
|
1100
1112
|
}
|
|
1101
|
-
}
|
|
1102
|
-
else {
|
|
1113
|
+
} else {
|
|
1103
1114
|
node = nodes[mapEntry.ieeeAddr];
|
|
1104
1115
|
}
|
|
1105
1116
|
if (node) {
|
|
@@ -1117,7 +1128,7 @@ function showNetworkMap(devices, map){
|
|
|
1117
1128
|
|
|
1118
1129
|
if (mapEntry.relationship === 0 || mapEntry.relationship === 1) { // 0 - parent, 1 - child
|
|
1119
1130
|
// // parent/child
|
|
1120
|
-
if (mapEntry.status !== 'online'
|
|
1131
|
+
if (mapEntry.status !== 'online') {
|
|
1121
1132
|
label = label + ' (off)';
|
|
1122
1133
|
linkColor = '#ff0000';
|
|
1123
1134
|
}
|
|
@@ -1134,8 +1145,8 @@ function showNetworkMap(devices, map){
|
|
|
1134
1145
|
if (reverse) {
|
|
1135
1146
|
// update reverse edge
|
|
1136
1147
|
edge = reverse;
|
|
1137
|
-
edge.label += '\n'+label;
|
|
1138
|
-
edge.arrows.from = {
|
|
1148
|
+
edge.label += '\n' + label;
|
|
1149
|
+
edge.arrows.from = {enabled: false, scaleFactor: 0.5}; // start hidden if node is not selected
|
|
1139
1150
|
if (mapEntry.relationship == 1) { //
|
|
1140
1151
|
edge.color.color = linkColor;
|
|
1141
1152
|
edge.color.highlight = linkColor;
|
|
@@ -1150,7 +1161,7 @@ function showNetworkMap(devices, map){
|
|
|
1150
1161
|
size: 0, // start hidden
|
|
1151
1162
|
color: linkColor
|
|
1152
1163
|
},
|
|
1153
|
-
arrows: {
|
|
1164
|
+
arrows: {to: {enabled: false, scaleFactor: 0.5}},
|
|
1154
1165
|
//arrowStrikethrough: false,
|
|
1155
1166
|
color: {
|
|
1156
1167
|
color: linkColor,
|
|
@@ -1164,7 +1175,7 @@ function showNetworkMap(devices, map){
|
|
|
1164
1175
|
values.fromArrow = values.fromArrowScale != 1 ? true : false; // simplified, arrow existing if scale is not default value
|
|
1165
1176
|
},
|
|
1166
1177
|
label: () => {
|
|
1167
|
-
|
|
1178
|
+
// see onMapSelect workaround
|
|
1168
1179
|
// values.size = 10;
|
|
1169
1180
|
}
|
|
1170
1181
|
},
|
|
@@ -1230,15 +1241,16 @@ function showNetworkMap(devices, map){
|
|
|
1230
1241
|
const nodesArray = Object.values(nodes);
|
|
1231
1242
|
// add devices without network links to map
|
|
1232
1243
|
devices.forEach((dev) => {
|
|
1233
|
-
const node = nodesArray.find((node) => {
|
|
1244
|
+
const node = nodesArray.find((node) => {
|
|
1245
|
+
return node.id == dev._id;
|
|
1246
|
+
});
|
|
1234
1247
|
if (!node) {
|
|
1235
1248
|
const node = createNode(dev);
|
|
1236
1249
|
|
|
1237
|
-
if (node)
|
|
1238
|
-
|
|
1239
|
-
node.font = {color:'#ff0000'};
|
|
1250
|
+
if (node) {
|
|
1251
|
+
node.font = {color: '#ff0000'};
|
|
1240
1252
|
if (dev.info && dev.info.device._type == 'Coordinator') {
|
|
1241
|
-
node.font = {color:'#000000'};
|
|
1253
|
+
node.font = {color: '#000000'};
|
|
1242
1254
|
}
|
|
1243
1255
|
nodesArray.push(node);
|
|
1244
1256
|
}
|
|
@@ -1260,7 +1272,7 @@ function showNetworkMap(devices, map){
|
|
|
1260
1272
|
shape: 'box'
|
|
1261
1273
|
},
|
|
1262
1274
|
layout: {
|
|
1263
|
-
improvedLayout:true,
|
|
1275
|
+
improvedLayout: true,
|
|
1264
1276
|
}
|
|
1265
1277
|
};
|
|
1266
1278
|
|
|
@@ -1310,25 +1322,26 @@ function showNetworkMap(devices, map){
|
|
|
1310
1322
|
if (networkEvents.length > 0) {
|
|
1311
1323
|
network.redraw();
|
|
1312
1324
|
const toDelete = [];
|
|
1313
|
-
networkEvents.forEach((event, index)=>{
|
|
1325
|
+
networkEvents.forEach((event, index) => {
|
|
1314
1326
|
if (event.radius >= 1) {
|
|
1315
1327
|
toDelete.push(index);
|
|
1316
1328
|
} else {
|
|
1317
1329
|
event.radius += 0.08;
|
|
1318
1330
|
}
|
|
1319
1331
|
});
|
|
1320
|
-
toDelete.forEach((index)=>{
|
|
1332
|
+
toDelete.forEach((index) => {
|
|
1321
1333
|
networkEvents.splice(index, 1);
|
|
1322
1334
|
});
|
|
1323
1335
|
}
|
|
1324
1336
|
}
|
|
1325
|
-
|
|
1337
|
+
|
|
1338
|
+
network.on('beforeDrawing', function (ctx) {
|
|
1326
1339
|
if (networkEvents.length > 0) {
|
|
1327
|
-
networkEvents.forEach((event)=>{
|
|
1340
|
+
networkEvents.forEach((event) => {
|
|
1328
1341
|
const inode = event.node;
|
|
1329
1342
|
const nodePosition = network.getPositions();
|
|
1330
1343
|
event.radius = (event.radius > 1) ? 1 : event.radius;
|
|
1331
|
-
const cap = Math.cos(event.radius*Math.PI/2);
|
|
1344
|
+
const cap = Math.cos(event.radius * Math.PI / 2);
|
|
1332
1345
|
const colorCircle = `rgba(0, 255, 255, ${cap.toFixed(2)})`;
|
|
1333
1346
|
const colorBorder = `rgba(0, 255, 255, ${cap.toFixed(2)})`;
|
|
1334
1347
|
ctx.strokeStyle = colorCircle;
|
|
@@ -1345,11 +1358,11 @@ function showNetworkMap(devices, map){
|
|
|
1345
1358
|
function redrawMap() {
|
|
1346
1359
|
if (network != undefined && devices.length > 0) {
|
|
1347
1360
|
const width = ($('.adapter-body').width() || $('#main').width()) - 20,
|
|
1348
|
-
height = ($('.adapter-body').height() || ($('#main').height())) -120;
|
|
1361
|
+
height = ($('.adapter-body').height() || ($('#main').height())) - 120;
|
|
1349
1362
|
network.setSize(width, height);
|
|
1350
1363
|
network.redraw();
|
|
1351
1364
|
network.fit();
|
|
1352
|
-
network.moveTo({offset:{x:0.5 * width, y:0.5 * height}});
|
|
1365
|
+
network.moveTo({offset: {x: 0.5 * width, y: 0.5 * height}});
|
|
1353
1366
|
}
|
|
1354
1367
|
}
|
|
1355
1368
|
|
|
@@ -1363,9 +1376,9 @@ function updateMapFilter() {
|
|
|
1363
1376
|
const invisColor = $('#filterMesh').is(':checked') ? 0.2 : 0;
|
|
1364
1377
|
mapEdges.forEach((edge) => {
|
|
1365
1378
|
if (((edge.relationship === 0 || edge.relationship === 1) && showParent)
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1379
|
+
|| (edge.relationship === 2 && showSibl)
|
|
1380
|
+
|| (edge.relationship === 3 && showParent) // ignore relationship "unknown"
|
|
1381
|
+
|| (edge.relationship === 4 && showPrvChild)) {
|
|
1369
1382
|
edge.color.opacity = 1.0;
|
|
1370
1383
|
} else {
|
|
1371
1384
|
edge.color.opacity = invisColor;
|
|
@@ -1389,13 +1402,15 @@ function getComPorts(onChange) {
|
|
|
1389
1402
|
// }, 1000);
|
|
1390
1403
|
// return;
|
|
1391
1404
|
// }
|
|
1392
|
-
if (!list)
|
|
1405
|
+
if (!list) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1393
1408
|
const element = $('#ports');
|
|
1394
1409
|
for (let j = 0; j < list.length; j++) {
|
|
1395
|
-
element.append('<li><a href="#!">' + list[j].comName +'</a></li>');
|
|
1410
|
+
element.append('<li><a href="#!" data-value="' + list[j].comName + '">' + list[j].comName + (list[j].label ? (' [' + list[j].label + ']') : '') + '</a></li>');
|
|
1396
1411
|
}
|
|
1397
|
-
$('#ports a').click(function() {
|
|
1398
|
-
$('#port').val($(this).
|
|
1412
|
+
$('#ports a').click(function () {
|
|
1413
|
+
$('#port').val($(this).data('value'));
|
|
1399
1414
|
Materialize.updateTextFields();
|
|
1400
1415
|
onChange();
|
|
1401
1416
|
});
|
|
@@ -1405,29 +1420,33 @@ function getComPorts(onChange) {
|
|
|
1405
1420
|
function loadDeveloperTab() {
|
|
1406
1421
|
// fill device selector
|
|
1407
1422
|
updateSelect('#dev', devices,
|
|
1408
|
-
function(key, device) {
|
|
1423
|
+
function (key, device) {
|
|
1409
1424
|
if (device.hasOwnProperty('info')) {
|
|
1410
|
-
if (device.info.device._type
|
|
1425
|
+
if (device.info.device._type === 'Coordinator') {
|
|
1411
1426
|
return null;
|
|
1412
1427
|
}
|
|
1413
1428
|
return `${device.common.name} (${device.info.name})`;
|
|
1414
1429
|
} else { // fallback if device in list but not paired
|
|
1415
|
-
device.common.name + ' ' +device.native.id;
|
|
1430
|
+
return device.common.name + ' ' + device.native.id;
|
|
1416
1431
|
}
|
|
1417
1432
|
},
|
|
1418
|
-
function(key, device) {
|
|
1433
|
+
function (key, device) {
|
|
1419
1434
|
return device._id;
|
|
1420
1435
|
});
|
|
1421
1436
|
// add groups to device selector
|
|
1422
1437
|
const groupList = [];
|
|
1423
1438
|
for (const key in groups) {
|
|
1424
|
-
groupList.push({
|
|
1439
|
+
groupList.push({
|
|
1440
|
+
_id: namespace + '.' + key.toString(16).padStart(16, '0'),
|
|
1441
|
+
groupId: key,
|
|
1442
|
+
groupName: groups[key]
|
|
1443
|
+
});
|
|
1425
1444
|
}
|
|
1426
1445
|
updateSelect('#dev', groupList,
|
|
1427
|
-
function(key, device) {
|
|
1428
|
-
return 'Group '+device.groupId+': '+device.groupName;
|
|
1446
|
+
function (key, device) {
|
|
1447
|
+
return 'Group ' + device.groupId + ': ' + device.groupName;
|
|
1429
1448
|
},
|
|
1430
|
-
function(key, device) {
|
|
1449
|
+
function (key, device) {
|
|
1431
1450
|
return device._id;
|
|
1432
1451
|
}, true);
|
|
1433
1452
|
|
|
@@ -1437,10 +1456,10 @@ function loadDeveloperTab() {
|
|
|
1437
1456
|
populateSelector('#type', 'typeList', this.value);
|
|
1438
1457
|
|
|
1439
1458
|
if (responseCodes == false) {
|
|
1440
|
-
const getValue = function() { // convert to number if needed
|
|
1459
|
+
const getValue = function () { // convert to number if needed
|
|
1441
1460
|
let attrData = $('#value-input').val();
|
|
1442
1461
|
if (attrData.startsWith('"') && attrData.endsWith('"')) {
|
|
1443
|
-
attrData = attrData.substr(1, attrData.length -2);
|
|
1462
|
+
attrData = attrData.substr(1, attrData.length - 2);
|
|
1444
1463
|
} else {
|
|
1445
1464
|
const numValue = Number(attrData);
|
|
1446
1465
|
attrData = !isNaN(numValue) ? numValue : attrData;
|
|
@@ -1465,35 +1484,38 @@ function loadDeveloperTab() {
|
|
|
1465
1484
|
return data;
|
|
1466
1485
|
};
|
|
1467
1486
|
|
|
1468
|
-
const prepareExpertData = function() {
|
|
1487
|
+
const prepareExpertData = function () {
|
|
1469
1488
|
try {
|
|
1470
1489
|
return JSON.parse($('#expert-json').val());
|
|
1471
1490
|
} catch (exception) {
|
|
1472
1491
|
showDevRunInfo('JSON error', exception, 'yellow');
|
|
1473
1492
|
}
|
|
1474
1493
|
};
|
|
1475
|
-
const setExpertData = function(prop, value, removeIfEmpty = true) {
|
|
1494
|
+
const setExpertData = function (prop, value, removeIfEmpty = true) {
|
|
1476
1495
|
if (!$('#expert-mode').is(':checked')) {
|
|
1477
1496
|
return;
|
|
1478
1497
|
}
|
|
1479
|
-
if (!removeIfEmpty && value == null) {
|
|
1498
|
+
if (!removeIfEmpty && value == null) {
|
|
1499
|
+
value = '';
|
|
1500
|
+
}
|
|
1480
1501
|
let data;
|
|
1481
1502
|
if (prop) {
|
|
1482
1503
|
data = prepareExpertData();
|
|
1483
1504
|
// https://stackoverflow.com/a/6394168/6937282
|
|
1484
|
-
const assignVal = function index(obj,is, value) {
|
|
1505
|
+
const assignVal = function index(obj, is, value) {
|
|
1485
1506
|
if (typeof is == 'string') {
|
|
1486
|
-
return index(obj,is.split('.'), value);
|
|
1487
|
-
} else if (is.length
|
|
1507
|
+
return index(obj, is.split('.'), value);
|
|
1508
|
+
} else if (is.length === 1 && value !== undefined) {
|
|
1488
1509
|
if (value == null) {
|
|
1489
1510
|
return delete obj[is[0]];
|
|
1490
1511
|
} else {
|
|
1491
1512
|
return obj[is[0]] = value;
|
|
1492
1513
|
}
|
|
1493
|
-
} else if (is.length
|
|
1514
|
+
} else if (!is.length) {
|
|
1494
1515
|
return obj;
|
|
1495
|
-
} else
|
|
1496
|
-
return index(obj[is[0]],is.slice(1), value);
|
|
1516
|
+
} else {
|
|
1517
|
+
return index(obj[is[0]], is.slice(1), value);
|
|
1518
|
+
}
|
|
1497
1519
|
};
|
|
1498
1520
|
assignVal(data, prop, value);
|
|
1499
1521
|
} else {
|
|
@@ -1503,7 +1525,7 @@ function loadDeveloperTab() {
|
|
|
1503
1525
|
};
|
|
1504
1526
|
|
|
1505
1527
|
// init event listener only at first load
|
|
1506
|
-
$('#dev-selector').change(function() {
|
|
1528
|
+
$('#dev-selector').change(function () {
|
|
1507
1529
|
if (this.selectedIndex <= 0) {
|
|
1508
1530
|
return;
|
|
1509
1531
|
}
|
|
@@ -1514,48 +1536,48 @@ function loadDeveloperTab() {
|
|
|
1514
1536
|
|
|
1515
1537
|
const epList = device ? device.info.device._endpoints : null;
|
|
1516
1538
|
updateSelect('#ep', epList,
|
|
1517
|
-
function(key, ep) {
|
|
1539
|
+
function (key, ep) {
|
|
1518
1540
|
return ep.ID;
|
|
1519
1541
|
},
|
|
1520
|
-
function(key, ep) {
|
|
1542
|
+
function (key, ep) {
|
|
1521
1543
|
return ep.ID;
|
|
1522
1544
|
});
|
|
1523
1545
|
setExpertData('devId', this.value);
|
|
1524
1546
|
setExpertData('ep', $('#ep-selector').val(), false);
|
|
1525
1547
|
});
|
|
1526
1548
|
|
|
1527
|
-
$('#ep-selector').change(function() {
|
|
1549
|
+
$('#ep-selector').change(function () {
|
|
1528
1550
|
setExpertData('ep', this.value);
|
|
1529
1551
|
});
|
|
1530
1552
|
|
|
1531
|
-
$('#cid-selector').change(function() {
|
|
1553
|
+
$('#cid-selector').change(function () {
|
|
1532
1554
|
populateSelector('#attrid', 'attrIdList', this.value);
|
|
1533
|
-
if ($('#cmd-type-selector').val()
|
|
1555
|
+
if ($('#cmd-type-selector').val() === 'functional') {
|
|
1534
1556
|
const cid = $('#cid-selector option:selected').val();
|
|
1535
1557
|
populateSelector('#cmd', 'cmdListFunctional', cid);
|
|
1536
1558
|
}
|
|
1537
1559
|
setExpertData('cid', this.value);
|
|
1538
1560
|
});
|
|
1539
1561
|
|
|
1540
|
-
$('#cmd-type-selector').change(function() {
|
|
1541
|
-
if (this.value
|
|
1562
|
+
$('#cmd-type-selector').change(function () {
|
|
1563
|
+
if (this.value === 'foundation') {
|
|
1542
1564
|
populateSelector('#cmd', 'cmdListFoundation');
|
|
1543
|
-
} else if (this.value
|
|
1565
|
+
} else if (this.value === 'functional') {
|
|
1544
1566
|
const cid = $('#cid-selector option:selected').val();
|
|
1545
1567
|
populateSelector('#cmd', 'cmdListFunctional', cid);
|
|
1546
1568
|
}
|
|
1547
1569
|
setExpertData('cmdType', this.value);
|
|
1548
1570
|
});
|
|
1549
1571
|
|
|
1550
|
-
$('#cmd-selector').change(function() {
|
|
1572
|
+
$('#cmd-selector').change(function () {
|
|
1551
1573
|
setExpertData('cmd', this.value);
|
|
1552
1574
|
});
|
|
1553
|
-
$('#attrid-selector').change(function() {
|
|
1554
|
-
setExpertData('zclData', {[this.value]:{}});
|
|
1575
|
+
$('#attrid-selector').change(function () {
|
|
1576
|
+
setExpertData('zclData', {[this.value]: {}});
|
|
1555
1577
|
});
|
|
1556
1578
|
|
|
1557
1579
|
// value selector checkbox
|
|
1558
|
-
$('#value-needed').change(function() {
|
|
1580
|
+
$('#value-needed').change(function () {
|
|
1559
1581
|
const attr = $('#attrid-selector').val();
|
|
1560
1582
|
let attrData = null;
|
|
1561
1583
|
if (this.checked === true) {
|
|
@@ -1564,17 +1586,17 @@ function loadDeveloperTab() {
|
|
|
1564
1586
|
} else {
|
|
1565
1587
|
$('#value-input').attr('disabled', 'disabled');
|
|
1566
1588
|
}
|
|
1567
|
-
setExpertData('zclData.'+attr, attrData);
|
|
1589
|
+
setExpertData('zclData.' + attr, attrData);
|
|
1568
1590
|
$('#type-selector').select();
|
|
1569
1591
|
Materialize.updateTextFields();
|
|
1570
1592
|
});
|
|
1571
1593
|
|
|
1572
|
-
$('#value-input').keyup(function() {
|
|
1594
|
+
$('#value-input').keyup(function () {
|
|
1573
1595
|
const attr = $('#attrid-selector').val();
|
|
1574
|
-
setExpertData('zclData.'+attr, getValue());
|
|
1596
|
+
setExpertData('zclData.' + attr, getValue());
|
|
1575
1597
|
});
|
|
1576
1598
|
|
|
1577
|
-
$('#expert-mode').change(function() {
|
|
1599
|
+
$('#expert-mode').change(function () {
|
|
1578
1600
|
if (this.checked === true) {
|
|
1579
1601
|
setExpertData();
|
|
1580
1602
|
$('#expert-json-box').css('display', 'inline-block');
|
|
@@ -1585,7 +1607,7 @@ function loadDeveloperTab() {
|
|
|
1585
1607
|
Materialize.updateTextFields();
|
|
1586
1608
|
});
|
|
1587
1609
|
|
|
1588
|
-
$('#dev-send-btn').click(function() {
|
|
1610
|
+
$('#dev-send-btn').click(function () {
|
|
1589
1611
|
let data;
|
|
1590
1612
|
if ($('#expert-mode').is(':checked')) {
|
|
1591
1613
|
data = prepareExpertData();
|
|
@@ -1593,7 +1615,7 @@ function loadDeveloperTab() {
|
|
|
1593
1615
|
data = prepareData();
|
|
1594
1616
|
}
|
|
1595
1617
|
sendToZigbee(data.devId, data.ep, data.cid, data.cmd, data.cmdType, data.zclData, data.cfg, function (reply) {
|
|
1596
|
-
console.log('Reply from zigbee: '+ JSON.stringify(reply));
|
|
1618
|
+
console.log('Reply from zigbee: ' + JSON.stringify(reply));
|
|
1597
1619
|
if (reply.hasOwnProperty('localErr')) {
|
|
1598
1620
|
showDevRunInfo(reply.localErr, reply.errMsg, 'yellow');
|
|
1599
1621
|
} else if (reply.hasOwnProperty('localStatus')) {
|
|
@@ -1634,25 +1656,34 @@ function loadDeveloperTab() {
|
|
|
1634
1656
|
*/
|
|
1635
1657
|
function sendToZigbee(id, ep, cid, cmd, cmdType, zclData, cfg, callback) {
|
|
1636
1658
|
if (!id) {
|
|
1637
|
-
if (callback) {
|
|
1659
|
+
if (callback) {
|
|
1660
|
+
callback({localErr: 'Incomplete', errMsg: 'Please select Device and Endpoint!'});
|
|
1661
|
+
}
|
|
1638
1662
|
return;
|
|
1639
1663
|
}
|
|
1640
1664
|
if (!cid || !cmd || !cmdType) {
|
|
1641
|
-
if (callback) {
|
|
1665
|
+
if (callback) {
|
|
1666
|
+
callback({
|
|
1667
|
+
localErr: 'Incomplete',
|
|
1668
|
+
errMsg: 'Please choose ClusterId, Command, CommandType and AttributeId!'
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1642
1671
|
return;
|
|
1643
1672
|
}
|
|
1644
1673
|
const data = {id: id, ep: ep, cid: cid, cmd: cmd, cmdType: cmdType, zclData: zclData, cfg: cfg};
|
|
1645
|
-
if (callback) {
|
|
1674
|
+
if (callback) {
|
|
1675
|
+
callback({localStatus: 'Send', errMsg: 'Waiting for reply...'});
|
|
1676
|
+
}
|
|
1646
1677
|
|
|
1647
|
-
const sendTimeout = setTimeout(function() {
|
|
1678
|
+
const sendTimeout = setTimeout(function () {
|
|
1648
1679
|
if (callback) {
|
|
1649
1680
|
callback({localErr: 'Timeout', errMsg: 'We did not receive any response.'});
|
|
1650
1681
|
}
|
|
1651
1682
|
}, 15000);
|
|
1652
1683
|
|
|
1653
|
-
console.log('Send to zigbee, id '+id+ ',ep '+ep+', cid '+cid+', cmd '+cmd+', cmdType '+cmdType+', zclData '+JSON.stringify(zclData));
|
|
1684
|
+
console.log('Send to zigbee, id ' + id + ',ep ' + ep + ', cid ' + cid + ', cmd ' + cmd + ', cmdType ' + cmdType + ', zclData ' + JSON.stringify(zclData));
|
|
1654
1685
|
|
|
1655
|
-
sendTo(namespace, 'sendToZigbee', data, function(reply) {
|
|
1686
|
+
sendTo(namespace, 'sendToZigbee', data, function (reply) {
|
|
1656
1687
|
clearTimeout(sendTimeout);
|
|
1657
1688
|
if (callback) {
|
|
1658
1689
|
callback(reply);
|
|
@@ -1665,11 +1696,10 @@ function sendToZigbee(id, ep, cid, cmd, cmdType, zclData, cfg, callback) {
|
|
|
1665
1696
|
*/
|
|
1666
1697
|
function showDevRunInfo(result, text, level) {
|
|
1667
1698
|
const card = $('#devActResult');
|
|
1668
|
-
if (level
|
|
1669
|
-
card.removeClass(
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
card.removeClass( 'yellow-text' ).addClass( 'white-text' );
|
|
1699
|
+
if (level === 'yellow') {
|
|
1700
|
+
card.removeClass('white-text').addClass('yellow-text');
|
|
1701
|
+
} else {
|
|
1702
|
+
card.removeClass('yellow-text').addClass('white-text');
|
|
1673
1703
|
}
|
|
1674
1704
|
$('#devActResult').text(result);
|
|
1675
1705
|
$('#devInfoMsg').text(text);
|
|
@@ -1677,13 +1707,13 @@ function showDevRunInfo(result, text, level) {
|
|
|
1677
1707
|
|
|
1678
1708
|
function addDevLog(reply) {
|
|
1679
1709
|
const statusCode = reply.statusCode;
|
|
1680
|
-
let logHtml = '<span>'+JSON.stringify(reply.msg)+'</span><br>';
|
|
1710
|
+
let logHtml = '<span>' + JSON.stringify(reply.msg) + '</span><br>';
|
|
1681
1711
|
if (responseCodes != undefined) {
|
|
1682
1712
|
const status = Object.keys(responseCodes).find(key => responseCodes[key] === statusCode);
|
|
1683
1713
|
if (statusCode == 0) {
|
|
1684
|
-
logHtml = '<span class="green-text">'+status+'</span> '+logHtml;
|
|
1714
|
+
logHtml = '<span class="green-text">' + status + '</span> ' + logHtml;
|
|
1685
1715
|
} else {
|
|
1686
|
-
logHtml = '<span class="yellow-text">'+status+'</span> '+logHtml;
|
|
1716
|
+
logHtml = '<span class="yellow-text">' + status + '</span> ' + logHtml;
|
|
1687
1717
|
}
|
|
1688
1718
|
}
|
|
1689
1719
|
const logView = $('#dev_result_log');
|
|
@@ -1695,7 +1725,7 @@ function addDevLog(reply) {
|
|
|
1695
1725
|
* Query adapter and update select with result
|
|
1696
1726
|
*/
|
|
1697
1727
|
function populateSelector(selectId, key, cid) {
|
|
1698
|
-
$(selectId+'>option:enabled').remove(); // remove existing elements
|
|
1728
|
+
$(selectId + '>option:enabled').remove(); // remove existing elements
|
|
1699
1729
|
$(selectId).select();
|
|
1700
1730
|
if (cid == '-2') {
|
|
1701
1731
|
updateSelect(selectId, null);
|
|
@@ -1706,7 +1736,7 @@ function populateSelector(selectId, key, cid) {
|
|
|
1706
1736
|
if (key === 'attrIdList') {
|
|
1707
1737
|
updateSelect(selectId, list,
|
|
1708
1738
|
(attrName, attr) => {
|
|
1709
|
-
return attrName + ' ('+attr.ID +', type '+attr.type+')';
|
|
1739
|
+
return attrName + ' (' + attr.ID + ', type ' + attr.type + ')';
|
|
1710
1740
|
},
|
|
1711
1741
|
(attrName) => {
|
|
1712
1742
|
return attrName;
|
|
@@ -1714,7 +1744,7 @@ function populateSelector(selectId, key, cid) {
|
|
|
1714
1744
|
} else if (key === 'typeList') {
|
|
1715
1745
|
updateSelect(selectId, list,
|
|
1716
1746
|
(name, val) => {
|
|
1717
|
-
return name +' ('+val+')';
|
|
1747
|
+
return name + ' (' + val + ')';
|
|
1718
1748
|
},
|
|
1719
1749
|
(name, val) => {
|
|
1720
1750
|
return val;
|
|
@@ -1722,7 +1752,7 @@ function populateSelector(selectId, key, cid) {
|
|
|
1722
1752
|
} else {
|
|
1723
1753
|
updateSelect(selectId, list,
|
|
1724
1754
|
(propName, propInfo) => {
|
|
1725
|
-
return propName +' ('+propInfo.ID+')';
|
|
1755
|
+
return propName + ' (' + propInfo.ID + ')';
|
|
1726
1756
|
},
|
|
1727
1757
|
(propName) => {
|
|
1728
1758
|
return propName;
|
|
@@ -1732,32 +1762,31 @@ function populateSelector(selectId, key, cid) {
|
|
|
1732
1762
|
}
|
|
1733
1763
|
|
|
1734
1764
|
function updateSelect(id, list, getText, getId, append = false) {
|
|
1735
|
-
const selectId = id+'-selector';
|
|
1765
|
+
const selectId = id + '-selector';
|
|
1736
1766
|
const mySelect = $(selectId);
|
|
1737
1767
|
if (!append) {
|
|
1738
|
-
$(selectId+'>:not(:first[disabled])').remove(); // remove existing elements, except first if disabled, (is 'Select...' info)
|
|
1768
|
+
$(selectId + '>:not(:first[disabled])').remove(); // remove existing elements, except first if disabled, (is 'Select...' info)
|
|
1739
1769
|
mySelect.select();
|
|
1740
1770
|
}
|
|
1741
1771
|
if (list == null && !append) {
|
|
1742
1772
|
const infoOption = new Option('Nothing available');
|
|
1743
1773
|
infoOption.disabled = true;
|
|
1744
|
-
mySelect.append(
|
|
1745
|
-
}
|
|
1746
|
-
else {
|
|
1774
|
+
mySelect.append(infoOption);
|
|
1775
|
+
} else {
|
|
1747
1776
|
const keys = Object.keys(list); // is index in case of array
|
|
1748
|
-
for (let i=0; i<keys.length; i++) {
|
|
1777
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1749
1778
|
const key = keys[i];
|
|
1750
1779
|
const item = list[key];
|
|
1751
1780
|
const optionText = getText(key, item);
|
|
1752
1781
|
if (optionText == null) {
|
|
1753
1782
|
continue;
|
|
1754
1783
|
}
|
|
1755
|
-
mySelect.append(
|
|
1784
|
+
mySelect.append(new Option(optionText, getId(key, item)));
|
|
1756
1785
|
}
|
|
1757
1786
|
}
|
|
1758
1787
|
|
|
1759
|
-
if ($(id+'-c-input').length > 0) {
|
|
1760
|
-
mySelect.append(
|
|
1788
|
+
if ($(id + '-c-input').length > 0) {
|
|
1789
|
+
mySelect.append(new Option('CUSTOM', -2));
|
|
1761
1790
|
}
|
|
1762
1791
|
// update select element (Materialize)
|
|
1763
1792
|
mySelect.select();
|
|
@@ -1786,17 +1815,17 @@ function showGroups() {
|
|
|
1786
1815
|
const element = $('#groups_table');
|
|
1787
1816
|
for (const j in groups) {
|
|
1788
1817
|
if (groups.hasOwnProperty(j)) {
|
|
1789
|
-
element.append(`<tr id="group_${j}" class="group"><td>${j}</td><td><div>${groups[j]}<span class="right"
|
|
1790
|
-
|
|
1791
|
-
|
|
1818
|
+
element.append(`<tr id="group_${j}" class="group"><td>${j}</td><td><div>${groups[j]}<span class="right">` +
|
|
1819
|
+
`<a id="${j}" name="groupedit" class="waves-effect green btn-floating"><i class="material-icons">edit</i></a>` +
|
|
1820
|
+
`<a id="${j}" name="groupdelete" class="waves-effect red btn-floating"><i class="material-icons">delete</i></a></span></div></td></tr>`);
|
|
1792
1821
|
}
|
|
1793
1822
|
}
|
|
1794
|
-
$(
|
|
1823
|
+
$('a.btn-floating[name=\'groupedit\']').click(function () {
|
|
1795
1824
|
const index = $(this).attr('id'),
|
|
1796
1825
|
name = groups[index];
|
|
1797
1826
|
editGroupName(index, name, false);
|
|
1798
1827
|
});
|
|
1799
|
-
$(
|
|
1828
|
+
$('a.btn-floating[name=\'groupdelete\']').click(function () {
|
|
1800
1829
|
const index = $(this).attr('id'),
|
|
1801
1830
|
name = groups[index];
|
|
1802
1831
|
deleteGroupConfirmation(index, name);
|
|
@@ -1808,53 +1837,51 @@ function editGroupName(id, name, isnew) {
|
|
|
1808
1837
|
//console.log('devices: '+ JSON.stringify(devices));
|
|
1809
1838
|
const groupables = [];
|
|
1810
1839
|
for (const d of devices) {
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1840
|
+
if (d && d.info && d.info.endpoints) {
|
|
1841
|
+
for (const ep of d.info.endpoints) {
|
|
1842
|
+
if (ep.inputClusters.includes(4)) {
|
|
1843
|
+
groupables.push(ep);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1817
1846
|
}
|
|
1818
|
-
|
|
1819
|
-
//console.log('device ' + JSON.stringify(d));
|
|
1847
|
+
//console.log('device ' + JSON.stringify(d));
|
|
1820
1848
|
}
|
|
1821
1849
|
|
|
1822
1850
|
//var text = 'Enter new name for "'+name+'" ('+id+')?';
|
|
1823
1851
|
if (isnew) {
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
$('#groupedit').find(
|
|
1836
|
-
$('#groupedit
|
|
1837
|
-
$(
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
newName = $('#groupedit').find("input[id='g_name']").val();
|
|
1852
|
+
$('#groupedit').find('.editgroup').addClass('hide');
|
|
1853
|
+
$('#groupedit').find('.addgroup').removeClass('hide');
|
|
1854
|
+
$('#groupedit').find('.input-field.members').addClass('hide');
|
|
1855
|
+
$('#groupedit').find('.input-field.groupid').removeClass('hide');
|
|
1856
|
+
} else {
|
|
1857
|
+
$('#groupedit').find('.editgroup').removeClass('hide');
|
|
1858
|
+
$('#groupedit').find('.addgroup').addClass('hide');
|
|
1859
|
+
$('#groupedit').find('.input-field.members').removeClass('hide');
|
|
1860
|
+
$('#groupedit').find('.input-field.groupid').addClass('hide');
|
|
1861
|
+
}
|
|
1862
|
+
$('#groupedit').find('input[id=\'g_index\']').val(id);
|
|
1863
|
+
$('#groupedit').find('input[id=\'g_name\']').val(name);
|
|
1864
|
+
$('#groupedit a.btn[name=\'save\']').unbind('click');
|
|
1865
|
+
$('#groupedit a.btn[name=\'save\']').click(() => {
|
|
1866
|
+
const newId = $('#groupedit').find('input[id=\'g_index\']').val(),
|
|
1867
|
+
newName = $('#groupedit').find('input[id=\'g_name\']').val();
|
|
1841
1868
|
updateGroup(id, newId, newName);
|
|
1842
|
-
//
|
|
1843
|
-
//
|
|
1869
|
+
// showGroups();
|
|
1870
|
+
// getDevices();
|
|
1844
1871
|
});
|
|
1845
1872
|
$('#groupedit').modal('open');
|
|
1846
1873
|
Materialize.updateTextFields();
|
|
1847
1874
|
}
|
|
1848
1875
|
|
|
1849
1876
|
function deleteGroupConfirmation(id, name) {
|
|
1850
|
-
const text = translateWord('Do you really whant to delete group') + ' "'+name+'" ('+id+')?';
|
|
1877
|
+
const text = translateWord('Do you really whant to delete group') + ' "' + name + '" (' + id + ')?';
|
|
1851
1878
|
$('#modaldelete').find('p').text(text);
|
|
1852
1879
|
$('#forcediv').addClass('hide');
|
|
1853
|
-
$(
|
|
1854
|
-
$(
|
|
1880
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
1881
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
1855
1882
|
deleteGroup(id);
|
|
1856
|
-
//
|
|
1857
|
-
//
|
|
1883
|
+
// showGroups();
|
|
1884
|
+
// getDevices();
|
|
1858
1885
|
});
|
|
1859
1886
|
$('#modaldelete').modal('open');
|
|
1860
1887
|
}
|
|
@@ -1862,8 +1889,8 @@ function deleteGroupConfirmation(id, name) {
|
|
|
1862
1889
|
function updateGroup(id, newId, newName) {
|
|
1863
1890
|
delete groups[id];
|
|
1864
1891
|
groups[newId] = newName;
|
|
1865
|
-
sendTo(namespace, 'renameGroup', {
|
|
1866
|
-
if (msg &&
|
|
1892
|
+
sendTo(namespace, 'renameGroup', {id: newId, name: newName}, function (msg) {
|
|
1893
|
+
if (msg && msg.error) {
|
|
1867
1894
|
showMessage(msg.error, _('Error'));
|
|
1868
1895
|
}
|
|
1869
1896
|
getDevices();
|
|
@@ -1872,8 +1899,8 @@ function updateGroup(id, newId, newName) {
|
|
|
1872
1899
|
|
|
1873
1900
|
function deleteGroup(id) {
|
|
1874
1901
|
delete groups[id];
|
|
1875
|
-
sendTo(namespace, 'deleteGroup', id
|
|
1876
|
-
if (msg &&
|
|
1902
|
+
sendTo(namespace, 'deleteGroup', id, function (msg) {
|
|
1903
|
+
if (msg && msg.error) {
|
|
1877
1904
|
showMessage(msg.error, _('Error'));
|
|
1878
1905
|
}
|
|
1879
1906
|
getDevices();
|
|
@@ -1881,58 +1908,55 @@ function deleteGroup(id) {
|
|
|
1881
1908
|
}
|
|
1882
1909
|
|
|
1883
1910
|
function updateDev(id, newName, newGroups) {
|
|
1884
|
-
const dev = devices.find((d) => d._id
|
|
1885
|
-
if (dev && dev.common.name
|
|
1911
|
+
const dev = devices.find((d) => d._id === id);
|
|
1912
|
+
if (dev && dev.common.name !== newName) {
|
|
1886
1913
|
renameDevice(id, newName);
|
|
1887
1914
|
}
|
|
1888
|
-
const keys = Object.keys(newGroups)
|
|
1889
|
-
if (keys && keys.length)
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
});
|
|
1902
|
-
showWaitingDialog('Updating group memberships', 10);
|
|
1915
|
+
const keys = Object.keys(newGroups);
|
|
1916
|
+
if (keys && keys.length) {
|
|
1917
|
+
sendTo(namespace, 'updateGroupMembership', {id: id, groups: newGroups}, function (msg) {
|
|
1918
|
+
closeWaitingDialog();
|
|
1919
|
+
if (msg && msg.error) {
|
|
1920
|
+
showMessage(msg.error, _('Error'));
|
|
1921
|
+
} else {
|
|
1922
|
+
// save dev-groups on success
|
|
1923
|
+
dev.groups = newGroups;
|
|
1924
|
+
}
|
|
1925
|
+
showDevices();
|
|
1926
|
+
});
|
|
1927
|
+
showWaitingDialog('Updating group memberships', 10);
|
|
1903
1928
|
|
|
1904
1929
|
}
|
|
1905
|
-
/*
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1930
|
+
/*
|
|
1931
|
+
if (dev.info.device._type == 'Router') {
|
|
1932
|
+
const oldGroups = devGroups[id] || [];
|
|
1933
|
+
if (oldGroups.toString() != newGroups.toString()) {
|
|
1934
|
+
devGroups[id] = newGroups;
|
|
1935
|
+
sendTo(namespace, 'updateGroupMembership', { id: id, groups: newGroups }, function (msg) {
|
|
1936
|
+
if (msg && msg.error) {
|
|
1937
|
+
showMessage(msg.error, _('Error'));
|
|
1938
|
+
}
|
|
1939
|
+
else {
|
|
1940
|
+
// save dev-groups on success
|
|
1941
|
+
dev.groups = newGroups;
|
|
1942
|
+
}
|
|
1943
|
+
showDevices();
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1920
1946
|
}
|
|
1921
|
-
|
|
1922
|
-
*/
|
|
1947
|
+
*/
|
|
1923
1948
|
}
|
|
1924
1949
|
|
|
1925
1950
|
function resetConfirmation() {
|
|
1926
1951
|
$('#modalreset').modal('open');
|
|
1927
1952
|
const btn = $('#modalreset .modal-content a.btn');
|
|
1928
1953
|
btn.unbind('click');
|
|
1929
|
-
btn.click(function(e) {
|
|
1954
|
+
btn.click(function (e) {
|
|
1930
1955
|
sendTo(namespace, 'reset', {mode: e.target.id}, function (err) {
|
|
1931
1956
|
if (err) {
|
|
1932
1957
|
console.log(err);
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
console.log('Reseted');
|
|
1958
|
+
} else {
|
|
1959
|
+
console.log('Reset done');
|
|
1936
1960
|
}
|
|
1937
1961
|
});
|
|
1938
1962
|
});
|
|
@@ -1942,7 +1966,7 @@ function showViewConfig() {
|
|
|
1942
1966
|
$('#modalviewconfig').modal('open');
|
|
1943
1967
|
}
|
|
1944
1968
|
|
|
1945
|
-
function prepareBindingDialog(bindObj){
|
|
1969
|
+
function prepareBindingDialog(bindObj) {
|
|
1946
1970
|
const binddevices = devices.slice();
|
|
1947
1971
|
binddevices.unshift('');
|
|
1948
1972
|
const bind_source = (bindObj) ? [bindObj.bind_source] : [''];
|
|
@@ -1953,12 +1977,12 @@ function prepareBindingDialog(bindObj){
|
|
|
1953
1977
|
const allowClustersName = {5: 'genScenes', 6: 'genOnOff', 8: 'genLevelCtrl', 768: 'lightingColorCtrl'};
|
|
1954
1978
|
// fill device selector
|
|
1955
1979
|
list2select('#bind_source', binddevices, bind_source,
|
|
1956
|
-
function(key, device) {
|
|
1980
|
+
function (key, device) {
|
|
1957
1981
|
if (device == '') {
|
|
1958
1982
|
return 'Select source device';
|
|
1959
1983
|
}
|
|
1960
1984
|
if (device.hasOwnProperty('info')) {
|
|
1961
|
-
if (device.info.device._type
|
|
1985
|
+
if (device.info.device._type === 'Coordinator') {
|
|
1962
1986
|
return null;
|
|
1963
1987
|
}
|
|
1964
1988
|
// check for output clusters
|
|
@@ -1978,19 +2002,18 @@ function prepareBindingDialog(bindObj){
|
|
|
1978
2002
|
return null;
|
|
1979
2003
|
}
|
|
1980
2004
|
return device.common.name;
|
|
1981
|
-
}
|
|
1982
|
-
|
|
1983
|
-
device.common.name + ' ' +device.native.id;
|
|
2005
|
+
} else { // fallback if device in list but not paired
|
|
2006
|
+
return device.common.name + ' ' + device.native.id;
|
|
1984
2007
|
}
|
|
1985
2008
|
},
|
|
1986
|
-
function(key, device) {
|
|
2009
|
+
function (key, device) {
|
|
1987
2010
|
if (device == '') {
|
|
1988
2011
|
return '';
|
|
1989
2012
|
} else {
|
|
1990
2013
|
return device._id;
|
|
1991
2014
|
}
|
|
1992
2015
|
},
|
|
1993
|
-
function(key, device) {
|
|
2016
|
+
function (key, device) {
|
|
1994
2017
|
if (device == '') {
|
|
1995
2018
|
return 'disabled';
|
|
1996
2019
|
} else if (device.icon) {
|
|
@@ -2005,12 +2028,12 @@ function prepareBindingDialog(bindObj){
|
|
|
2005
2028
|
bindtargets.push({'_id': key, 'groupId': key, 'groupName': groups[key]});
|
|
2006
2029
|
}
|
|
2007
2030
|
list2select('#bind_target', bindtargets, bind_target,
|
|
2008
|
-
function(key, device) {
|
|
2031
|
+
function (key, device) {
|
|
2009
2032
|
if (device == '') {
|
|
2010
2033
|
return 'Select target device';
|
|
2011
2034
|
}
|
|
2012
2035
|
if (device.hasOwnProperty('info')) {
|
|
2013
|
-
if (device.info.device._type
|
|
2036
|
+
if (device.info.device._type === 'Coordinator') {
|
|
2014
2037
|
return null;
|
|
2015
2038
|
}
|
|
2016
2039
|
// check for input clusters
|
|
@@ -2036,14 +2059,14 @@ function prepareBindingDialog(bindObj){
|
|
|
2036
2059
|
}
|
|
2037
2060
|
}
|
|
2038
2061
|
},
|
|
2039
|
-
function(key, device) {
|
|
2062
|
+
function (key, device) {
|
|
2040
2063
|
if (device == '') {
|
|
2041
2064
|
return '';
|
|
2042
2065
|
} else {
|
|
2043
2066
|
return device._id;
|
|
2044
2067
|
}
|
|
2045
2068
|
},
|
|
2046
|
-
function(key, device) {
|
|
2069
|
+
function (key, device) {
|
|
2047
2070
|
if (device == '') {
|
|
2048
2071
|
return 'disabled';
|
|
2049
2072
|
} else if (device.icon) {
|
|
@@ -2062,13 +2085,17 @@ function prepareBindingDialog(bindObj){
|
|
|
2062
2085
|
const epList = device ? device.info.endpoints : [];
|
|
2063
2086
|
const sClusterList = epList.map((ep) => {
|
|
2064
2087
|
const clusters = ep.outputClusters.map((cl) => {
|
|
2065
|
-
return allowClusters.includes(cl) ? {ID: ep.ID+'_'+cl, name: allowClustersName[cl]} : null;
|
|
2066
|
-
}).filter((i) => {
|
|
2067
|
-
|
|
2068
|
-
|
|
2088
|
+
return allowClusters.includes(cl) ? {ID: ep.ID + '_' + cl, name: allowClustersName[cl]} : null;
|
|
2089
|
+
}).filter((i) => {
|
|
2090
|
+
return i != null;
|
|
2091
|
+
});
|
|
2092
|
+
return clusters.length == 0 ? null : [{ID: ep.ID, name: 'all'}, clusters];
|
|
2093
|
+
}).flat(2).filter((i) => {
|
|
2094
|
+
return i != null;
|
|
2095
|
+
});
|
|
2069
2096
|
list2select('#bind_source_ep', sClusterList, (selected) ? [selected] : [],
|
|
2070
2097
|
(key, ep) => {
|
|
2071
|
-
return ep.ID+' '+ep.name;
|
|
2098
|
+
return ep.ID + ' ' + ep.name;
|
|
2072
2099
|
},
|
|
2073
2100
|
(key, ep) => {
|
|
2074
2101
|
return ep.ID;
|
|
@@ -2084,13 +2111,20 @@ function prepareBindingDialog(bindObj){
|
|
|
2084
2111
|
const epList = device ? device.info.endpoints : [];
|
|
2085
2112
|
const tClusterList = epList.map((ep) => {
|
|
2086
2113
|
const clusters = ep.inputClusters.map((cl) => {
|
|
2087
|
-
return (allowClusters.includes(cl) && (!sourceCl || sourceCl == cl)) ? {
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2114
|
+
return (allowClusters.includes(cl) && (!sourceCl || sourceCl == cl)) ? {
|
|
2115
|
+
ID: ep.ID + '_' + cl,
|
|
2116
|
+
name: allowClustersName[cl]
|
|
2117
|
+
} : null;
|
|
2118
|
+
}).filter((i) => {
|
|
2119
|
+
return i != null;
|
|
2120
|
+
});
|
|
2121
|
+
return !clusters.length ? null : [{ID: ep.ID, name: 'all'}, clusters];
|
|
2122
|
+
}).flat(2).filter(i => {
|
|
2123
|
+
return i != null;
|
|
2124
|
+
});
|
|
2091
2125
|
list2select('#bind_target_ep', tClusterList, (selected) ? [selected] : [],
|
|
2092
2126
|
(key, ep) => {
|
|
2093
|
-
return ep.ID+' '+ep.name;
|
|
2127
|
+
return ep.ID + ' ' + ep.name;
|
|
2094
2128
|
},
|
|
2095
2129
|
(key, ep) => {
|
|
2096
2130
|
return ep.ID;
|
|
@@ -2098,7 +2132,7 @@ function prepareBindingDialog(bindObj){
|
|
|
2098
2132
|
);
|
|
2099
2133
|
};
|
|
2100
2134
|
|
|
2101
|
-
$('#bind_source').change(function() {
|
|
2135
|
+
$('#bind_source').change(function () {
|
|
2102
2136
|
if (this.selectedIndex <= 0) {
|
|
2103
2137
|
return;
|
|
2104
2138
|
}
|
|
@@ -2110,7 +2144,7 @@ function prepareBindingDialog(bindObj){
|
|
|
2110
2144
|
configureSourceEp();
|
|
2111
2145
|
}
|
|
2112
2146
|
|
|
2113
|
-
$('#bind_target').change(function() {
|
|
2147
|
+
$('#bind_target').change(function () {
|
|
2114
2148
|
if (this.selectedIndex <= 0) {
|
|
2115
2149
|
return;
|
|
2116
2150
|
}
|
|
@@ -2123,7 +2157,7 @@ function prepareBindingDialog(bindObj){
|
|
|
2123
2157
|
configureTargetEp();
|
|
2124
2158
|
}
|
|
2125
2159
|
|
|
2126
|
-
$('#bind_source_ep').change(function() {
|
|
2160
|
+
$('#bind_source_ep').change(function () {
|
|
2127
2161
|
$('#bind_target').trigger('change');
|
|
2128
2162
|
});
|
|
2129
2163
|
|
|
@@ -2132,8 +2166,8 @@ function prepareBindingDialog(bindObj){
|
|
|
2132
2166
|
}
|
|
2133
2167
|
|
|
2134
2168
|
function addBindingDialog() {
|
|
2135
|
-
$(
|
|
2136
|
-
$(
|
|
2169
|
+
$('#bindingmodaledit a.btn[name=\'save\']').unbind('click');
|
|
2170
|
+
$('#bindingmodaledit a.btn[name=\'save\']').click(() => {
|
|
2137
2171
|
const //bind_id = $('#bindingmodaledit').find("input[id='bind_id']").val(),
|
|
2138
2172
|
bind_source = $('#bindingmodaledit').find('#bind_source option:selected').val(),
|
|
2139
2173
|
bind_source_ep = $('#bindingmodaledit').find('#bind_source_ep option:selected').val(),
|
|
@@ -2157,10 +2191,8 @@ function addBinding(bind_source, bind_source_ep, bind_target, bind_target_ep, un
|
|
|
2157
2191
|
unbind_from_coordinator
|
|
2158
2192
|
}, function (msg) {
|
|
2159
2193
|
closeWaitingDialog();
|
|
2160
|
-
if (msg) {
|
|
2161
|
-
|
|
2162
|
-
showMessage(msg.error, _('Error'));
|
|
2163
|
-
}
|
|
2194
|
+
if (msg && msg.error) {
|
|
2195
|
+
showMessage(msg.error, _('Error'));
|
|
2164
2196
|
}
|
|
2165
2197
|
getBinding();
|
|
2166
2198
|
});
|
|
@@ -2177,10 +2209,8 @@ function editBinding(bind_id, bind_source, bind_source_ep, bind_target, bind_tar
|
|
|
2177
2209
|
unbind_from_coordinator
|
|
2178
2210
|
}, function (msg) {
|
|
2179
2211
|
closeWaitingDialog();
|
|
2180
|
-
if (msg) {
|
|
2181
|
-
|
|
2182
|
-
showMessage(msg.error, _('Error'));
|
|
2183
|
-
}
|
|
2212
|
+
if (msg && msg.error) {
|
|
2213
|
+
showMessage(msg.error, _('Error'));
|
|
2184
2214
|
}
|
|
2185
2215
|
getBinding();
|
|
2186
2216
|
});
|
|
@@ -2188,8 +2218,8 @@ function editBinding(bind_id, bind_source, bind_source_ep, bind_target, bind_tar
|
|
|
2188
2218
|
}
|
|
2189
2219
|
|
|
2190
2220
|
function editBindingDialog(bindObj) {
|
|
2191
|
-
$(
|
|
2192
|
-
$(
|
|
2221
|
+
$('#bindingmodaledit a.btn[name=\'save\']').unbind('click');
|
|
2222
|
+
$('#bindingmodaledit a.btn[name=\'save\']').click(() => {
|
|
2193
2223
|
const //bind_id = $('#bindingmodaledit').find("input[id='bind_id']").val(),
|
|
2194
2224
|
bind_source = $('#bindingmodaledit').find('#bind_source option:selected').val(),
|
|
2195
2225
|
bind_source_ep = $('#bindingmodaledit').find('#bind_source_ep option:selected').val(),
|
|
@@ -2225,9 +2255,9 @@ function showBinding() {
|
|
|
2225
2255
|
<i class="right">${target_icon}</i>
|
|
2226
2256
|
<div style="min-height:72px; font-size: 0.8em" class="truncate">
|
|
2227
2257
|
<ul>
|
|
2228
|
-
<li><span class="label">source:</span><span>0x${bind_source.replace(namespace+'.', '')}</span></li>
|
|
2258
|
+
<li><span class="label">source:</span><span>0x${bind_source.replace(namespace + '.', '')}</span></li>
|
|
2229
2259
|
<li><span class="label">endpoint:</span><span>${bind_source_ep}</span></li>
|
|
2230
|
-
<li><span class="label">target:</span><span>0x${bind_target.replace(namespace+'.', '')}</span></li>
|
|
2260
|
+
<li><span class="label">target:</span><span>0x${bind_target.replace(namespace + '.', '')}</span></li>
|
|
2231
2261
|
<li><span class="label">endpoint:</span><span>${bind_target_ep}</span></li>
|
|
2232
2262
|
</ul>
|
|
2233
2263
|
</div>
|
|
@@ -2249,11 +2279,11 @@ function showBinding() {
|
|
|
2249
2279
|
element.append(card);
|
|
2250
2280
|
});
|
|
2251
2281
|
|
|
2252
|
-
$(
|
|
2282
|
+
$('#binding button[name=\'delete\']').click(function () {
|
|
2253
2283
|
const bind_id = $(this).parents('.binding')[0].id;
|
|
2254
2284
|
deleteBindingConfirmation(bind_id);
|
|
2255
2285
|
});
|
|
2256
|
-
$(
|
|
2286
|
+
$('#binding button[name=\'edit\']').click(function () {
|
|
2257
2287
|
const bind_id = $(this).parents('.binding')[0].id;
|
|
2258
2288
|
const bindObj = binding.find((b) => b.id == bind_id);
|
|
2259
2289
|
if (bindObj) {
|
|
@@ -2280,8 +2310,8 @@ function deleteBindingConfirmation(id) {
|
|
|
2280
2310
|
$('#modaldelete').find('p').text(text);
|
|
2281
2311
|
//$('#forcediv').removeClass('hide');
|
|
2282
2312
|
$('#forcediv').addClass('hide');
|
|
2283
|
-
$(
|
|
2284
|
-
$(
|
|
2313
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
2314
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
2285
2315
|
deleteBinding(id);
|
|
2286
2316
|
});
|
|
2287
2317
|
$('#modaldelete').modal('open');
|
|
@@ -2314,14 +2344,14 @@ function genDevInfo(device) {
|
|
|
2314
2344
|
const dev = (device && device.info) ? device.info.device : undefined;
|
|
2315
2345
|
const mapped = (device && device.info) ? device.info.mapped : undefined;
|
|
2316
2346
|
if (!dev) return `<div class="truncate">No info</div>`;
|
|
2317
|
-
const genRow = function(name, value, refresh) {
|
|
2347
|
+
const genRow = function (name, value, refresh) {
|
|
2318
2348
|
if (value === undefined) {
|
|
2319
2349
|
return '';
|
|
2320
2350
|
} else {
|
|
2321
2351
|
return `<li><span class="label">${name}:</span><span>${value}</span></li>`;
|
|
2322
2352
|
}
|
|
2323
2353
|
};
|
|
2324
|
-
const genRowValues = function(name, value) {
|
|
2354
|
+
const genRowValues = function (name, value) {
|
|
2325
2355
|
if (value === undefined) {
|
|
2326
2356
|
return '';
|
|
2327
2357
|
} else {
|
|
@@ -2356,7 +2386,7 @@ function genDevInfo(device) {
|
|
|
2356
2386
|
</div>`;
|
|
2357
2387
|
}
|
|
2358
2388
|
const imgSrc = device.icon || device.common.icon;
|
|
2359
|
-
const imgInfo = (imgSrc) ? `<img src=${imgSrc} width='150px' onerror="this.onerror=null;this.src='img/unavailable.png';"><div class="divider"></div
|
|
2389
|
+
const imgInfo = (imgSrc) ? `<img src=${imgSrc} width='150px' onerror="this.onerror=null;this.src='img/unavailable.png';"><div class="divider"></div>` : '';
|
|
2360
2390
|
const info =
|
|
2361
2391
|
`<div class="col s12 m6 l6 xl6">
|
|
2362
2392
|
${imgInfo}
|
|
@@ -2388,29 +2418,28 @@ function genDevInfo(device) {
|
|
|
2388
2418
|
return info;
|
|
2389
2419
|
}
|
|
2390
2420
|
|
|
2391
|
-
function showDevInfo(id){
|
|
2421
|
+
function showDevInfo(id) {
|
|
2392
2422
|
const info = genDevInfo(getDeviceByID(id));
|
|
2393
2423
|
$('#devinfo').html(info);
|
|
2394
2424
|
$('#modaldevinfo').modal('open');
|
|
2395
2425
|
}
|
|
2396
2426
|
|
|
2397
|
-
function showGroupList(show){
|
|
2427
|
+
function showGroupList(show) {
|
|
2398
2428
|
const htmlsections = [];
|
|
2399
2429
|
for (const groupid in devGroups) {
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
htmlsections.push(`
|
|
2430
|
+
const dev = devGroups[groupid];
|
|
2431
|
+
const grpname = (dev.common && dev.common.name ? dev.common.name : 'Group ' + groupid);
|
|
2432
|
+
const selectables = [];
|
|
2433
|
+
const members = [];
|
|
2434
|
+
if (dev && dev.memberinfo) {
|
|
2435
|
+
selectables.push(`<select id="members_${groupid}" multiple>`);
|
|
2436
|
+
for (let m = 0; m < dev.memberinfo.length; m++) {
|
|
2437
|
+
members.push(`${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (${dev.memberinfo[m].ieee})`);
|
|
2438
|
+
selectables.push(`<option value="${m}">${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (...${dev.memberinfo[m].ieee.slice(-4)})</option>`);
|
|
2439
|
+
}
|
|
2440
|
+
selectables.push('</select>');
|
|
2441
|
+
}
|
|
2442
|
+
htmlsections.push(`
|
|
2414
2443
|
<div class="row">
|
|
2415
2444
|
<div class="col s4 m4 l4">
|
|
2416
2445
|
<h5>${grpname}<h5>
|
|
@@ -2423,38 +2452,38 @@ function showGroupList(show){
|
|
|
2423
2452
|
}
|
|
2424
2453
|
|
|
2425
2454
|
$('#grouplist').html(htmlsections.join(''));
|
|
2426
|
-
$('#add').click(function() {
|
|
2427
|
-
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
|
|
2428
|
-
editGroupName(maxind+1, 'Group ' + maxind+1, true);
|
|
2455
|
+
$('#add').click(function () {
|
|
2456
|
+
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
2457
|
+
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
2429
2458
|
showGroupList(false);
|
|
2430
2459
|
});
|
|
2431
2460
|
|
|
2432
|
-
$(
|
|
2433
|
-
$(
|
|
2461
|
+
$('#modalgrouplist a.btn[name=\'save\']').unbind('click');
|
|
2462
|
+
$('#modalgrouplist a.btn[name=\'save\']').click(() => {
|
|
2434
2463
|
});
|
|
2435
2464
|
if (show) $('#modalgrouplist').modal('open');
|
|
2436
2465
|
}
|
|
2437
2466
|
|
|
2438
2467
|
let waitingTimeout, waitingInt;
|
|
2439
2468
|
|
|
2440
|
-
function showWaitingDialog(text, timeout){
|
|
2469
|
+
function showWaitingDialog(text, timeout) {
|
|
2441
2470
|
let countDown = timeout;
|
|
2442
|
-
waitingInt = setInterval(function() {
|
|
2471
|
+
waitingInt = setInterval(function () {
|
|
2443
2472
|
countDown -= 1;
|
|
2444
|
-
const percent = 100-100*countDown/timeout;
|
|
2473
|
+
const percent = 100 - 100 * countDown / timeout;
|
|
2445
2474
|
$('#waiting_progress_line').css('width', `${percent}%`);
|
|
2446
2475
|
}, 1000);
|
|
2447
|
-
waitingTimeout = setTimeout(function() {
|
|
2476
|
+
waitingTimeout = setTimeout(function () {
|
|
2448
2477
|
$('#waiting_progress_line').css('width', `0%`);
|
|
2449
2478
|
clearTimeout(waitingInt);
|
|
2450
2479
|
clearTimeout(waitingTimeout);
|
|
2451
2480
|
$('#modalWaiting').modal('close');
|
|
2452
|
-
}, timeout*1000);
|
|
2481
|
+
}, timeout * 1000);
|
|
2453
2482
|
$('#waiting_message').text(text);
|
|
2454
2483
|
$('#modalWaiting').modal('open');
|
|
2455
2484
|
}
|
|
2456
2485
|
|
|
2457
|
-
function closeWaitingDialog(){
|
|
2486
|
+
function closeWaitingDialog() {
|
|
2458
2487
|
if (waitingInt) clearTimeout(waitingInt);
|
|
2459
2488
|
if (waitingTimeout) clearTimeout(waitingTimeout);
|
|
2460
2489
|
$('#modalWaiting').modal('close');
|
|
@@ -2471,7 +2500,7 @@ function showChannels() {
|
|
|
2471
2500
|
$('#modalchannels').modal('open');
|
|
2472
2501
|
let info = '';
|
|
2473
2502
|
for (let ch = 11; ch < 27; ch++) {
|
|
2474
|
-
const value = msg.energyvalues[ch-11];
|
|
2503
|
+
const value = msg.energyvalues[ch - 11];
|
|
2475
2504
|
info +=
|
|
2476
2505
|
`<div style="padding-top: 10px">
|
|
2477
2506
|
<span class="">№ ${ch}: ${value}%</span>
|
|
@@ -2529,7 +2558,7 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
2529
2558
|
|
|
2530
2559
|
list2select('#exclude_target', onlyOneTargets, exclude_target,
|
|
2531
2560
|
|
|
2532
|
-
function(key, device) {
|
|
2561
|
+
function (key, device) {
|
|
2533
2562
|
if (device == '') {
|
|
2534
2563
|
return 'Select model';
|
|
2535
2564
|
}
|
|
@@ -2542,14 +2571,14 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
2542
2571
|
return device.common.type;
|
|
2543
2572
|
}
|
|
2544
2573
|
},
|
|
2545
|
-
function(key, device) {
|
|
2574
|
+
function (key, device) {
|
|
2546
2575
|
if (device == '') {
|
|
2547
2576
|
return '';
|
|
2548
2577
|
} else {
|
|
2549
2578
|
return device._id;
|
|
2550
2579
|
}
|
|
2551
2580
|
},
|
|
2552
|
-
function(key, device) {
|
|
2581
|
+
function (key, device) {
|
|
2553
2582
|
if (device == '') {
|
|
2554
2583
|
return 'disabled';
|
|
2555
2584
|
} else if (device.icon) {
|
|
@@ -2563,8 +2592,8 @@ function prepareExcludeDialog(excludeObj) {
|
|
|
2563
2592
|
}
|
|
2564
2593
|
|
|
2565
2594
|
function addExcludeDialog() {
|
|
2566
|
-
$(
|
|
2567
|
-
$(
|
|
2595
|
+
$('#excludemodaledit a.btn[name=\'save\']').unbind('click');
|
|
2596
|
+
$('#excludemodaledit a.btn[name=\'save\']').click(() => {
|
|
2568
2597
|
const exclude_id = $('#excludemodaledit').find('#exclude_target option:selected').val();
|
|
2569
2598
|
|
|
2570
2599
|
const ids = devices.map(el => el._id);
|
|
@@ -2647,7 +2676,7 @@ function showExclude() {
|
|
|
2647
2676
|
element.append(card);
|
|
2648
2677
|
});
|
|
2649
2678
|
|
|
2650
|
-
$(
|
|
2679
|
+
$('#exclude button[name=\'delete\']').click(function () {
|
|
2651
2680
|
const exclude_id = $(this).parents('.exclude')[0].id;
|
|
2652
2681
|
deleteExcludeConfirmation(exclude_id);
|
|
2653
2682
|
deleteExclude(exclude_id);
|
|
@@ -2655,14 +2684,13 @@ function showExclude() {
|
|
|
2655
2684
|
}
|
|
2656
2685
|
|
|
2657
2686
|
|
|
2658
|
-
|
|
2659
2687
|
function deleteExcludeConfirmation(id) {
|
|
2660
2688
|
const text = translateWord('Do you really want to delete exclude?');
|
|
2661
2689
|
$('#modaldelete').find('p').text(text);
|
|
2662
2690
|
//$('#forcediv').removeClass('hide');
|
|
2663
2691
|
$('#forcediv').addClass('hide');
|
|
2664
|
-
$(
|
|
2665
|
-
$(
|
|
2692
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
2693
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
2666
2694
|
deleteExclude(id);
|
|
2667
2695
|
});
|
|
2668
2696
|
$('#modaldelete').modal('open');
|
|
@@ -2703,7 +2731,7 @@ function doFilter(inputText) {
|
|
|
2703
2731
|
} else {
|
|
2704
2732
|
return room;
|
|
2705
2733
|
}
|
|
2706
|
-
}).filter((item)=>item != undefined).map((item)=>item.toLowerCase().trim());
|
|
2734
|
+
}).filter((item) => item != undefined).map((item) => item.toLowerCase().trim());
|
|
2707
2735
|
valid = rooms.includes(roomFilter);
|
|
2708
2736
|
} else {
|
|
2709
2737
|
valid = false;
|
|
@@ -2720,9 +2748,9 @@ function doFilter(inputText) {
|
|
|
2720
2748
|
function doSort() {
|
|
2721
2749
|
if (shuffleInstance) {
|
|
2722
2750
|
const sortOrder = $('#device-order-btn').text().toLowerCase();
|
|
2723
|
-
if (sortOrder
|
|
2751
|
+
if (sortOrder === 'default') {
|
|
2724
2752
|
shuffleInstance.sort({});
|
|
2725
|
-
} else if (sortOrder
|
|
2753
|
+
} else if (sortOrder === 'a-z') {
|
|
2726
2754
|
shuffleInstance.sort({
|
|
2727
2755
|
by: sortByTitle
|
|
2728
2756
|
});
|
|
@@ -2736,12 +2764,12 @@ function sortByTitle(element) {
|
|
|
2736
2764
|
|
|
2737
2765
|
function getDashCard(dev, groupImage) {
|
|
2738
2766
|
const title = dev.common.name,
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2767
|
+
id = dev._id,
|
|
2768
|
+
type = dev.common.type,
|
|
2769
|
+
img_src = (groupImage ? groupImage : dev.icon || dev.common.icon),
|
|
2770
|
+
isActive = !dev.common.deactivated,
|
|
2771
|
+
rooms = [],
|
|
2772
|
+
lang = systemLang || 'en';
|
|
2745
2773
|
const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
|
|
2746
2774
|
const rid = id.split('.').join('_');
|
|
2747
2775
|
const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
|
|
@@ -2750,46 +2778,46 @@ function getDashCard(dev, groupImage) {
|
|
|
2750
2778
|
battery_cls = getBatteryCls(dev.battery),
|
|
2751
2779
|
lqi_cls = getLQICls(dev.link_quality),
|
|
2752
2780
|
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>` : '',
|
|
2753
|
-
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>':''),
|
|
2754
|
-
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>`),
|
|
2755
|
-
permitJoinBtn = (isActive && dev.info && dev.info.device._type
|
|
2781
|
+
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>' : ''),
|
|
2782
|
+
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>`),
|
|
2783
|
+
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>' : '',
|
|
2756
2784
|
infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '',
|
|
2757
2785
|
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>` : '';
|
|
2758
|
-
const info = (dev.statesDef) ? dev.statesDef.map((stateDef)=>{
|
|
2786
|
+
const info = (dev.statesDef) ? dev.statesDef.map((stateDef) => {
|
|
2759
2787
|
const id = stateDef.id;
|
|
2760
2788
|
const sid = id.split('.').join('_');
|
|
2761
2789
|
let val = stateDef.val || '';
|
|
2762
|
-
if (stateDef.role
|
|
2763
|
-
val = `<span class="switch"><label><input type="checkbox" ${(val) ?
|
|
2764
|
-
} else if (stateDef.role
|
|
2765
|
-
val = `<span class="range-field dash"><input type="range" min="0" max="100" ${(val != undefined) ? `value="${val}"` :
|
|
2766
|
-
} else if (stateDef.role
|
|
2767
|
-
val = `<span class="range-field dash"><input type="range" min="150" max="500" ${(val != undefined) ? `value="${val}"` :
|
|
2768
|
-
} else if (stateDef.type
|
|
2790
|
+
if (stateDef.role === 'switch' && stateDef.write) {
|
|
2791
|
+
val = `<span class="switch"><label><input type="checkbox" ${(val) ? 'checked' : ''}><span class="lever"></span></label></span>`;
|
|
2792
|
+
} else if (stateDef.role === 'level.dimmer' && stateDef.write) {
|
|
2793
|
+
val = `<span class="range-field dash"><input type="range" min="0" max="100" ${(val != undefined) ? `value="${val}"` : ''} /></span>`;
|
|
2794
|
+
} else if (stateDef.role === 'level.color.temperature' && stateDef.write) {
|
|
2795
|
+
val = `<span class="range-field dash"><input type="range" min="150" max="500" ${(val != undefined) ? `value="${val}"` : ''} /></span>`;
|
|
2796
|
+
} else if (stateDef.type === 'boolean') {
|
|
2769
2797
|
const disabled = (stateDef.write) ? '' : 'disabled="disabled"';
|
|
2770
|
-
val = `<label class="dash"><input type="checkbox" ${(val == true) ?
|
|
2798
|
+
val = `<label class="dash"><input type="checkbox" ${(val == true) ? 'checked=\'checked\'' : ''} ${disabled}/><span></span></label>`;
|
|
2771
2799
|
} else if (stateDef.states && stateDef.write) {
|
|
2772
2800
|
let options;
|
|
2773
|
-
if(typeof stateDef.states ==
|
|
2801
|
+
if (typeof stateDef.states == 'string') {
|
|
2774
2802
|
const sts = stateDef.states.split(';');
|
|
2775
2803
|
options = sts.map((item) => {
|
|
2776
2804
|
const v = item.split(':');
|
|
2777
|
-
return `<option value="${v[0]}" ${(val == v[0]) ?
|
|
2805
|
+
return `<option value="${v[0]}" ${(val == v[0]) ? 'selected' : ''}>${v[1]}</option>`;
|
|
2778
2806
|
});
|
|
2779
2807
|
} else {
|
|
2780
2808
|
options = [];
|
|
2781
|
-
for(const [key, value] of Object.entries(stateDef.states)) {
|
|
2782
|
-
options.push(`<option value="${key}" ${(val == key) ?
|
|
2809
|
+
for (const [key, value] of Object.entries(stateDef.states)) {
|
|
2810
|
+
options.push(`<option value="${key}" ${(val == key) ? 'selected' : ''}>${value}</option>`);
|
|
2783
2811
|
}
|
|
2784
2812
|
}
|
|
2785
|
-
val = `<select class="browser-default enum" style="height: 16px; padding:
|
|
2813
|
+
val = `<select class="browser-default enum" style="color : white; background-color: grey; height: 16px; padding: 0; width: auto; display: inline-block">${options.join('')}</select>`;
|
|
2786
2814
|
} else {
|
|
2787
2815
|
val = `<span class="dash value">${val} ${(stateDef.unit) ? stateDef.unit : ''}</span>`;
|
|
2788
2816
|
}
|
|
2789
2817
|
return `<li><span class="label dash truncate">${stateDef.name}</span><span id=${sid} oid=${id} class="state">${val}</span></li>`;
|
|
2790
2818
|
}).join('') : '';
|
|
2791
2819
|
const dashCard = `
|
|
2792
|
-
<div class="card-content zcard ${isActive?'':'bg_red'}">
|
|
2820
|
+
<div class="card-content zcard ${isActive ? '' : 'bg_red'}">
|
|
2793
2821
|
<div class="flip" style="cursor: pointer">
|
|
2794
2822
|
<span class="top right small" style="border-radius: 50%">
|
|
2795
2823
|
${idleTime}
|
|
@@ -2802,7 +2830,7 @@ function getDashCard(dev, groupImage) {
|
|
|
2802
2830
|
<i class="left">${image}</i>
|
|
2803
2831
|
<div style="min-height:88px; font-size: 0.8em; height: 130px; overflow-y: auto" class="truncate">
|
|
2804
2832
|
<ul>
|
|
2805
|
-
${(isActive?info:'Device deactivated')}
|
|
2833
|
+
${(isActive ? info : 'Device deactivated')}
|
|
2806
2834
|
</ul>
|
|
2807
2835
|
</div>
|
|
2808
2836
|
<div class="footer right-align"></div>
|
|
@@ -2815,19 +2843,19 @@ function setDashStates(id, state) {
|
|
|
2815
2843
|
const devId = getDevId(id);
|
|
2816
2844
|
const dev = getDeviceByID(devId);
|
|
2817
2845
|
if (dev) {
|
|
2818
|
-
const stateDef = dev.statesDef.find((stateDef)=> stateDef.id == id);
|
|
2846
|
+
const stateDef = dev.statesDef.find((stateDef) => stateDef.id == id);
|
|
2819
2847
|
if (stateDef) {
|
|
2820
2848
|
const sid = id.split('.').join('_');
|
|
2821
|
-
if (stateDef.role
|
|
2822
|
-
$(`#${sid}`).find(
|
|
2823
|
-
} else if (stateDef.role
|
|
2824
|
-
$(`#${sid}`).find(
|
|
2825
|
-
} else if (stateDef.role
|
|
2826
|
-
$(`#${sid}`).find(
|
|
2849
|
+
if (stateDef.role === 'switch' && stateDef.write) {
|
|
2850
|
+
$(`#${sid}`).find('input[type=\'checkbox\']').prop('checked', state.val);
|
|
2851
|
+
} else if (stateDef.role === 'level.dimmer' && stateDef.write) {
|
|
2852
|
+
$(`#${sid}`).find('input[type=\'range\']').prop('value', state.val);
|
|
2853
|
+
} else if (stateDef.role === 'level.color.temperature' && stateDef.write) {
|
|
2854
|
+
$(`#${sid}`).find('input[type=\'range\']').prop('value', state.val);
|
|
2827
2855
|
} else if (stateDef.states && stateDef.write) {
|
|
2828
2856
|
$(`#${sid}`).find(`select option[value=${state.val}]`).prop('selected', true);
|
|
2829
|
-
} else if (stateDef.type
|
|
2830
|
-
$(`#${sid}`).find(
|
|
2857
|
+
} else if (stateDef.type === 'boolean') {
|
|
2858
|
+
$(`#${sid}`).find('input[type=\'checkbox\']').prop('checked', state.val);
|
|
2831
2859
|
} else {
|
|
2832
2860
|
$(`#${sid}`).find('.value').text(`${state.val} ${(stateDef.unit) ? stateDef.unit : ''}`);
|
|
2833
2861
|
}
|
|
@@ -2836,23 +2864,23 @@ function setDashStates(id, state) {
|
|
|
2836
2864
|
}
|
|
2837
2865
|
|
|
2838
2866
|
function hookControls() {
|
|
2839
|
-
$(
|
|
2867
|
+
$('input[type=\'checkbox\']').change(function (event) {
|
|
2840
2868
|
const val = $(this).is(':checked');
|
|
2841
|
-
const id = $(this).parents(
|
|
2869
|
+
const id = $(this).parents('.state').attr('oid');
|
|
2842
2870
|
sendTo(namespace, 'setState', {id: id, val: val}, function (data) {
|
|
2843
2871
|
//console.log(data);
|
|
2844
2872
|
});
|
|
2845
2873
|
});
|
|
2846
|
-
$(
|
|
2874
|
+
$('input[type=\'range\']').change(function (event) {
|
|
2847
2875
|
const val = $(this).val();
|
|
2848
|
-
const id = $(this).parents(
|
|
2876
|
+
const id = $(this).parents('.state').attr('oid');
|
|
2849
2877
|
sendTo(namespace, 'setState', {id: id, val: val}, function (data) {
|
|
2850
2878
|
//console.log(data);
|
|
2851
2879
|
});
|
|
2852
2880
|
});
|
|
2853
|
-
$(
|
|
2881
|
+
$('.state select').on('change', function () {
|
|
2854
2882
|
const val = $(this).val();
|
|
2855
|
-
const id = $(this).parents(
|
|
2883
|
+
const id = $(this).parents('.state').attr('oid');
|
|
2856
2884
|
sendTo(namespace, 'setState', {id: id, val: val}, function (data) {
|
|
2857
2885
|
//console.log(data);
|
|
2858
2886
|
});
|
|
@@ -2860,12 +2888,12 @@ function hookControls() {
|
|
|
2860
2888
|
}
|
|
2861
2889
|
|
|
2862
2890
|
function getIdleTime(value) {
|
|
2863
|
-
return (value) ? moment(new Date(value)).fromNow(true) :
|
|
2891
|
+
return (value) ? moment(new Date(value)).fromNow(true) : '';
|
|
2864
2892
|
}
|
|
2865
2893
|
|
|
2866
2894
|
function updateCardTimer() {
|
|
2867
2895
|
if (devices) {
|
|
2868
|
-
devices.forEach((dev)=>{
|
|
2896
|
+
devices.forEach((dev) => {
|
|
2869
2897
|
const id = dev._id;
|
|
2870
2898
|
if (id) {
|
|
2871
2899
|
const rid = id.split('.').join('_');
|
|
@@ -2882,9 +2910,7 @@ function updateDevice(id) {
|
|
|
2882
2910
|
showMessage(devs.error, _('Error'));
|
|
2883
2911
|
} else {
|
|
2884
2912
|
removeDevice(id);
|
|
2885
|
-
devs.forEach((dev)
|
|
2886
|
-
devices.push(dev);
|
|
2887
|
-
})
|
|
2913
|
+
devs.forEach(dev => devices.push(dev));
|
|
2888
2914
|
showDevices();
|
|
2889
2915
|
}
|
|
2890
2916
|
}
|
|
@@ -2902,21 +2928,21 @@ function removeDevice(id) {
|
|
|
2902
2928
|
}
|
|
2903
2929
|
|
|
2904
2930
|
function swapActive(id) {
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2931
|
+
const dev = getDeviceByID(id);
|
|
2932
|
+
if (dev && dev.common) {
|
|
2933
|
+
dev.common.deactivated = !(dev.common.deactivated);
|
|
2934
|
+
sendTo(namespace, 'setDeviceActivated', {id: id, deactivated: dev.common.deactivated}, function () {
|
|
2935
|
+
showDevices();
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2912
2938
|
}
|
|
2913
2939
|
|
|
2914
2940
|
function reconfigureDlg(id) {
|
|
2915
2941
|
const text = translateWord(`Do you really want to reconfigure device?`);
|
|
2916
2942
|
$('#modalreconfigure').find('p').text(text);
|
|
2917
|
-
$(
|
|
2918
|
-
$(
|
|
2919
|
-
reconfigureDevice(id
|
|
2943
|
+
$('#modalreconfigure a.btn[name=\'yes\']').unbind('click');
|
|
2944
|
+
$('#modalreconfigure a.btn[name=\'yes\']').click(() => {
|
|
2945
|
+
reconfigureDevice(id/*, force*/);
|
|
2920
2946
|
});
|
|
2921
2947
|
$('#modalreconfigure').modal('open');
|
|
2922
2948
|
Materialize.updateTextFields();
|