iobroker.zigbee 2.0.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/admin/admin.js +281 -102
- package/admin/index_m.html +168 -124
- package/admin/tab_m.html +7 -3
- package/docs/de/img/Bild30.png +0 -0
- package/docs/de/img/Bild38.png +0 -0
- package/docs/de/img/Info.png +0 -0
- package/docs/de/img/Zigbee_config_de.jpg +0 -0
- package/docs/de/img/battery.png +0 -0
- package/docs/de/img/debug.png +0 -0
- package/docs/de/img/delete.png +0 -0
- package/docs/de/img/disconnected.png +0 -0
- package/docs/de/img/edit_grp.png +0 -0
- package/docs/de/img/edit_image.png +0 -0
- package/docs/de/img/grp_nok.png +0 -0
- package/docs/de/img/grp_ok.png +0 -0
- package/docs/de/img/on_off.png +0 -0
- package/docs/de/img/reconfigure.png +0 -0
- package/docs/de/readme.md +52 -43
- package/docs/en/img/Zigbee_config_en.png +0 -0
- package/docs/en/img/Zigbee_pairing_en.png +0 -0
- package/docs/en/readme.md +71 -66
- package/io-package.json +18 -18
- package/lib/DeviceDebug.js +2 -1
- package/lib/commands.js +165 -33
- package/lib/devices.js +2 -2
- package/lib/exposes.js +8 -30
- package/lib/localConfig.js +2 -2
- package/lib/seriallist.js +9 -2
- package/lib/statescontroller.js +132 -38
- package/lib/utils.js +41 -11
- package/lib/zbDeviceConfigure.js +9 -2
- package/lib/zigbeecontroller.js +120 -94
- package/main.js +131 -70
- package/package.json +8 -8
- package/docs/en/img/Bild23.png +0 -0
- package/docs/en/img/Bild25.png +0 -0
- package/docs/en/img/Bild26.png +0 -0
- package/docs/en/img/Bild4.png +0 -0
- package/docs/en/img/Bild9.png +0 -0
package/README.md
CHANGED
|
@@ -152,6 +152,13 @@ You can thank the authors by these links:
|
|
|
152
152
|
|
|
153
153
|
-----------------------------------------------------------------------------------------------------
|
|
154
154
|
## Changelog
|
|
155
|
+
### 3.0.0 (2025-04-08)
|
|
156
|
+
* (asgothian) Breaking change: Start of zigbee subsystem requires configuration entry !!!
|
|
157
|
+
* (asgothian) Hardware configuration panel
|
|
158
|
+
* (asgothian) Update for external converter - detect /dist/ subfolder
|
|
159
|
+
* (asgothian) Update device image: use of icons defined in external converter (beta)
|
|
160
|
+
*
|
|
161
|
+
|
|
155
162
|
### 2.0.5 (2025-03-25)
|
|
156
163
|
* (asgothian) ZHC 23.6.0
|
|
157
164
|
* (asgothian) ZH 3.3.x
|
|
@@ -177,7 +184,6 @@ You can thank the authors by these links:
|
|
|
177
184
|
* (asgothian) fix Adapter-Checker notes
|
|
178
185
|
* (asgothian) improve base64 image detection
|
|
179
186
|
* (asgothian) removed unused adaptert objects (info.groups, excludes) from adapter config
|
|
180
|
-
*
|
|
181
187
|
|
|
182
188
|
### 2.0.2 (2025-03-02)
|
|
183
189
|
* (asgothian) expose generation with expose function requiring a device. (Issue #1842)
|
package/admin/admin.js
CHANGED
|
@@ -32,7 +32,9 @@ let devices = [],
|
|
|
32
32
|
shuffleInstance,
|
|
33
33
|
errorData = [],
|
|
34
34
|
debugMessages = {},
|
|
35
|
-
debugInLog = true
|
|
35
|
+
debugInLog = true,
|
|
36
|
+
nvRamBackup = {},
|
|
37
|
+
isHerdsmanRunning = false;
|
|
36
38
|
const dbgMsgfilter = new Set();
|
|
37
39
|
const dbgMsghide = new Set();
|
|
38
40
|
const updateCardInterval = setInterval(updateCardTimer, 6000);
|
|
@@ -55,11 +57,12 @@ const networkOptions = {
|
|
|
55
57
|
|
|
56
58
|
const savedSettings = [
|
|
57
59
|
'port', 'panID', 'channel', 'disableLed', 'countDown', 'groups', 'extPanID', 'precfgkey', 'transmitPower',
|
|
58
|
-
'adapterType', 'debugHerdsman', 'disableBackup', 'disablePing', 'external', 'startWithInconsistent',
|
|
60
|
+
'adapterType', 'debugHerdsman', 'disableBackup', 'disablePing', 'external', 'startWithInconsistent',
|
|
61
|
+
'warnOnDeviceAnnouncement', 'baudRate', 'flowCTRL', 'autostart'
|
|
59
62
|
];
|
|
60
63
|
|
|
61
64
|
function getDeviceByID(ID) {
|
|
62
|
-
return devices.find((devInfo) => {
|
|
65
|
+
if (devices) return devices.find((devInfo) => {
|
|
63
66
|
try {
|
|
64
67
|
return devInfo._id == ID;
|
|
65
68
|
} catch (e) {
|
|
@@ -380,6 +383,31 @@ function deleteConfirmation(id, name) {
|
|
|
380
383
|
Materialize.updateTextFields();
|
|
381
384
|
}
|
|
382
385
|
|
|
386
|
+
function deleteNvBackupConfirmation() {
|
|
387
|
+
const text = translateWord('Do you really want to the NV Backup data ?');
|
|
388
|
+
$('#modaldelete').find('p').text(text);
|
|
389
|
+
$('#force').prop('checked', false);
|
|
390
|
+
$('#forcediv').addClass('hide');
|
|
391
|
+
$('#modaldelete a.btn[name=\'yes\']').unbind('click');
|
|
392
|
+
$('#modaldelete a.btn[name=\'yes\']').click(() => {
|
|
393
|
+
//const force = $('#force').prop('checked');
|
|
394
|
+
showWaitingDialog('Attempting to delete nvBackup.json', 60000);
|
|
395
|
+
sendTo(namespace, 'deleteNVBackup', {}, function (msg) {
|
|
396
|
+
closeWaitingDialog();
|
|
397
|
+
if (msg) {
|
|
398
|
+
if (msg.error) {
|
|
399
|
+
showMessage(msg.error, _('Error'));
|
|
400
|
+
} else {
|
|
401
|
+
getDevices();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
$('#modaldelete').modal('open');
|
|
407
|
+
Materialize.updateTextFields();
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
|
|
383
411
|
function cleanConfirmation() {
|
|
384
412
|
const text = translateWord('Do you really want to remove orphaned states?');
|
|
385
413
|
$('#modalclean').find('p').text(text);
|
|
@@ -782,18 +810,27 @@ function getCoordinatorInfo() {
|
|
|
782
810
|
sendTo(namespace, 'getCoordinatorInfo', {}, function (msg) {
|
|
783
811
|
if (msg) {
|
|
784
812
|
if (msg.error) {
|
|
785
|
-
|
|
813
|
+
errorData.push(msg.error);
|
|
814
|
+
isHerdsmanRunning = false;
|
|
815
|
+
updateStartButton();
|
|
786
816
|
} else {
|
|
787
817
|
coordinatorinfo = msg;
|
|
818
|
+
isHerdsmanRunning = true;
|
|
819
|
+
updateStartButton()
|
|
788
820
|
}
|
|
789
821
|
}
|
|
790
822
|
});
|
|
791
823
|
}
|
|
824
|
+
|
|
792
825
|
function checkDebugDevice(id) {
|
|
793
|
-
|
|
826
|
+
// returns: -1: debug not set
|
|
827
|
+
// 0: debug set explicitly
|
|
828
|
+
// > 0: debug set by pattern.
|
|
829
|
+
if (!debugDevices) return -1;
|
|
830
|
+
if (debugDevices.indexOf(id) > -1) return 0 // debug set
|
|
794
831
|
for (const addressPart of debugDevices) {
|
|
795
832
|
if (typeof id === 'string' && id.includes(addressPart)) {
|
|
796
|
-
return debugDevices.indexOf(addressPart)+1;
|
|
833
|
+
return debugDevices.indexOf(addressPart)+1; // debug set by pattern (>0)
|
|
797
834
|
}
|
|
798
835
|
}
|
|
799
836
|
return -1;
|
|
@@ -1067,8 +1104,10 @@ function getDebugMessages() {
|
|
|
1067
1104
|
|
|
1068
1105
|
function getDevices() {
|
|
1069
1106
|
getCoordinatorInfo();
|
|
1070
|
-
sendTo(namespace, '
|
|
1107
|
+
sendTo(namespace, 'getDevices', {}, function (msg) {
|
|
1071
1108
|
if (msg) {
|
|
1109
|
+
devices = msg.devices ? msg.devices : [];
|
|
1110
|
+
// check if stashed error messages are sent alongside
|
|
1072
1111
|
if (msg.clean)
|
|
1073
1112
|
$('#state_cleanup_btn').removeClass('hide');
|
|
1074
1113
|
else
|
|
@@ -1077,23 +1116,28 @@ function getDevices() {
|
|
|
1077
1116
|
$('#show_errors_btn').removeClass('hide');
|
|
1078
1117
|
errorData = msg.errors;
|
|
1079
1118
|
}
|
|
1080
|
-
else
|
|
1119
|
+
else {
|
|
1081
1120
|
$('#show_errors_btn').addClass('hide');
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
//check if debug messages are sent alongside
|
|
1124
|
+
if (msg && typeof (msg.debugDevices == 'array')) {
|
|
1125
|
+
debugDevices = msg.debugDevices;
|
|
1126
|
+
console.warn('debug devices is sent')
|
|
1127
|
+
}
|
|
1128
|
+
else
|
|
1129
|
+
debugDevices = [];
|
|
1130
|
+
if (debugMessages.byId) {
|
|
1131
|
+
debugMessages.byId = msg;
|
|
1132
|
+
if (msg) displayDebugMessages(debugMessages)
|
|
1133
|
+
}
|
|
1093
1134
|
if (msg.error) {
|
|
1094
|
-
|
|
1135
|
+
errorData.push(msg.error);
|
|
1136
|
+
isHerdsmanRunning = false;
|
|
1137
|
+
updateStartButton();
|
|
1095
1138
|
} else {
|
|
1096
|
-
|
|
1139
|
+
isHerdsmanRunning = true;
|
|
1140
|
+
updateStartButton();
|
|
1097
1141
|
showDevices();
|
|
1098
1142
|
getDebugMessages();
|
|
1099
1143
|
getExclude();
|
|
@@ -1128,8 +1172,12 @@ function getMap() {
|
|
|
1128
1172
|
$('#refresh').removeClass('disabled');
|
|
1129
1173
|
if (msg) {
|
|
1130
1174
|
if (msg.error) {
|
|
1131
|
-
|
|
1175
|
+
errorData.push(msg.error);
|
|
1176
|
+
isHerdsmanRunning = false;
|
|
1177
|
+
updateStartButton();
|
|
1132
1178
|
} else {
|
|
1179
|
+
isHerdsmanRunning = true;
|
|
1180
|
+
updateStartButton();
|
|
1133
1181
|
if (msg.errors.length > 0 && $('#errorCollectionOn').is(':checked')) {
|
|
1134
1182
|
showMessage(msg.errors.join('<p>'), 'Map generation messages');
|
|
1135
1183
|
}
|
|
@@ -1149,14 +1197,24 @@ function getRandomExtPanID()
|
|
|
1149
1197
|
return bytes.join('');
|
|
1150
1198
|
}
|
|
1151
1199
|
|
|
1200
|
+
function getRandomChannel()
|
|
1201
|
+
{
|
|
1202
|
+
const channels = [11,15,20,25]
|
|
1203
|
+
return channels[Math.floor(Math.random() * 4)];
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
|
|
1152
1207
|
|
|
1153
1208
|
// the function loadSettings has to exist ...
|
|
1154
1209
|
|
|
1155
1210
|
function load(settings, onChange) {
|
|
1156
|
-
if (settings.
|
|
1211
|
+
if (settings.extPanID === undefined || settings.extPanID == '') {
|
|
1212
|
+
settings.channel = getRandomChannel();
|
|
1213
|
+
}
|
|
1214
|
+
if (settings.panID === undefined || settings.panID == 0) {
|
|
1157
1215
|
settings.panID = Math.floor(Math.random() * 10000);
|
|
1158
1216
|
}
|
|
1159
|
-
if (settings.extPanID === undefined) {
|
|
1217
|
+
if (settings.extPanID === undefined || settings.extPanID == '') {
|
|
1160
1218
|
settings.extPanID = getRandomExtPanID();
|
|
1161
1219
|
}
|
|
1162
1220
|
// fix for previous wrong value
|
|
@@ -1167,9 +1225,6 @@ function load(settings, onChange) {
|
|
|
1167
1225
|
if (settings.precfgkey === undefined) {
|
|
1168
1226
|
settings.precfgkey = '01030507090B0D0F00020406080A0C0D';
|
|
1169
1227
|
}
|
|
1170
|
-
if (settings.channel === undefined) {
|
|
1171
|
-
settings.channel = 11;
|
|
1172
|
-
}
|
|
1173
1228
|
if (settings.disablePing === undefined) {
|
|
1174
1229
|
settings.disablePing = false;
|
|
1175
1230
|
}
|
|
@@ -1179,6 +1234,7 @@ function load(settings, onChange) {
|
|
|
1179
1234
|
if (settings.baudRate === undefined) {
|
|
1180
1235
|
settings.baudRate = 115200;
|
|
1181
1236
|
}
|
|
1237
|
+
if (settings.autostart === undefined) settings.autostart = false;
|
|
1182
1238
|
|
|
1183
1239
|
// example: select elements with id=key and class=value and insert value
|
|
1184
1240
|
for (const key in settings) {
|
|
@@ -1190,10 +1246,12 @@ function load(settings, onChange) {
|
|
|
1190
1246
|
if (value.attr('type') === 'checkbox') {
|
|
1191
1247
|
value.prop('checked', settings[key]).change(function () {
|
|
1192
1248
|
onChange();
|
|
1249
|
+
validateNVRamBackup(false, key)
|
|
1193
1250
|
});
|
|
1194
1251
|
} else {
|
|
1195
1252
|
value.val(settings[key]).change(function () {
|
|
1196
1253
|
onChange();
|
|
1254
|
+
validateNVRamBackup(false, key)
|
|
1197
1255
|
}).keyup(function () {
|
|
1198
1256
|
$(this).trigger('change');
|
|
1199
1257
|
});
|
|
@@ -1206,6 +1264,7 @@ function load(settings, onChange) {
|
|
|
1206
1264
|
//dialog = new MatDialog({EndingTop: '50%'});
|
|
1207
1265
|
getDevices();
|
|
1208
1266
|
getNamedColors();
|
|
1267
|
+
readNVRamBackup(false);
|
|
1209
1268
|
//getDebugMessages();
|
|
1210
1269
|
//getMap();
|
|
1211
1270
|
//addCard();
|
|
@@ -1213,6 +1272,36 @@ function load(settings, onChange) {
|
|
|
1213
1272
|
// Signal to admin, that no changes yet
|
|
1214
1273
|
onChange(false);
|
|
1215
1274
|
|
|
1275
|
+
$('#test-btn').click(function () {
|
|
1276
|
+
console.warn(`isHerdsmanRunning: ${isHerdsmanRunning}`)
|
|
1277
|
+
if (!isHerdsmanRunning) {
|
|
1278
|
+
const port = $('#port.value').val();
|
|
1279
|
+
console.warn(`port is ${port}`)
|
|
1280
|
+
showWaitingDialog(`Trying to connect to ${port}`, 300);
|
|
1281
|
+
sendTo(namespace, 'testConnection', { address:port }, function(msg) {
|
|
1282
|
+
console.warn(`send to returned with ${JSON.stringify(msg)}`);
|
|
1283
|
+
closeWaitingDialog();
|
|
1284
|
+
if (msg) {
|
|
1285
|
+
if (msg.error) {
|
|
1286
|
+
showMessage(msg.error, _('Error'));
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
})
|
|
1290
|
+
}
|
|
1291
|
+
else {
|
|
1292
|
+
showMessage('function unavailable while herdsman is running', _('Error'))
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1296
|
+
$('#readNVRam-btn').click(function() {
|
|
1297
|
+
readNVRamBackup(true);
|
|
1298
|
+
})
|
|
1299
|
+
// test start commands
|
|
1300
|
+
$('#show_test_run').click(function () {
|
|
1301
|
+
console.warn(`isHerdsmanRunning: ${isHerdsmanRunning}`)
|
|
1302
|
+
doTestStart(!isHerdsmanRunning);
|
|
1303
|
+
});
|
|
1304
|
+
|
|
1216
1305
|
$('#state_cleanup_btn').click(function () {
|
|
1217
1306
|
cleanConfirmation();
|
|
1218
1307
|
});
|
|
@@ -1241,6 +1330,10 @@ function load(settings, onChange) {
|
|
|
1241
1330
|
resetConfirmation();
|
|
1242
1331
|
});
|
|
1243
1332
|
|
|
1333
|
+
$('#deleteNVRam-btn').click(function () {
|
|
1334
|
+
deleteNvBackupConfirmation();
|
|
1335
|
+
});
|
|
1336
|
+
|
|
1244
1337
|
$('#viewconfig').click(function () {
|
|
1245
1338
|
showViewConfig();
|
|
1246
1339
|
});
|
|
@@ -1248,6 +1341,9 @@ function load(settings, onChange) {
|
|
|
1248
1341
|
$('#scan').click(function () {
|
|
1249
1342
|
showChannels();
|
|
1250
1343
|
});
|
|
1344
|
+
$('#scan_t').click(function () {
|
|
1345
|
+
showChannels();
|
|
1346
|
+
});
|
|
1251
1347
|
|
|
1252
1348
|
sendTo(namespace, 'getGroups', {}, function (data) {
|
|
1253
1349
|
groups = data.groups;
|
|
@@ -1274,6 +1370,10 @@ function load(settings, onChange) {
|
|
|
1274
1370
|
}
|
|
1275
1371
|
});
|
|
1276
1372
|
|
|
1373
|
+
$('#hardware').click(function() {
|
|
1374
|
+
validateNVRamBackup(false);
|
|
1375
|
+
});
|
|
1376
|
+
|
|
1277
1377
|
$(document).ready(function () {
|
|
1278
1378
|
$('.modal').modal({
|
|
1279
1379
|
startingTop: '30%',
|
|
@@ -1331,6 +1431,7 @@ function showMessages() {
|
|
|
1331
1431
|
data = mess + '\n' + data;
|
|
1332
1432
|
}
|
|
1333
1433
|
$('#stdout').text(data);
|
|
1434
|
+
$('#stdout_t').text(messages.join('\n'));
|
|
1334
1435
|
}
|
|
1335
1436
|
|
|
1336
1437
|
function showPairingProcess() {
|
|
@@ -1344,6 +1445,41 @@ function showPairingProcess() {
|
|
|
1344
1445
|
Materialize.updateTextFields();
|
|
1345
1446
|
}
|
|
1346
1447
|
|
|
1448
|
+
function doTestStart(start) {
|
|
1449
|
+
updateStartButton(true);
|
|
1450
|
+
if (start) {
|
|
1451
|
+
const ovr = { extPanID:$('#extPanID.value').val(),
|
|
1452
|
+
panID: $('#PanID.value').val(),
|
|
1453
|
+
channel: $('#channel.value').val(),
|
|
1454
|
+
port: $('#port.value').val(),
|
|
1455
|
+
adapterType: $('#adapterType.value').val(),
|
|
1456
|
+
baudRate: $('#baudRate.value').val(),
|
|
1457
|
+
precfgkey: $('#precfgkey.value').val(),
|
|
1458
|
+
flowCTRL: $('#flowCTRL.value').prop('checked')
|
|
1459
|
+
};
|
|
1460
|
+
// $('#testStartStart').addClass('disabled');
|
|
1461
|
+
messages = [];
|
|
1462
|
+
sendTo(namespace, 'testConnect', { start:true, zigbeeOptions:ovr }, function(msg) {
|
|
1463
|
+
if (msg) {
|
|
1464
|
+
if (msg.status)
|
|
1465
|
+
$('#testStartStop').removeClass('disabled');
|
|
1466
|
+
else
|
|
1467
|
+
$('#testStartStart').removeClass('disabled');
|
|
1468
|
+
}
|
|
1469
|
+
})
|
|
1470
|
+
}
|
|
1471
|
+
else {
|
|
1472
|
+
//$('#testStartStop').addClass('disabled');
|
|
1473
|
+
sendTo(namespace, 'testConnect', { start:false }, function(msg) {
|
|
1474
|
+
if (msg) {
|
|
1475
|
+
if (msg.status) $('#testStartStart').removeClass('disabled');
|
|
1476
|
+
else $('#testStartStop').removeClass('disabled');
|
|
1477
|
+
}
|
|
1478
|
+
})
|
|
1479
|
+
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1347
1483
|
// ... and the function save has to exist.
|
|
1348
1484
|
// you have to make sure the callback is called with the settings object as first param!
|
|
1349
1485
|
|
|
@@ -1370,6 +1506,36 @@ function getDevId(adapterDevId) {
|
|
|
1370
1506
|
return adapterDevId.split('.').slice(0, 3).join('.');
|
|
1371
1507
|
}
|
|
1372
1508
|
|
|
1509
|
+
|
|
1510
|
+
function updateStartButton(block) {
|
|
1511
|
+
if (block) {
|
|
1512
|
+
$('#show_test_run').addClass('disabled');
|
|
1513
|
+
$('#reset-btn').addClass('disabled');
|
|
1514
|
+
$('#deleteNVRam-btn').addClass('disabled');
|
|
1515
|
+
$('#ErrorNotificationBtn').removeClass('hide')
|
|
1516
|
+
$('#ErrorNotificationBtn').removeClass('blinking')
|
|
1517
|
+
$('#ErrorNotificationIcon').removeClass('icon-red')
|
|
1518
|
+
$('#ErrorNotificationIcon').addClass('icon-orange')
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
if (isHerdsmanRunning)
|
|
1522
|
+
{
|
|
1523
|
+
$('#ErrorNotificationBtn').addClass('hide')
|
|
1524
|
+
$('#ErrorNotificationBtn').removeClass('blinking');
|
|
1525
|
+
$('#show_test_run').removeClass('disabled');
|
|
1526
|
+
$('#deleteNVRam-btn').removeClass('disabled');
|
|
1527
|
+
$('#reset-btn').removeClass('disabled');
|
|
1528
|
+
}
|
|
1529
|
+
else {
|
|
1530
|
+
$('#ErrorNotificationIcon').addClass('icon-red')
|
|
1531
|
+
$('#ErrorNotificationIcon').removeClass('icon-orange')
|
|
1532
|
+
$('#ErrorNotificationBtn').removeClass('hide')
|
|
1533
|
+
$('#ErrorNotificationBtn').addClass('blinking');
|
|
1534
|
+
$('#show_test_run').removeClass('disabled');
|
|
1535
|
+
$('#deleteNVRam-btn').removeClass('disabled');
|
|
1536
|
+
$('#reset-btn').addClass('disabled');
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1373
1539
|
// subscribe to changes
|
|
1374
1540
|
socket.emit('subscribe', namespace + '.*');
|
|
1375
1541
|
socket.emit('subscribeObjects', namespace + '.*');
|
|
@@ -1404,6 +1570,14 @@ socket.on('stateChange', function (id, state) {
|
|
|
1404
1570
|
else {
|
|
1405
1571
|
messages.push(state.val);
|
|
1406
1572
|
showMessages();
|
|
1573
|
+
if (state.val.startsWith('Zigbee-Herdsman started successfully')) {
|
|
1574
|
+
isHerdsmanRunning = true;
|
|
1575
|
+
updateStartButton();
|
|
1576
|
+
}
|
|
1577
|
+
if (state.val.startsWith('herdsman stopped') || state.val.startsWith('Error herdsman')) {
|
|
1578
|
+
isHerdsmanRunning = false;
|
|
1579
|
+
updateStartButton();
|
|
1580
|
+
}
|
|
1407
1581
|
}
|
|
1408
1582
|
} else {
|
|
1409
1583
|
const devId = getDevId(id);
|
|
@@ -2215,31 +2389,6 @@ function list2select(selector, list, selected, getText, getKey, getData) {
|
|
|
2215
2389
|
element.select();
|
|
2216
2390
|
}
|
|
2217
2391
|
|
|
2218
|
-
/*
|
|
2219
|
-
function showGroups() {
|
|
2220
|
-
$('#groups_table').find('.group').remove();
|
|
2221
|
-
if (!groups) return;
|
|
2222
|
-
const element = $('#groups_table');
|
|
2223
|
-
for (const j in groups) {
|
|
2224
|
-
if (groups.hasOwnProperty(j)) {
|
|
2225
|
-
element.append(`<tr id="group_${j}" class="group"><td>${j}</td><td><div>${groups[j]}<span class="right">` +
|
|
2226
|
-
`<a id="${j}" name="groupedit" class="waves-effect green btn-floating"><i class="material-icons">edit</i></a>` +
|
|
2227
|
-
`<a id="${j}" name="groupdelete" class="waves-effect red btn-floating"><i class="material-icons">delete</i></a></span></div></td></tr>`);
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
$('a.btn-floating[name=\'groupedit\']').click(function () {
|
|
2231
|
-
const index = $(this).attr('id'),
|
|
2232
|
-
name = groups[index];
|
|
2233
|
-
editGroupName(index, name, false);
|
|
2234
|
-
});
|
|
2235
|
-
$('a.btn-floating[name=\'groupdelete\']').click(function () {
|
|
2236
|
-
const index = $(this).attr('id'),
|
|
2237
|
-
name = groups[index];
|
|
2238
|
-
deleteGroupConfirmation(index, name);
|
|
2239
|
-
});
|
|
2240
|
-
}
|
|
2241
|
-
*/
|
|
2242
|
-
|
|
2243
2392
|
function editGroup(id, name) {
|
|
2244
2393
|
const grp = devGroups[id];
|
|
2245
2394
|
let info = '';
|
|
@@ -2843,48 +2992,6 @@ function showDevInfo(id) {
|
|
|
2843
2992
|
$('#modaldevinfo').modal('open');
|
|
2844
2993
|
}
|
|
2845
2994
|
|
|
2846
|
-
/*
|
|
2847
|
-
function showGroupList(show) {
|
|
2848
|
-
const htmlsections = [];
|
|
2849
|
-
for (const groupid in devGroups) {
|
|
2850
|
-
const dev = devGroups[groupid];
|
|
2851
|
-
const grpname = (dev.common && dev.common.name ? dev.common.name : 'Group ' + groupid);
|
|
2852
|
-
const selectables = [];
|
|
2853
|
-
const members = [];
|
|
2854
|
-
if (dev && dev.memberinfo) {
|
|
2855
|
-
selectables.push(`<select id="members_${groupid}" multiple>`);
|
|
2856
|
-
for (let m = 0; m < dev.memberinfo.length; m++) {
|
|
2857
|
-
members.push(`${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (${dev.memberinfo[m].ieee})`);
|
|
2858
|
-
selectables.push(`<option value="${m}">${dev.memberinfo[m].device}.${dev.memberinfo[m].epid} (...${dev.memberinfo[m].ieee.slice(-4)})</option>`);
|
|
2859
|
-
}
|
|
2860
|
-
selectables.push('</select>');
|
|
2861
|
-
}
|
|
2862
|
-
htmlsections.push(`
|
|
2863
|
-
<div class="row">
|
|
2864
|
-
<div class="col s4 m4 l4">
|
|
2865
|
-
<h5>${grpname}<h5>
|
|
2866
|
-
</div>
|
|
2867
|
-
<div class=col s7 m7 l7">
|
|
2868
|
-
${members.join('<br>')}
|
|
2869
|
-
</div>
|
|
2870
|
-
</div>
|
|
2871
|
-
`);
|
|
2872
|
-
}
|
|
2873
|
-
|
|
2874
|
-
$('#grouplist').html(htmlsections.join(''));
|
|
2875
|
-
$('#add').click(function () {
|
|
2876
|
-
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
2877
|
-
addGroup(maxind + 1, 'Group ' + maxind + 1, true);
|
|
2878
|
-
showGroupList(false);
|
|
2879
|
-
});
|
|
2880
|
-
|
|
2881
|
-
$('#modalgrouplist a.btn[name=\'save\']').unbind('click');
|
|
2882
|
-
$('#modalgrouplist a.btn[name=\'save\']').click(() => {
|
|
2883
|
-
});
|
|
2884
|
-
if (show) $('#modalgrouplist').modal('open');
|
|
2885
|
-
}
|
|
2886
|
-
*/
|
|
2887
|
-
|
|
2888
2995
|
let waitingTimeout, waitingInt;
|
|
2889
2996
|
|
|
2890
2997
|
function showWaitingDialog(text, timeout) {
|
|
@@ -3354,14 +3461,17 @@ function updateCardTimer() {
|
|
|
3354
3461
|
}
|
|
3355
3462
|
|
|
3356
3463
|
function updateDevice(id) {
|
|
3357
|
-
sendTo(namespace, 'getDevice', {id: id}, function (
|
|
3358
|
-
if (
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3464
|
+
sendTo(namespace, 'getDevice', {id: id}, function (msg) {
|
|
3465
|
+
if (msg) {
|
|
3466
|
+
const devs = msg.devices;
|
|
3467
|
+
if (devs) {
|
|
3468
|
+
if (devs.error) {
|
|
3469
|
+
showMessage(devs.error, _('Error'));
|
|
3470
|
+
} else {
|
|
3471
|
+
removeDevice(id);
|
|
3472
|
+
devs.forEach(dev => devices.push(dev));
|
|
3473
|
+
showDevices();
|
|
3474
|
+
}
|
|
3365
3475
|
}
|
|
3366
3476
|
}
|
|
3367
3477
|
});
|
|
@@ -3409,3 +3519,72 @@ function reconfigureDevice(id) {
|
|
|
3409
3519
|
});
|
|
3410
3520
|
showWaitingDialog('Device is being reconfigure', 30);
|
|
3411
3521
|
}
|
|
3522
|
+
|
|
3523
|
+
const warnLevel = {
|
|
3524
|
+
extPanID : function(v) { return !(v && v.toLowerCase().trim()!='dddddddddddddddd')},
|
|
3525
|
+
channel: function(v) { const num = parseInt(v); return !(num==11 || num==15 || num==20 || num==25)},
|
|
3526
|
+
}
|
|
3527
|
+
const validatableKeys = ['channel', 'precfgkey', 'extPanID', 'panID'];
|
|
3528
|
+
|
|
3529
|
+
function validateConfigData(key, val) {
|
|
3530
|
+
if (validatableKeys.indexOf(key) < 0 || !val) return;
|
|
3531
|
+
if (warnLevel[key]) {
|
|
3532
|
+
if (warnLevel[key](val)) {
|
|
3533
|
+
console.warn(`warning set for ${key} (${val})`)
|
|
3534
|
+
$(`#${key}_ALERT`).removeClass('hide')
|
|
3535
|
+
} else $(`#${key}_ALERT`).addClass('hide')
|
|
3536
|
+
}
|
|
3537
|
+
if (nvRamBackup[key]) {
|
|
3538
|
+
console.warn(`value of ${key} is ${val} (${nvRamBackup[key]})`);
|
|
3539
|
+
if (val == nvRamBackup[key])
|
|
3540
|
+
{
|
|
3541
|
+
console.warn(`ok set for ${key} (${val})`)
|
|
3542
|
+
$(`#${key}_OK`).removeClass('hide')
|
|
3543
|
+
$(`#${key}_NOK`).addClass('hide')
|
|
3544
|
+
}
|
|
3545
|
+
else
|
|
3546
|
+
{
|
|
3547
|
+
console.warn(`nok set for ${key} (${val})`)
|
|
3548
|
+
$(`#${key}_OK`).addClass('hide')
|
|
3549
|
+
$(`#${key}_NOK`).removeClass('hide')
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
else {
|
|
3553
|
+
console.warn(`noval set for ${key} (${val})`)
|
|
3554
|
+
$(`#${key}_OK`).addClass('hide')
|
|
3555
|
+
$(`#${key}_NOK`).addClass('hide')
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
function validateNVRamBackup(update, src) {
|
|
3560
|
+
console.warn('validateNVRam');
|
|
3561
|
+
const validatedKeys = src ? [src] : validatableKeys;
|
|
3562
|
+
const validator = {};
|
|
3563
|
+
for (const key of validatedKeys) {
|
|
3564
|
+
const value = $('#' + key + '.value');
|
|
3565
|
+
if (nvRamBackup[key] && update) {
|
|
3566
|
+
if (value.attr('type') === 'checkbox') {
|
|
3567
|
+
value.prop('checked', nvRamBackup[key]);
|
|
3568
|
+
} else {
|
|
3569
|
+
value.val(nvRamBackup[key])
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
validateConfigData(key, value.val());
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
|
|
3576
|
+
|
|
3577
|
+
function readNVRamBackup(update) {
|
|
3578
|
+
console.warn('read nvRam')
|
|
3579
|
+
sendTo(namespace, 'readNVRam', {}, function(msg) {
|
|
3580
|
+
if (msg) {
|
|
3581
|
+
if (msg.error && update) {
|
|
3582
|
+
showMessages(msg.error, _('Error'));
|
|
3583
|
+
delete msg.error;
|
|
3584
|
+
}
|
|
3585
|
+
nvRamBackup = msg;
|
|
3586
|
+
validateNVRamBackup(update)
|
|
3587
|
+
}
|
|
3588
|
+
});
|
|
3589
|
+
|
|
3590
|
+
}
|