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