iobroker.zigbee 1.6.6 → 1.6.15

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/admin/admin.js CHANGED
@@ -129,6 +129,7 @@ function getGroupCard(dev) {
129
129
  title = dev.common.name,
130
130
  lq = '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>',
131
131
  rooms = [],
132
+ numid = parseInt(id.replace(namespace+'.group_', '')),
132
133
  lang = systemLang || 'en';
133
134
  for (const r in dev.rooms) {
134
135
  if (dev.rooms[r].hasOwnProperty(lang)) {
@@ -137,16 +138,17 @@ function getGroupCard(dev) {
137
138
  rooms.push(dev.rooms[r]);
138
139
  }
139
140
  }
141
+ devGroups[numid] = dev;
140
142
  const room = rooms.join(',') || '&nbsp';
141
143
  let memberCount = 0;
142
144
  let info = `<div style="min-height:88px; font-size: 0.8em; height: 98px; overflow-y: auto" class="truncate">
143
145
  <ul>`;
144
- info = info.concat(`<li><span class="labelinfo">Group ${id.replace(namespace+'.group_', '')}</span></li>`);
146
+ info = info.concat(`<li><span class="labelinfo">Group ${numid}</span></li>`);
145
147
  if (dev.memberinfo === undefined) {
146
148
  info = info.concat(`<li><span class="labelinfo">No devices in group</span></li>`);
147
149
  } else {
148
150
  for (let m=0;m < dev.memberinfo.length; m++) {
149
- info = info.concat(`<li><span class="labelinfo">${dev.memberinfo[m].name}</span><span> ...${dev.memberinfo[m].ieee.slice(-4)}</span></li>`);
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>`);
150
152
  }
151
153
  memberCount = (dev.memberinfo.length<8?dev.memberinfo.length:7);
152
154
  };
@@ -199,6 +201,7 @@ function getCard(dev) {
199
201
  type_url = (dev.common.type ? sanitizeModelParameter(dev.common.type) : 'unknown'),
200
202
  img_src = dev.icon || dev.common.icon,
201
203
  rooms = [],
204
+ isActive = (dev.common.deactivated ? false : true),
202
205
  lang = systemLang || 'en';
203
206
  for (const r in dev.rooms) {
204
207
  if (dev.rooms[r].hasOwnProperty(lang)) {
@@ -213,11 +216,11 @@ function getCard(dev) {
213
216
  const modelUrl = (!type) ? '' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${type}</a>`;
214
217
  const image = `<img src="${img_src}" width="80px" onerror="this.onerror=null;this.src='img/unavailable.png';">`,
215
218
  nwk = (dev.info && dev.info.device) ? dev.info.device._networkAddress : undefined,
216
- battery_cls = getBatteryCls(dev.battery),
219
+ battery_cls = (isActive ? getBatteryCls(dev.battery):''),
217
220
  lqi_cls = getLQICls(dev.link_quality),
218
- battery = (dev.battery) ? `<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>` : '',
219
- lq = (dev.link_quality) > 0 ? `<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>` : '',
220
- status = (dev.link_quality) > 0 ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : `<div class="col tool"><i class="material-icons icon-black">leak_remove</i></div>`,
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>` : '',
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>` : '',
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>`:''),
221
224
  info = `<div style="min-height:88px; font-size: 0.8em" class="truncate">
222
225
  <ul>
223
226
  <li><span class="labelinfo">ieee:</span><span>0x${id.replace(namespace+'.', '')}</span></li>
@@ -227,10 +230,11 @@ function getCard(dev) {
227
230
  </ul>
228
231
  </div>`,
229
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>' : '',
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>`,
230
234
  infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '';
231
235
  const dashCard = getDashCard(dev);
232
236
  const card = `<div id="${id}" class="device">
233
- <div class="card hoverable flipable">
237
+ <div class="card hoverable flipable ${isActive?'':'bg_red'}">
234
238
  <div class="front face">${dashCard}</div>
235
239
  <div class="back face">
236
240
  <div class="card-content zcard">
@@ -258,6 +262,10 @@ function getCard(dev) {
258
262
  <button name="edit" class="right btn-flat btn-small">
259
263
  <i class="material-icons icon-green">edit</i>
260
264
  </button>
265
+ <button name="reconfigure" class="right btn-flat btn-small tooltipped" title="Reconfigure">
266
+ <i class="material-icons icon-red">sync</i>
267
+ </button>
268
+ ${deactBtn}
261
269
  ${permitJoinBtn}
262
270
  </div>
263
271
  </div>
@@ -348,25 +356,96 @@ function cleanConfirmation() {
348
356
  Materialize.updateTextFields();
349
357
  }
350
358
 
359
+ function EndPointIDfromEndPoint(ep)
360
+ {
361
+ if (ep && ep.deviceIeeeAddress && ep.ID)
362
+ return `${ep.deviceIeeeAddress}:${ep.ID}`;
363
+ return 'unidentified';
364
+ }
365
+
351
366
  function editName(id, name) {
367
+ console.log('editName called with '+name);
352
368
  const dev = devices.find((d) => d._id == id);
353
369
  $('#modaledit').find("input[id='d_name']").val(name);
354
- if (dev.info && dev.info.device._type == 'Router') {
355
- list2select('#d_groups', groups, devGroups[id] || []);
356
- $('#modaledit').find('.input-field.groups').removeClass('hide');
357
- } else {
358
- $('#modaledit').find('.input-field.groups').addClass('hide');
359
- }
370
+ // if (dev.info && dev.info.device._type == 'Router') {
371
+ const groupables = [];
372
+ if (dev && dev.info && dev.info.endpoints) {
373
+ for (const ep of dev.info.endpoints) {
374
+ if (ep.inputClusters.includes(4)) {
375
+ groupables.push({ epid:EndPointIDfromEndPoint(ep), ep:ep, memberOf:[]});
376
+ }
377
+ }
378
+ }
379
+ const numEP = groupables.length;
380
+ // console.log('groupables: '+JSON.stringify(groupables));
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) {
386
+ // go through all the groups. Find the ones to list for each groupable
387
+ if (numEP == 1) {
388
+ $('#modaledit').find('.endpointid').addClass('hide');
389
+ }
390
+ else {
391
+ $('#modaledit').find('.endpointid').removeClass('hide');
392
+ }
393
+ for (const d of devices) {
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
+ }
402
+ }
403
+ }
404
+ }
405
+ }
406
+ }
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
+ }
416
+ }
417
+ // } else {
418
+ // $('#modaledit').find('.input-field.endpoints').addClass('hide');
419
+ // $('#modaledit').find('.input-field.groups').addClass('hide');
420
+ // }
360
421
  $("#modaledit a.btn[name='save']").unbind('click');
361
422
  $("#modaledit a.btn[name='save']").click(() => {
362
- const newName = $('#modaledit').find("input[id='d_name']").val(),
363
- newGroups = $('#d_groups').val();
364
- updateDev(id, newName, newGroups);
423
+ const newName = $('#modaledit').find("input[id='d_name']").val();
424
+ const groupsbyid = {};
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
+ }
432
+ console.log('grpid ' + JSON.stringify(groupsbyid));
433
+ updateDev(id, newName, groupsbyid);
365
434
  });
366
435
  $('#modaledit').modal('open');
367
436
  Materialize.updateTextFields();
368
437
  }
369
438
 
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;
447
+ }
448
+
370
449
  function deleteDevice(id, force) {
371
450
  sendTo(namespace, 'deleteDevice', {id: id, force: force}, function (msg) {
372
451
  closeWaitingDialog();
@@ -438,7 +517,6 @@ function showDevices() {
438
517
  }
439
518
  return 0;
440
519
  });
441
- devGroups = {};
442
520
  for (let i=0;i < devices.length; i++) {
443
521
  const d = devices[i];
444
522
  if (!d.info) {
@@ -455,7 +533,7 @@ function showDevices() {
455
533
  } else {
456
534
  //if (d.groups && d.info && d.info.device._type == "Router") {
457
535
  if (d.groups) {
458
- devGroups[d._id] = d.groups;
536
+ // devGroups[d._id] = d.groups;
459
537
  if (typeof d.groups.map == 'function') {
460
538
  d.groupNames = d.groups.map(item=>{
461
539
  return groups[item] || '';
@@ -529,7 +607,7 @@ function showDevices() {
529
607
  const dev_block = $(this).parents('div.device'),
530
608
  id = dev_block.attr('id').replace(namespace+'.group_', ''),
531
609
  name = getDevName(dev_block);
532
- editGroupName(id, name);
610
+ editGroupName(id, name, false);
533
611
  });
534
612
  $("button.btn-floating[name='join']").click(function() {
535
613
  const dev_block = $(this).parents('div.device');
@@ -548,6 +626,14 @@ function showDevices() {
548
626
  $("a.btn-flat[name='close']").click((e) => {
549
627
  closeReval(e);
550
628
  });
629
+ $(".card-reveal-buttons button[name='reconfigure']").click(function() {
630
+ const dev_block = $(this).parents('div.device');
631
+ reconfigureDlg(getDevId(dev_block));
632
+ });
633
+ $(".card-reveal-buttons button[name='swapactive']").click(function() {
634
+ const dev_block = $(this).parents('div.device');
635
+ swapActive(getDevId(dev_block));
636
+ });
551
637
 
552
638
  showNetworkMap(devices, map);
553
639
  translateAll();
@@ -762,13 +848,14 @@ function load(settings, onChange) {
762
848
  });
763
849
 
764
850
  $('#add_group').click(function() {
851
+ // showGroupList(true);
765
852
  const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
766
- editGroupName(maxind+1, '');
853
+ editGroupName(maxind+1, 'Group ' + maxind+1, true);
767
854
  });
768
855
  $('#add_grp_btn').click(function() {
856
+ // showGroupList(true);
769
857
  const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
770
- editGroupName(maxind+1, '');
771
- getDevices();
858
+ editGroupName(maxind+1, 'Group ' + maxind+1, true);
772
859
  });
773
860
 
774
861
  $(document).ready(function() {
@@ -1706,7 +1793,7 @@ function showGroups() {
1706
1793
  $("a.btn-floating[name='groupedit']").click(function() {
1707
1794
  const index = $(this).attr('id'),
1708
1795
  name = groups[index];
1709
- editGroupName(index, name);
1796
+ editGroupName(index, name, false);
1710
1797
  });
1711
1798
  $("a.btn-floating[name='groupdelete']").click(function() {
1712
1799
  const index = $(this).attr('id'),
@@ -1715,8 +1802,35 @@ function showGroups() {
1715
1802
  });
1716
1803
  }
1717
1804
 
1718
- function editGroupName(id, name) {
1805
+ function editGroupName(id, name, isnew) {
1806
+ //const dev = devices.find((d) => d._id == id);
1807
+ //console.log('devices: '+ JSON.stringify(devices));
1808
+ const groupables = [];
1809
+ for (const d of devices) {
1810
+ if (d && d.info && d.info.endpoints) {
1811
+ for (const ep of d.info.endpoints) {
1812
+ if (ep.inputClusters.includes(4))
1813
+ {
1814
+ groupables.push(ep);
1815
+ }
1816
+ }
1817
+ }
1818
+ //console.log('device ' + JSON.stringify(d));
1819
+ }
1820
+
1719
1821
  //var text = 'Enter new name for "'+name+'" ('+id+')?';
1822
+ if (isnew) {
1823
+ $('#groupedit').find('.editgroup').addClass('hide');
1824
+ $('#groupedit').find('.addgroup').removeClass('hide');
1825
+ $('#groupedit').find('.input-field.members').addClass('hide');
1826
+ $('#groupedit').find('.input-field.groupid').removeClass('hide');
1827
+ }
1828
+ else {
1829
+ $('#groupedit').find('.editgroup').removeClass('hide');
1830
+ $('#groupedit').find('.addgroup').addClass('hide');
1831
+ $('#groupedit').find('.input-field.members').removeClass('hide');
1832
+ $('#groupedit').find('.input-field.groupid').addClass('hide');
1833
+ }
1720
1834
  $('#groupedit').find("input[id='g_index']").val(id);
1721
1835
  $('#groupedit').find("input[id='g_name']").val(name);
1722
1836
  $("#groupedit a.btn[name='save']").unbind('click');
@@ -1725,7 +1839,7 @@ function editGroupName(id, name) {
1725
1839
  newName = $('#groupedit').find("input[id='g_name']").val();
1726
1840
  updateGroup(id, newId, newName);
1727
1841
  // showGroups();
1728
- getDevices();
1842
+ // getDevices();
1729
1843
  });
1730
1844
  $('#groupedit').modal('open');
1731
1845
  Materialize.updateTextFields();
@@ -1739,7 +1853,7 @@ function deleteGroupConfirmation(id, name) {
1739
1853
  $("#modaldelete a.btn[name='yes']").click(() => {
1740
1854
  deleteGroup(id);
1741
1855
  // showGroups();
1742
- getDevices();
1856
+ // getDevices();
1743
1857
  });
1744
1858
  $('#modaldelete').modal('open');
1745
1859
  }
@@ -1747,12 +1861,22 @@ function deleteGroupConfirmation(id, name) {
1747
1861
  function updateGroup(id, newId, newName) {
1748
1862
  delete groups[id];
1749
1863
  groups[newId] = newName;
1750
- sendTo(namespace, 'renameGroup', { id: newId, name: newName} );
1864
+ sendTo(namespace, 'renameGroup', { id: newId, name: newName}, function(msg) {
1865
+ if (msg && ms.error) {
1866
+ showMessage(msg.error, _('Error'));
1867
+ }
1868
+ getDevices();
1869
+ });
1751
1870
  }
1752
1871
 
1753
1872
  function deleteGroup(id) {
1754
1873
  delete groups[id];
1755
- sendTo(namespace, 'deleteGroup', id );
1874
+ sendTo(namespace, 'deleteGroup', id , function(msg) {
1875
+ if (msg && ms.error) {
1876
+ showMessage(msg.error, _('Error'));
1877
+ }
1878
+ getDevices();
1879
+ });
1756
1880
  }
1757
1881
 
1758
1882
  function updateDev(id, newName, newGroups) {
@@ -1760,6 +1884,24 @@ function updateDev(id, newName, newGroups) {
1760
1884
  if (dev && dev.common.name != newName) {
1761
1885
  renameDevice(id, newName);
1762
1886
  }
1887
+ const keys = Object.keys(newGroups)
1888
+ if (keys && keys.length)
1889
+ {
1890
+ sendTo(namespace, 'updateGroupMembership', { id: id, groups: newGroups }, function (msg) {
1891
+ closeWaitingDialog();
1892
+ if (msg && msg.error) {
1893
+ showMessage(msg.error, _('Error'));
1894
+ }
1895
+ else {
1896
+ // save dev-groups on success
1897
+ dev.groups = newGroups;
1898
+ }
1899
+ showDevices();
1900
+ });
1901
+ showWaitingDialog('Updating group memberships', 10);
1902
+
1903
+ }
1904
+ /*
1763
1905
  if (dev.info.device._type == 'Router') {
1764
1906
  const oldGroups = devGroups[id] || [];
1765
1907
  if (oldGroups.toString() != newGroups.toString()) {
@@ -1776,6 +1918,7 @@ function updateDev(id, newName, newGroups) {
1776
1918
  });
1777
1919
  }
1778
1920
  }
1921
+ */
1779
1922
  }
1780
1923
 
1781
1924
  function resetConfirmation() {
@@ -2170,7 +2313,7 @@ function genDevInfo(device) {
2170
2313
  const dev = (device && device.info) ? device.info.device : undefined;
2171
2314
  const mapped = (device && device.info) ? device.info.mapped : undefined;
2172
2315
  if (!dev) return `<div class="truncate">No info</div>`;
2173
- const genRow = function(name, value) {
2316
+ const genRow = function(name, value, refresh) {
2174
2317
  if (value === undefined) {
2175
2318
  return '';
2176
2319
  } else {
@@ -2234,7 +2377,7 @@ function genDevInfo(device) {
2234
2377
  ${genRow('date code', dev._dateCode)}
2235
2378
  ${genRow('build', dev._softwareBuildID)}
2236
2379
  ${genRow('interviewed', dev._interviewCompleted)}
2237
- ${genRow('configured', (dev.meta.configured === 1))}
2380
+ ${genRow('configured', (dev.meta.configured === 1), true)}
2238
2381
  </ul>
2239
2382
  </div>
2240
2383
  </div>
@@ -2250,17 +2393,60 @@ function showDevInfo(id){
2250
2393
  $('#modaldevinfo').modal('open');
2251
2394
  }
2252
2395
 
2396
+ function showGroupList(show){
2397
+ const htmlsections = [];
2398
+ for (const groupid in devGroups) {
2399
+ const dev = devGroups[groupid];
2400
+ const grpname = (dev.common && dev.common.name?dev.common.name:'Group '+groupid);
2401
+ const selectables = [];
2402
+ const members = [];
2403
+ if (dev && dev.memberinfo)
2404
+ {
2405
+ selectables.push(`<select id="members_${groupid}" multiple>`)
2406
+ for (let m=0;m<dev.memberinfo.length; m++) {
2407
+ members.push(`${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (${dev.memberinfo[m].ieee})`)
2408
+ selectables.push(`<option value="${m}">${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (...${dev.memberinfo[m].ieee.slice(-4)})</option>`);
2409
+ }
2410
+ selectables.push('</select>');
2411
+ }
2412
+ htmlsections.push(`
2413
+ <div class="row">
2414
+ <div class="col s4 m4 l4">
2415
+ <h5>${grpname}<h5>
2416
+ </div>
2417
+ <div class=col s7 m7 l7">
2418
+ ${members.join('<br>')}
2419
+ </div>
2420
+ </div>
2421
+ `);
2422
+ }
2423
+
2424
+ $('#grouplist').html(htmlsections.join(''));
2425
+ $('#add').click(function() {
2426
+ const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a,b) => a>b ? a : b, 0));
2427
+ editGroupName(maxind+1, 'Group ' + maxind+1, true);
2428
+ showGroupList(false);
2429
+ });
2430
+
2431
+ $("#modalgrouplist a.btn[name='save']").unbind('click');
2432
+ $("#modalgrouplist a.btn[name='save']").click(() => {
2433
+ });
2434
+ if (show) $('#modalgrouplist').modal('open');
2435
+ }
2436
+
2437
+ let waitingTimeout, waitingInt;
2253
2438
 
2254
2439
  function showWaitingDialog(text, timeout){
2255
2440
  let countDown = timeout;
2256
- const waitingInt = setInterval(function() {
2441
+ waitingInt = setInterval(function() {
2257
2442
  countDown -= 1;
2258
2443
  const percent = 100-100*countDown/timeout;
2259
2444
  $('#waiting_progress_line').css('width', `${percent}%`);
2260
2445
  }, 1000);
2261
- setTimeout(function() {
2446
+ waitingTimeout = setTimeout(function() {
2262
2447
  $('#waiting_progress_line').css('width', `0%`);
2263
2448
  clearTimeout(waitingInt);
2449
+ clearTimeout(waitingTimeout);
2264
2450
  $('#modalWaiting').modal('close');
2265
2451
  }, timeout*1000);
2266
2452
  $('#waiting_message').text(text);
@@ -2268,6 +2454,8 @@ function showWaitingDialog(text, timeout){
2268
2454
  }
2269
2455
 
2270
2456
  function closeWaitingDialog(){
2457
+ if (waitingInt) clearTimeout(waitingInt);
2458
+ if (waitingTimeout) clearTimeout(waitingTimeout);
2271
2459
  $('#modalWaiting').modal('close');
2272
2460
  }
2273
2461
 
@@ -2550,6 +2738,7 @@ function getDashCard(dev, groupImage) {
2550
2738
  id = dev._id,
2551
2739
  type = dev.common.type,
2552
2740
  img_src = (groupImage ? groupImage: dev.icon || dev.common.icon),
2741
+ isActive = (dev.common.deactivated ? false : true),
2553
2742
  rooms = [],
2554
2743
  lang = systemLang || 'en';
2555
2744
  const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
@@ -2559,12 +2748,12 @@ function getDashCard(dev, groupImage) {
2559
2748
  nwk = (dev.info && dev.info.device) ? dev.info.device._networkAddress : undefined,
2560
2749
  battery_cls = getBatteryCls(dev.battery),
2561
2750
  lqi_cls = getLQICls(dev.link_quality),
2562
- battery = (dev.battery) ? `<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>` : '',
2563
- lq = (dev.link_quality) > 0 ? `<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>` : '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>',
2564
- status = (dev.link_quality) > 0 ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : (groupImage ? '': `<div class="col tool"><i class="material-icons icon-black">leak_remove</i></div>`),
2565
- 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>' : '',
2751
+ battery = (dev.battery && isActive) ? `<div class="col tool"><i id="${rid}_battery_icon" class="material-icons ${battery_cls}">battery_std</i><div id="${rid}_battery" class="center" style="font-size:0.7em">${dev.battery}</div></div>` : '',
2752
+ lq = (dev.link_quality > 0 && isActive) ? `<div class="col tool"><i id="${rid}_link_quality_icon" class="material-icons ${lqi_cls}">network_check</i><div id="${rid}_link_quality" class="center" style="font-size:0.7em">${dev.link_quality}</div></div>` : (isActive ? '<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>':''),
2753
+ status = (dev.link_quality > 0 && isActive) ? `<div class="col tool"><i class="material-icons icon-green">check_circle</i></div>` : (groupImage || !isActive ? '': `<div class="col tool"><i class="material-icons icon-black">leak_remove</i></div>`),
2754
+ permitJoinBtn = (isActive && dev.info && dev.info.device._type == '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>' : '',
2566
2755
  infoBtn = (nwk) ? `<button name="info" class="left btn-flat btn-small"><i class="material-icons icon-blue">info</i></button>` : '',
2567
- idleTime = (dev.link_quality_lc > 0) ? `<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>` : '';
2756
+ 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>` : '';
2568
2757
  const info = (dev.statesDef) ? dev.statesDef.map((stateDef)=>{
2569
2758
  const id = stateDef.id;
2570
2759
  const sid = id.split('.').join('_');
@@ -2591,7 +2780,7 @@ function getDashCard(dev, groupImage) {
2591
2780
  return `<li><span class="label dash truncate">${stateDef.name}</span><span id=${sid} oid=${id} class="state">${val}</span></li>`;
2592
2781
  }).join('') : '';
2593
2782
  const dashCard = `
2594
- <div class="card-content zcard">
2783
+ <div class="card-content zcard ${isActive?'':'bg_red'}">
2595
2784
  <div class="flip" style="cursor: pointer">
2596
2785
  <span class="top right small" style="border-radius: 50%">
2597
2786
  ${idleTime}
@@ -2604,7 +2793,7 @@ function getDashCard(dev, groupImage) {
2604
2793
  <i class="left">${image}</i>
2605
2794
  <div style="min-height:88px; font-size: 0.8em; height: 130px; overflow-y: auto" class="truncate">
2606
2795
  <ul>
2607
- ${info}
2796
+ ${(isActive?info:'Device deactivated')}
2608
2797
  </ul>
2609
2798
  </div>
2610
2799
  <div class="footer right-align"></div>
@@ -2702,3 +2891,36 @@ function removeDevice(id) {
2702
2891
  }
2703
2892
  }
2704
2893
  }
2894
+
2895
+ function swapActive(id) {
2896
+ const dev = getDeviceByID(id);
2897
+ if (dev && dev.common) {
2898
+ dev.common.deactivated = !(dev.common.deactivated)
2899
+ sendTo(namespace, 'setDeviceActivated', {id: id, deactivated: dev.common.deactivated}, function () {
2900
+ showDevices();
2901
+ });
2902
+ }
2903
+ }
2904
+
2905
+ function reconfigureDlg(id) {
2906
+ const text = translateWord(`Do you really want to reconfigure device?`);
2907
+ $('#modalreconfigure').find('p').text(text);
2908
+ $("#modalreconfigure a.btn[name='yes']").unbind('click');
2909
+ $("#modalreconfigure a.btn[name='yes']").click(() => {
2910
+ reconfigureDevice(id, force);
2911
+ });
2912
+ $('#modalreconfigure').modal('open');
2913
+ Materialize.updateTextFields();
2914
+ }
2915
+
2916
+ function reconfigureDevice(id) {
2917
+ sendTo(namespace, 'reconfigure', {id: id}, function (msg) {
2918
+ closeWaitingDialog();
2919
+ if (msg) {
2920
+ if (msg.error) {
2921
+ showMessage(msg.error, _('Error'));
2922
+ }
2923
+ }
2924
+ });
2925
+ showWaitingDialog('Device is being reconfigure', 30);
2926
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file