iobroker.zigbee 3.1.5 → 3.1.6
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 +4 -0
- package/admin/admin.js +210 -124
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/index_m.html +14 -0
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/io-package.json +14 -14
- package/lib/commands.js +52 -33
- package/lib/developer.js +0 -0
- package/lib/exposes.js +3 -2
- package/lib/localConfig.js +8 -0
- package/lib/ota.js +0 -0
- package/lib/zbDeviceConfigure.js +0 -0
- package/lib/zigbeecontroller.js +4 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -152,6 +152,10 @@ You can thank the authors by these links:
|
|
|
152
152
|
|
|
153
153
|
-----------------------------------------------------------------------------------------------------
|
|
154
154
|
## Changelog
|
|
155
|
+
### 3.1.6 (2025-10-21)
|
|
156
|
+
* (asgothian) Bugfixes
|
|
157
|
+
*
|
|
158
|
+
|
|
155
159
|
### 3.1.5 (2025-10-04)
|
|
156
160
|
* (asgothian) Bugfixes
|
|
157
161
|
* (asgothian) ZHC25.36.0
|
package/admin/admin.js
CHANGED
|
@@ -9,6 +9,7 @@ const Materialize = (typeof M !== 'undefined') ? M : Materialize,
|
|
|
9
9
|
namespace = 'zigbee.' + instance,
|
|
10
10
|
namespaceLen = namespace.length;
|
|
11
11
|
let devices = [],
|
|
12
|
+
models = [],
|
|
12
13
|
debugDevices = [],
|
|
13
14
|
messages = [],
|
|
14
15
|
map = {},
|
|
@@ -17,6 +18,7 @@ let devices = [],
|
|
|
17
18
|
network,
|
|
18
19
|
networkEvents,
|
|
19
20
|
responseCodes = false,
|
|
21
|
+
localConfigData = {},
|
|
20
22
|
groups = {},
|
|
21
23
|
devGroups = {}, // eslint-disable-line prefer-const
|
|
22
24
|
binding = [],
|
|
@@ -180,7 +182,11 @@ function getLQICls(value) {
|
|
|
180
182
|
|
|
181
183
|
function sanitizeModelParameter(parameter) {
|
|
182
184
|
const replaceByUnderscore = /[\s/]/g;
|
|
183
|
-
|
|
185
|
+
try {
|
|
186
|
+
return parameter.replace(replaceByUnderscore, '_');
|
|
187
|
+
}
|
|
188
|
+
catch {}
|
|
189
|
+
return parameter;
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
/////
|
|
@@ -189,88 +195,156 @@ function sanitizeModelParameter(parameter) {
|
|
|
189
195
|
//
|
|
190
196
|
////
|
|
191
197
|
|
|
198
|
+
const LocalDataDisplayValues = {
|
|
199
|
+
unfoldedModels : {}, // { plug01: {devices: true/false, options: true/false}}
|
|
200
|
+
unfoldedDevices : {}, // { 0xdeadbeefdeadbeef: true/false}
|
|
201
|
+
buttonSet: new Set(),
|
|
202
|
+
showModels: true,
|
|
203
|
+
}
|
|
192
204
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const devicesByModel = {};
|
|
196
|
-
for (const dev of data) {
|
|
197
|
-
const modelID = dev.info?.mapped?.model || dev.info.device.modelZigbee || dev.info.device.name || 'unknown';
|
|
198
|
-
if (devicesByModel[modelID])
|
|
199
|
-
devicesByModel[modelID].devices.push(dev);
|
|
200
|
-
else devicesByModel[modelID] = {devices:[dev], icon:dev.common.icon};
|
|
201
|
-
}
|
|
202
|
-
console.warn(JSON.stringify(devicesByModel));
|
|
205
|
+
|
|
206
|
+
function getModelData(data, models) {
|
|
203
207
|
const Html = [];
|
|
204
208
|
// Html.push(`<ul class="collapsible">`);
|
|
205
|
-
|
|
206
|
-
for (const
|
|
207
|
-
const model =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
209
|
+
const s = new Set();
|
|
210
|
+
for (const k of Object.keys(models)) {
|
|
211
|
+
const model = models[k];
|
|
212
|
+
const key = model.model.model;
|
|
213
|
+
console.warn(`getmodeldata: model is ${key}, sO: ${JSON.stringify(model.setOptions)}`);
|
|
214
|
+
const numOptions = Object.keys(model.setOptions).length;
|
|
215
|
+
const foldData = LocalDataDisplayValues.unfoldedModels[k] || { devices:false, options:false};
|
|
216
|
+
let numrows = 1;
|
|
217
|
+
if (foldData.devices) numrows += model.devices.length;
|
|
218
|
+
if (numOptions > 0) numrows += 1;
|
|
219
|
+
if (foldData.options) numrows += numOptions;
|
|
220
|
+
//const numrows = (foldData.devices ? model.devices.length : 0) + (foldData.options ? numOptions : 0) + numOptions > 0 ? 2 : 1;
|
|
221
|
+
console.warn(`numrows is ${numrows} with ${model.devices.length} ${foldData.devices ? 'shown' : 'hidden'} devices and ${numOptions} options ${foldData.options ? 'shown' : 'hidden'}`);
|
|
222
|
+
const d_btn_name = `d_toggle_${k}`;
|
|
223
|
+
const e_btn_name = `m_edit_${k}`;
|
|
224
|
+
const d_btn_tip = `fold / unfold devices of ${key}`;
|
|
225
|
+
const e_btn_tip = `edit model ${key}`;
|
|
226
|
+
const d_btn = btnParam(d_btn_name, d_btn_tip, foldData.devices ? 'expand_less' : 'expand_more', false);
|
|
227
|
+
const e_btn = btnParam(e_btn_name, e_btn_tip, 'edit', 'green', false)
|
|
228
|
+
LocalDataDisplayValues.buttonSet.add(d_btn_name);
|
|
229
|
+
LocalDataDisplayValues.buttonSet.add(e_btn_name);
|
|
230
|
+
Html.push(`<tr id="datarowodd"><td rowspan="${numrows}"><img src = ${model.icon} alt="" width="80" height="auto"></td><td colspan="2">Devices of Model ${key}</td><td>${d_btn} ${e_btn}</td></tr>`)
|
|
231
|
+
let cnt = 0;
|
|
232
|
+
if (foldData.devices) {
|
|
233
|
+
for (const dev of model.devices) {
|
|
234
|
+
let devieee = dev._id.replace(`${namespace}.`, '');
|
|
235
|
+
|
|
236
|
+
if (devieee == undefined) devieee = 'unknown' + cnt++;
|
|
237
|
+
const bn = `d_edit_${devieee}`
|
|
238
|
+
Html.push(`<tr id="datarowopt"><td>${devieee}</td><td>${dev.common.name}</td><td>${btnParam(bn, 'edit '+ devieee, 'edit', 'lime', true)}</td></tr>`)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (numOptions > 0) {
|
|
242
|
+
const o_btn_name = `o_toggle_${k}`;
|
|
243
|
+
const o_btn_tip = `fold / unfold options for Model ${key}`;
|
|
244
|
+
LocalDataDisplayValues.buttonSet.add(o_btn_name);
|
|
245
|
+
Html.push(`<tr id="dataroweven"></td><td colspan="2">Options for ${key}</td><td>${btnParam(o_btn_name, o_btn_tip, foldData.options ? 'expand_less' : 'expand_more')}</td></tr>`)
|
|
246
|
+
if (foldData.options) {
|
|
247
|
+
for (const key of Object.keys(model.setOptions)) {
|
|
248
|
+
Html.push(`<tr id="dataroweven"><td>${key}</td><td ${model.setOptions[key] === undefined ? 'id="datared">"not set on model"' : '>'+model.setOptions[key]}</td><td> </td></tr>`)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
}
|
|
218
254
|
return Html;
|
|
219
255
|
}
|
|
256
|
+
|
|
257
|
+
function btnParam(id, tooltip, icon, color, disabled) {
|
|
258
|
+
return `<a id="${id}" class="btn-floating waves-effect waves-light right ${color ? color : 'blue'} ${disabled ? 'disabled ' : ''}tooltipped center-align hoverable translateT" title="${tooltip}"><i class="material-icons large">${icon}</i></a>`;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
|
|
220
262
|
function getDeviceData(deviceList, withIcon) {
|
|
221
|
-
const Html = [
|
|
263
|
+
const Html = [];
|
|
222
264
|
for (const dev of deviceList) {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
265
|
+
const rowspan = dev.options ? Object.keys(dev.options).length + 2 : 2;
|
|
266
|
+
const iconLink = `<img src=${dev.common.icon} class="dev_list">`;
|
|
267
|
+
const devieee = dev._id.replace(`${namespace}.`, '');
|
|
268
|
+
const o_btn_name = `do_toggle_${devieee}`;
|
|
269
|
+
const o_btn_tip = `fold / unfold options for ${devieee}`;
|
|
270
|
+
LocalDataDisplayValues.buttonSet.add(o_btn_name);
|
|
271
|
+
const bn = `f_edit_${devieee}`
|
|
272
|
+
LocalDataDisplayValues.buttonSet.add(bn);
|
|
273
|
+
|
|
274
|
+
Html.push(`<tr id="datarowodd"><td rowspan="${rowspan}">${iconLink}</td><td colspan="2">${dev.common.name} (${devieee})</td><td>${btnParam(o_btn_name, o_btn_tip, LocalDataDisplayValues.unfoldedDevices ? 'do_not_disturb' : 'add_circle')}</td></tr>`);
|
|
275
|
+
Html.push(`<tr id="dataroweven"><td colspan="2">Device flags</td><td>${btnParam(bn, 'edit flags','edit')}</td></tr>`);
|
|
276
|
+
//console.warn(`dev is ${JSON.stringify(dev)}`);
|
|
277
|
+
if (dev.options && LocalDataDisplayValues.unfoldedDevices[devieee]) {
|
|
228
278
|
for (const o of dev.options) {
|
|
229
|
-
|
|
279
|
+
const bn = `o_edit_${devieee}.${o.key}`
|
|
280
|
+
LocalDataDisplayValues.buttonSet.add(bn);
|
|
281
|
+
Html.push(`<tr id="datarowopt"><td>${o.key}></td><td>${o.value}</td><td>${btnParam(bn, 'edit flags','edit')}</td></tr>`);
|
|
230
282
|
}
|
|
231
|
-
Html.push(`</div>`);
|
|
232
283
|
}
|
|
233
|
-
Html.push(`</div>`)
|
|
234
284
|
}
|
|
235
|
-
Html.push(`</div>`)
|
|
236
285
|
return Html;
|
|
237
286
|
}
|
|
238
|
-
function getGlobalOptionData() {
|
|
239
|
-
return ['No Data Yet'];
|
|
240
|
-
}
|
|
241
287
|
|
|
242
288
|
function showLocalData() {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const
|
|
289
|
+
LocalDataDisplayValues.buttonSet.clear();
|
|
290
|
+
const ModelHtml = getModelData(devices, models);
|
|
291
|
+
const DeviceHtml = getDeviceData(devices);
|
|
292
|
+
const sm = LocalDataDisplayValues.showModels;
|
|
293
|
+
const dmtoggle = btnParam('t_all_models', sm ? 'fold Models / show Devices' : 'fold Devices / show Models', !sm ? 'developer_board' : 'devices_other')
|
|
246
294
|
|
|
247
|
-
|
|
248
|
-
Html
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
Html.push (`<div class="collapsible-body">
|
|
260
|
-
<span>${getDeviceData(devices, true).join('')}</span>
|
|
261
|
-
</div>`);
|
|
262
|
-
Html.push ('</li><li>')
|
|
263
|
-
Html.push (`<div class="collapsible-header">
|
|
264
|
-
Global Options
|
|
265
|
-
</div>`);
|
|
266
|
-
Html.push (`<div class="collapsible-body">
|
|
267
|
-
<span>${getGlobalOptionData(devices).join('')}</span>
|
|
268
|
-
</div>`);
|
|
269
|
-
Html.push ('</li>')
|
|
270
|
-
Html.push (`</ul>`);
|
|
295
|
+
const RowSpan = sm ? ModelHtml.length +2 : DeviceHtml.length + 2;
|
|
296
|
+
const Html = [];
|
|
297
|
+
if (sm) {
|
|
298
|
+
Html.push(`<table style="width:100%"><tr id="datatable"><th rowspan="${RowSpan}"> </th><th colspan=3>Model Data</th><th>${dmtoggle}</th><th rowspan="${RowSpan}"> </th></tr>`)
|
|
299
|
+
Html.push(ModelHtml.join(''));
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
Html.push(`<table style="width:100%"><tr id="datatable"><th rowspan="${RowSpan}"> </th><th colspan=3>Device Data</th><th>${dmtoggle}</th><th rowspan="${RowSpan}"> </th></tr>`)
|
|
303
|
+
Html.push(DeviceHtml.join(''));
|
|
304
|
+
}
|
|
305
|
+
Html.push(`<tr id="datatable"><td colspan="4">Statistics</td></tr>`)
|
|
306
|
+
Html.push('</table>');
|
|
271
307
|
$('#tab-overrides').html(Html.join(''));
|
|
272
|
-
|
|
273
|
-
|
|
308
|
+
|
|
309
|
+
$('#t_all_models').click(function () {
|
|
310
|
+
LocalDataDisplayValues.showModels = !LocalDataDisplayValues.showModels;
|
|
311
|
+
showLocalData();
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
console.warn(`lddv is ${JSON.stringify(LocalDataDisplayValues)}`)
|
|
315
|
+
for (const item of LocalDataDisplayValues.buttonSet) {
|
|
316
|
+
console.warn(`adding click to ${item}`)
|
|
317
|
+
if (item.startsWith('d_toggle_')) $(`#${item}`).click(function () {
|
|
318
|
+
const key = item.substring(9);
|
|
319
|
+
console.warn(`clicked ${item}`);
|
|
320
|
+
if (LocalDataDisplayValues.unfoldedModels.hasOwnProperty(key))
|
|
321
|
+
LocalDataDisplayValues.unfoldedModels[key].devices =! LocalDataDisplayValues.unfoldedModels[key].devices;
|
|
322
|
+
else
|
|
323
|
+
LocalDataDisplayValues.unfoldedModels[key] = { devices:true, options: false };
|
|
324
|
+
showLocalData();
|
|
325
|
+
});
|
|
326
|
+
if (item.startsWith('o_toggle_')) $(`#${item}`).click(function () {
|
|
327
|
+
console.warn(`clicked ${item}`);
|
|
328
|
+
const key = item.substring(9);
|
|
329
|
+
if (LocalDataDisplayValues.unfoldedModels.hasOwnProperty(key))
|
|
330
|
+
LocalDataDisplayValues.unfoldedModels[key].options = !LocalDataDisplayValues.unfoldedModels[key].options;
|
|
331
|
+
else
|
|
332
|
+
LocalDataDisplayValues.unfoldedModels[key] = { devices:false, options: true };
|
|
333
|
+
showLocalData();
|
|
334
|
+
})
|
|
335
|
+
if (item.startsWith('do_toggle_')) $(`#${item}`).click(function () {
|
|
336
|
+
console.warn(`clicked ${item}`);
|
|
337
|
+
const key = item.substring(10);
|
|
338
|
+
if (LocalDataDisplayValues.unfoldedDevices.hasOwnProperty(key))
|
|
339
|
+
LocalDataDisplayValues.unfoldedDevices[key] =! LocalDataDisplayValues.unfoldedDevices[key];
|
|
340
|
+
else
|
|
341
|
+
LocalDataDisplayValues.unfoldedDevices[key] = true;
|
|
342
|
+
showLocalData();
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
|
|
274
348
|
}
|
|
275
349
|
|
|
276
350
|
/////
|
|
@@ -966,6 +1040,7 @@ function showDevices() {
|
|
|
966
1040
|
return room;
|
|
967
1041
|
}
|
|
968
1042
|
}).filter((item) => item != undefined));
|
|
1043
|
+
console.warn(`rooms is ${JSON.stringify(allRooms)}`);
|
|
969
1044
|
const roomSelector = $('#room-filter');
|
|
970
1045
|
roomSelector.empty();
|
|
971
1046
|
roomSelector.append(`<li class="device-order-item" data-type="All" tabindex="0"><a class="translate" data-lang="All">All</a></li>`);
|
|
@@ -988,12 +1063,14 @@ function showDevices() {
|
|
|
988
1063
|
|
|
989
1064
|
const element = $('#devices');
|
|
990
1065
|
|
|
991
|
-
if (
|
|
1066
|
+
if ($('tab-main')) try {
|
|
992
1067
|
shuffleInstance = devices && devices.length ? new Shuffle(element, {
|
|
993
1068
|
itemSelector: '.device',
|
|
994
1069
|
sizer: '.js-shuffle-sizer',
|
|
995
1070
|
}) : undefined;
|
|
996
1071
|
doFilter();
|
|
1072
|
+
} catch {
|
|
1073
|
+
// empty.
|
|
997
1074
|
}
|
|
998
1075
|
|
|
999
1076
|
const getDevName = function (dev_block) {
|
|
@@ -1692,55 +1769,31 @@ function getDevices() {
|
|
|
1692
1769
|
coordinatorinfo = msg;
|
|
1693
1770
|
updateStartButton()
|
|
1694
1771
|
}
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
}
|
|
1710
|
-
let newDebugMessages = false;
|
|
1711
|
-
|
|
1712
|
-
//check if debug messages are sent alongside
|
|
1713
|
-
if (msg && typeof (msg.debugDevices == 'array')) {
|
|
1714
|
-
debugDevices = msg.debugDevices;
|
|
1715
|
-
}
|
|
1716
|
-
else
|
|
1717
|
-
debugDevices = [];
|
|
1718
|
-
if (debugMessages.byId) {
|
|
1719
|
-
newDebugMessages = true;
|
|
1720
|
-
debugMessages.byId = msg;
|
|
1721
|
-
if (msg) displayDebugMessages(debugMessages)
|
|
1722
|
-
}
|
|
1723
|
-
lockout.isActive = false;
|
|
1724
|
-
if (msg.error) {
|
|
1725
|
-
errorData.push(msg.error);
|
|
1726
|
-
isHerdsmanRunning = false;
|
|
1727
|
-
} else {
|
|
1728
|
-
isHerdsmanRunning = true;
|
|
1729
|
-
if (!newDebugMessages) {
|
|
1730
|
-
getDebugMessages();
|
|
1731
|
-
}
|
|
1732
|
-
//getExclude();
|
|
1733
|
-
getBinding();
|
|
1734
|
-
}
|
|
1735
|
-
updateStartButton();
|
|
1736
|
-
showDevices();
|
|
1737
|
-
showLocalData();
|
|
1738
|
-
UpdateAdapterAlive(true)
|
|
1772
|
+
});
|
|
1773
|
+
sendToWrapper(namespace, 'getLocalConfigItems', {getAllData:true}, function(msg) {
|
|
1774
|
+
if (msg.hasOwnProperty('by_id') && msg.hasOwnProperty('by_model'))
|
|
1775
|
+
localConfigData = msg;
|
|
1776
|
+
})
|
|
1777
|
+
sendToWrapper(namespace, 'getDevices', {}, function (msg) {
|
|
1778
|
+
if (msg) {
|
|
1779
|
+
extractDevicesData(msg);
|
|
1780
|
+
if (msg.error) {
|
|
1781
|
+
errorData.push(msg.error);
|
|
1782
|
+
isHerdsmanRunning = false;
|
|
1783
|
+
} else {
|
|
1784
|
+
isHerdsmanRunning = true;
|
|
1785
|
+
getBinding();
|
|
1739
1786
|
}
|
|
1740
|
-
|
|
1787
|
+
updateStartButton();
|
|
1788
|
+
showDevices();
|
|
1789
|
+
showLocalData();
|
|
1790
|
+
UpdateAdapterAlive(true)
|
|
1791
|
+
}
|
|
1741
1792
|
});
|
|
1742
1793
|
}
|
|
1743
1794
|
|
|
1795
|
+
|
|
1796
|
+
|
|
1744
1797
|
if (lockout.timeoutid) {
|
|
1745
1798
|
clearTimeout(lockout.timeoutid);
|
|
1746
1799
|
}
|
|
@@ -1753,6 +1806,37 @@ function getDevices() {
|
|
|
1753
1806
|
|
|
1754
1807
|
}
|
|
1755
1808
|
|
|
1809
|
+
function extractDevicesData(msg) {
|
|
1810
|
+
devices = msg.devices ? msg.devices : [];
|
|
1811
|
+
// check if stashed error messages are sent alongside
|
|
1812
|
+
if (msg.clean)
|
|
1813
|
+
$('#state_cleanup_btn').removeClass('hide');
|
|
1814
|
+
else
|
|
1815
|
+
$('#state_cleanup_btn').addClass('hide');
|
|
1816
|
+
if (msg.errors && msg.errors.length > 0) {
|
|
1817
|
+
$('#show_errors_btn').removeClass('hide');
|
|
1818
|
+
errorData = msg.errors;
|
|
1819
|
+
}
|
|
1820
|
+
else {
|
|
1821
|
+
$('#show_errors_btn').addClass('hide');
|
|
1822
|
+
}
|
|
1823
|
+
//check if debug messages are sent alongside
|
|
1824
|
+
if (msg && typeof (msg.debugDevices == 'array')) {
|
|
1825
|
+
debugDevices = msg.debugDevices;
|
|
1826
|
+
}
|
|
1827
|
+
else
|
|
1828
|
+
debugDevices = [];
|
|
1829
|
+
if (debugMessages.byId) {
|
|
1830
|
+
debugMessages.byId = msg;
|
|
1831
|
+
if (msg) displayDebugMessages(debugMessages);
|
|
1832
|
+
}
|
|
1833
|
+
if (msg.models) models = msg.models;
|
|
1834
|
+
lockout.isActive = false;
|
|
1835
|
+
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
|
|
1839
|
+
|
|
1756
1840
|
function getNamedColors() {
|
|
1757
1841
|
sendToWrapper(namespace, 'getNamedColors', {}, function(msg) {
|
|
1758
1842
|
if (msg && typeof msg.colors) {
|
|
@@ -3951,20 +4035,22 @@ function sortByTitle(element) {
|
|
|
3951
4035
|
|
|
3952
4036
|
|
|
3953
4037
|
function updateDevice(id) {
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
if (devs
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
4038
|
+
if (devices.length > 0)
|
|
4039
|
+
sendToWrapper(namespace, 'getDevice', {id: id}, function (msg) {
|
|
4040
|
+
if (msg) {
|
|
4041
|
+
const devs = msg.devices;
|
|
4042
|
+
if (devs) {
|
|
4043
|
+
if (devs.error) {
|
|
4044
|
+
showMessage(devs.error, _('Error'));
|
|
4045
|
+
} else {
|
|
4046
|
+
removeDevice(id);
|
|
4047
|
+
devs.forEach(dev => devices.push(dev));
|
|
4048
|
+
showDevices();
|
|
4049
|
+
}
|
|
3964
4050
|
}
|
|
3965
4051
|
}
|
|
3966
|
-
}
|
|
3967
|
-
})
|
|
4052
|
+
});
|
|
4053
|
+
else sendToWrapper(namespace, 'getDevices', {}, extractDevicesData)
|
|
3968
4054
|
}
|
|
3969
4055
|
|
|
3970
4056
|
function removeDevice(id) {
|
|
File without changes
|
package/admin/index_m.html
CHANGED
|
@@ -326,6 +326,19 @@
|
|
|
326
326
|
#map {
|
|
327
327
|
margin: 0px;
|
|
328
328
|
}
|
|
329
|
+
.dev_list {
|
|
330
|
+
display: block;
|
|
331
|
+
margin-left: auto;
|
|
332
|
+
margin-right: auto;
|
|
333
|
+
width: 80px;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
#dataroweven { background-color: #909090; color: #c0c0c0 !important; }
|
|
337
|
+
#datarowodd { background-color: #c0c0c0; color: #202020 !important; }
|
|
338
|
+
#datarowopt { background-color: #707070; color: #c0c0c0 !important; }
|
|
339
|
+
#datatable { background-color: #3090c0; color: #202020 !important; }
|
|
340
|
+
#datared { color: #C00000 !important;}
|
|
341
|
+
#datalime { background-color: #cddc31; color: #c00000 !important;}
|
|
329
342
|
|
|
330
343
|
#tab-main .main-toolbar-table .filter-input {
|
|
331
344
|
display: inline-table;
|
|
@@ -633,6 +646,7 @@
|
|
|
633
646
|
|
|
634
647
|
}
|
|
635
648
|
|
|
649
|
+
|
|
636
650
|
.move-label-up {
|
|
637
651
|
position: absolute !important;
|
|
638
652
|
top: -60px !important;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zigbee",
|
|
4
|
-
"version": "3.1.
|
|
4
|
+
"version": "3.1.6",
|
|
5
5
|
"news": {
|
|
6
|
+
"3.1.6": {
|
|
7
|
+
"en": "Bugfixes\n",
|
|
8
|
+
"de": "Bugfixes\n",
|
|
9
|
+
"ru": "Багфиксы\n",
|
|
10
|
+
"pt": "Correcções de Erros\n",
|
|
11
|
+
"nl": "Bugfixes\n",
|
|
12
|
+
"fr": "Fixes de bogue\n",
|
|
13
|
+
"it": "Bugfix\n",
|
|
14
|
+
"es": "Bugfixes\n",
|
|
15
|
+
"pl": "Korekty błędów\n",
|
|
16
|
+
"uk": "Помилки\n",
|
|
17
|
+
"zh-cn": "错误修正\n"
|
|
18
|
+
},
|
|
6
19
|
"3.1.5": {
|
|
7
20
|
"en": "Bugfixes\nZHC25.36.0\nreduced stopTimeout to 5s",
|
|
8
21
|
"de": "Bugfixes\nZHC25.36.0\nreduzierter StopTimeout auf 5s",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "poprawianie obrazów",
|
|
81
94
|
"uk": "фіксувати зображення",
|
|
82
95
|
"zh-cn": "修正图像"
|
|
83
|
-
},
|
|
84
|
-
"3.0.1": {
|
|
85
|
-
"en": "Fix for Ikea SOMRIG configuration raising 'definition.endpoint is not a function' error.\nAccess to 'zigbee2mqtt options as settings in zigbee adapter (ALPHA Stage !)\nFix for 'error: zigbee.0 (1118300) zigbee.0 already running' at adapter start (Alpha Stage)\nUpdated hardware configuration panel - exchanged text buttons for buttons with icons.\nLimited states on device tiles to states which are read only or which can be modified sensibly via the device tile.\n",
|
|
86
|
-
"de": "Fix für Ikea SOMRIG Konfiguration erhöhen 'Definition. Endpoint ist kein Funktionsfehler.\nZugriff auf 'zigbee2mqtt Optionen als Einstellungen im Zickbee Adapter (ALPHA Stage!)\nFix für 'error: zigbee.0 (1118300) zigbee.0 bereits läuft' bei Adapterstart (Alpha Stage)\nAktualisiertes Hardware-Konfigurationsfeld - ausgetauschte Texttasten für Tasten mit Symbolen.\nBegrenzte Zustände auf Gerätefliesen zu Zuständen, die nur gelesen werden oder über die Gerätefliese sensibel modifiziert werden können.\n",
|
|
87
|
-
"ru": "Исправьте конфигурацию IKEA SOMRIG, повысив «определение». Конечная точка не является ошибкой функции.\nДоступ к опциям Zigbee2mqtt в качестве настроек в адаптере Zigbee (стадия ALPHA!)\nИсправьте ошибку: zigbee.0 (1118300) zigbee.0 уже работает на старте адаптера\nОбновленная аппаратная панель конфигурации - обмен текстовыми кнопками на кнопки с иконками.\nОграниченные состояния на плитках устройства к состояниям, которые читаются только или которые могут быть изменены чувственно через плитку устройства.\n",
|
|
88
|
-
"pt": "Corrigir para configuração Ikea SOMRIG elevando 'definição. endpoint não é um erro de função.\nAcesso às opções \"zigbee2mqttt como configurações no adaptador zigbee (Estação LAPHA!)\nFix for 'error: zigbee.0 (1118300) zigbee.0 já em execução' no início do adaptador (Alpha Stage)\nPainel de configuração de hardware atualizado - botões de texto trocados para botões com ícones.\nEstados limitados em telhas de dispositivo para estados que são lidos apenas ou que podem ser modificados sensivelmente através da telha do dispositivo.\n",
|
|
89
|
-
"nl": "Fix voor Ikea SOMRIG configuratie verhogen 'definitie. eindpunt is geen functiefout.\nToegang tot 'zigbee2mqtt opties als instellingen in zigbee adapter (ALPHA Stage !)\nFix voor 'fout: zigbee.0 (1118300) zigbee.0 al actief' bij adapterstart (Alpha Stage)\nBijgewerkt hardware configuratiepaneel - uitgewisselde tekstknoppen voor knoppen met pictogrammen.\nBeperkte toestanden op apparaattegels naar toestanden die alleen worden gelezen of die verstandig kunnen worden gewijzigd via de apparaattegel.\n",
|
|
90
|
-
"fr": "Correction pour la configuration Ikea SOMRIG augmentant la définition. le paramètre n'est pas une erreur de fonction.\nAccès aux options 'zigbee2mqtt comme réglages dans l'adaptateur zigbee (ALPHA Stage !)\nCorrection pour 'erreur: zigbee.0 (1118300) zigbee.0 déjà en cours d'exécution' au démarrage de l'adaptateur (Alpha Stage)\nPanneau de configuration du matériel mis à jour - boutons texte échangés pour les boutons avec des icônes.\nLes états limités sur les tuiles de l'appareil aux états qui sont lus seulement ou qui peuvent être modifiés de façon sensible via la tuile de l'appareil.\n",
|
|
91
|
-
"it": "Fissare per Ikea SOMRIG configurazione aumentando 'definizione. endpoint non è un errore di funzione.\nAccesso alle opzioni 'zigbee2mqtt come impostazioni nell'adattatore zigbee (ALPHA Stage !)\nCorrezione per 'error: zigbee.0 (1118300) zigbee.0 già in esecuzione' all'inizio dell'adattatore (Alpha Stage)\nPannello di configurazione hardware aggiornato - pulsanti di testo scambiati per pulsanti con icone.\nStati limitati su piastrelle di dispositivo a stati che sono letti solo o che possono essere modificati sensibilmente tramite la piastrella del dispositivo.\n",
|
|
92
|
-
"es": "Arregla para la configuración de Ikea SOMRIG criando 'definición. endpoint no es un error de función.\nAcceso a las opciones 'zigbee2mqtt como configuración en el adaptador de zigbee (ALPHA Stage !)\nFijación para 'error: zigbee.0 (1118300) zigbee.0 ya funcionando en el inicio del adaptador (Alpha Stage)\nPanel de configuración de hardware actualizado - botones de texto intercambiados para botones con iconos.\nEstados limitados en fichas de dispositivo a estados que se leen solamente o que pueden ser modificados de forma sensata a través de la ficha del dispositivo.\n",
|
|
93
|
-
"pl": "Napraw dla definicji podnoszenie konfiguracji Ikea SOMRIG. Punkt końcowy nie jest błędem funkcji.\nDostęp do opcji 'zigbee2mqtt jako ustawień w adapterze zigbee (ALPHA Stage!)\nFix for 'error: zigbee.0 (1118300) zigbee.0 already running' at adapter start (Alpha Stage)\nAktualizacja panelu konfiguracji sprzętowej - wymieniono przyciski tekstowe na przyciski z ikonami.\nOgraniczone stany na płytkach urządzenia do stanów, które są tylko odczytywane lub które mogą być modyfikowane w sposób rozsądny za pomocą płytki urządzenia.\n",
|
|
94
|
-
"uk": "Виправлення для налаштування Ikea SOMRIG 'Визначення. кінцева точка не є помилкою функції.\nДоступ до опцій Zigbee2mqtt як налаштування адаптера Zigbee (ALPHA Stage !)\nВиправлення для 'error: zigbee.0 (1118300) zigbee.0 вже запущений' при запуску адаптера (Alpha Stage)\nОновлена панель конфігурації обладнання - обмінні текстові кнопки для гудзиків з іконками.\nОбмежені стани на плитці пристрою для станів, які читаються тільки або які можуть бути змінені, швидко через плитку пристрою.\n",
|
|
95
|
-
"zh-cn": "修复Ikea SOMRIG 配置提升定义 。 结束点不是一个函数'错误.\n访问 'zigbee2mqtt 选项作为 Zigbee 适配器的设置( ALPHA stage !) \n在适配器启动( Alpha Stage)时为 'error: zigbee. 0 (1118300) zigbee. 0 已经运行' 进行修复\n更新的硬件配置面板 - 用图标交换文本按钮作为按钮.\n将设备瓦片的状态限制在只读或通过设备瓦片可敏感修改的状态.\n"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
package/lib/commands.js
CHANGED
|
@@ -339,10 +339,6 @@ class Commands {
|
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
-
|
|
343
|
-
async handleDeviceforInfo(device, states) {
|
|
344
|
-
}
|
|
345
|
-
|
|
346
342
|
async handleGroupforInfo(group, groups) {
|
|
347
343
|
group.icon = 'img/group.png';
|
|
348
344
|
group.vendor = 'ioBroker';
|
|
@@ -379,7 +375,7 @@ class Commands {
|
|
|
379
375
|
}
|
|
380
376
|
}
|
|
381
377
|
|
|
382
|
-
async fillInfo(device, device_stateDefs, all_states) {
|
|
378
|
+
async fillInfo(device, device_stateDefs, all_states, models) {
|
|
383
379
|
device.statesDef = (device_stateDefs || []).filter(stateDef => {
|
|
384
380
|
const sid = stateDef._id.replace(this.adapter.namespace + '.', '');
|
|
385
381
|
const names = sid.split('.');
|
|
@@ -403,7 +399,23 @@ class Commands {
|
|
|
403
399
|
});
|
|
404
400
|
|
|
405
401
|
const id = getZbId(device._id);
|
|
406
|
-
|
|
402
|
+
const entity = await this.zbController.resolveEntity(id)
|
|
403
|
+
|
|
404
|
+
device.info = this.buildDeviceInfo(entity);
|
|
405
|
+
|
|
406
|
+
const UID = models.UIDbyModel[device.info?.mapped?.model || 'unknown'] || `m_${Object.keys(models.UIDbyModel).length}`;
|
|
407
|
+
if (models.byUID.hasOwnProperty(UID)) {
|
|
408
|
+
models.byUID[UID].devices.push(device);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
models.byUID[UID] = {
|
|
412
|
+
model:device.info.mapped,
|
|
413
|
+
availableOptions : [...device.info?.mapped?.options || [], ...['use_legacy_model']],
|
|
414
|
+
setOptions: this.adapter.stController.localConfig.getByModel(device.info?.mapped?.model || 'unknown') || [],
|
|
415
|
+
devices: [device],
|
|
416
|
+
}
|
|
417
|
+
models.UIDbyModel[device.info?.mapped?.model || 'unknown'] = UID;
|
|
418
|
+
}
|
|
407
419
|
// check configuration
|
|
408
420
|
try {
|
|
409
421
|
if (device.info) {
|
|
@@ -412,13 +424,11 @@ class Commands {
|
|
|
412
424
|
[device.info.device, device.info.mapped],
|
|
413
425
|
);
|
|
414
426
|
if (result.length > 0) device.isConfigured = !result[0];
|
|
415
|
-
|
|
427
|
+
device.paired = true;
|
|
428
|
+
} else device.paired = false;
|
|
416
429
|
} catch (error) {
|
|
417
430
|
this.warn('error calling shouldConfigure: ' + error && error.message ? error.message : 'no error message');
|
|
418
431
|
}
|
|
419
|
-
device.paired = !!device.info;
|
|
420
|
-
|
|
421
|
-
|
|
422
432
|
}
|
|
423
433
|
|
|
424
434
|
buildDeviceInfo(device) {
|
|
@@ -427,11 +437,11 @@ class Commands {
|
|
|
427
437
|
rv.device = {
|
|
428
438
|
modelZigbee:device.device.modelID,
|
|
429
439
|
type:device.device.type,
|
|
430
|
-
ieee:device.device.ieeeAddr,
|
|
431
|
-
nwk:device.device.networkAddress,
|
|
440
|
+
ieee:device.device.ieeeAddr || device.device.groupID,
|
|
441
|
+
nwk:device.device.networkAddress || 0,
|
|
432
442
|
manuf_id:device.device.maufacturerID,
|
|
433
443
|
manuf_name:device.device.manufacturerName,
|
|
434
|
-
manufacturer:device.mapped
|
|
444
|
+
manufacturer:device.mapped?.vendor,
|
|
435
445
|
power:device.device.powerSource,
|
|
436
446
|
app_version:device.device.applicationVersion,
|
|
437
447
|
hard_version:device.device.hardwareVersion,
|
|
@@ -462,10 +472,10 @@ class Commands {
|
|
|
462
472
|
options:[],
|
|
463
473
|
}
|
|
464
474
|
if (device.mapped.options && typeof (device.mapped.options == 'object')) {
|
|
465
|
-
const optionDesc = [];
|
|
466
475
|
for (const option of device.mapped.options) {
|
|
467
|
-
if (option.name)
|
|
476
|
+
if (option.name) {
|
|
468
477
|
rv.mapped.options.push(option.name);
|
|
478
|
+
}
|
|
469
479
|
}
|
|
470
480
|
}
|
|
471
481
|
}
|
|
@@ -501,7 +511,7 @@ class Commands {
|
|
|
501
511
|
paired: true,
|
|
502
512
|
info: this.buildDeviceInfo(device),
|
|
503
513
|
native: { id: device.device.ieeeAddr.substring(2) },
|
|
504
|
-
mapped : {},
|
|
514
|
+
mapped : { model:'Coordinator' },
|
|
505
515
|
statesDev: [],
|
|
506
516
|
}
|
|
507
517
|
if (device.device.name === 'Coordinator') {
|
|
@@ -513,7 +523,6 @@ class Commands {
|
|
|
513
523
|
}
|
|
514
524
|
devices.push(coordinatorData);
|
|
515
525
|
}
|
|
516
|
-
|
|
517
526
|
}
|
|
518
527
|
|
|
519
528
|
async getDevices(from, command, id, callback) {
|
|
@@ -522,13 +531,14 @@ class Commands {
|
|
|
522
531
|
this.adapter.sendTo(from, command, {error: 'No active connection to Zigbee Hardware!'}, callback);
|
|
523
532
|
return;
|
|
524
533
|
}
|
|
525
|
-
const
|
|
534
|
+
const roomsEnum = await this.adapter.getEnumsAsync('enum.rooms') || {};
|
|
526
535
|
const deviceObjects = (id ? [await this.adapter.getObjectAsync(id)] : await this.adapter.getDevicesAsync());
|
|
527
536
|
const all_states = id ? await this.adapter.getStatesAsync(id + '.*') : await this.adapter.getStatesAsync('*');
|
|
528
537
|
const all_stateDefs = id ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
|
|
529
538
|
const illegalDevices = [];
|
|
530
539
|
const groups = {};
|
|
531
540
|
const PromiseChain = [];
|
|
541
|
+
const models = { byUID : {}, UIDbyModel: {} };
|
|
532
542
|
for (const devInfo of deviceObjects) {
|
|
533
543
|
if (devInfo._id.indexOf('group') > -1) {
|
|
534
544
|
PromiseChain.push(this.handleGroupforInfo(devInfo, groups));
|
|
@@ -544,22 +554,23 @@ class Commands {
|
|
|
544
554
|
devInfo.link_quality_lc = lq_state ? lq_state.lc : undefined;
|
|
545
555
|
const battery_state = all_states[`${devInfo._id}.battery`];
|
|
546
556
|
devInfo.battery = battery_state ? battery_state.val : undefined;
|
|
547
|
-
devInfo.rooms = [];
|
|
548
|
-
for (const room in rooms) {
|
|
549
|
-
if (!rooms.hasOwnProperty(room) ||
|
|
550
|
-
!rooms[room] ||
|
|
551
|
-
!rooms[room].common ||
|
|
552
|
-
!rooms[room].common.members
|
|
553
|
-
) {
|
|
554
|
-
continue;
|
|
555
|
-
}
|
|
556
|
-
if (rooms[room].common.members.includes(devInfo._id)) {
|
|
557
|
-
devInfo.rooms.push(rooms[room].common.name);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
557
|
|
|
561
558
|
}
|
|
562
|
-
|
|
559
|
+
devInfo.rooms = [];
|
|
560
|
+
const rooms = roomsEnum['enum.rooms'] || {};
|
|
561
|
+
for (const room of Object.keys(rooms)) {
|
|
562
|
+
if (!rooms.hasOwnProperty(room) ||
|
|
563
|
+
!rooms[room] ||
|
|
564
|
+
!rooms[room].common ||
|
|
565
|
+
!rooms[room].common.members
|
|
566
|
+
) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
if (rooms[room].common.members.includes(devInfo._id)) {
|
|
570
|
+
devInfo.rooms.push(rooms[room].common.name);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
PromiseChain.push(this.fillInfo(devInfo, all_stateDefs.filter(item => item._id.startsWith(devInfo._id)),all_states, models));
|
|
563
574
|
}
|
|
564
575
|
if (!id) {
|
|
565
576
|
for (const client of this.zbController.getClientIterator(true)) {
|
|
@@ -580,7 +591,12 @@ class Commands {
|
|
|
580
591
|
|
|
581
592
|
this.debug(`getDevices contains ${deviceObjects.length} Devices`);
|
|
582
593
|
const rv = { devices:deviceObjects, inLog:this.adapter.deviceDebug.logStatus, }
|
|
583
|
-
if (!id)
|
|
594
|
+
if (!id) {
|
|
595
|
+
rv.deviceDebugData = this.adapter.deviceDebug.collectDebugData();
|
|
596
|
+
rv.localOverrides = this.adapter.stController.localConfig.localData;
|
|
597
|
+
rv.models = models.byUID;
|
|
598
|
+
}
|
|
599
|
+
|
|
584
600
|
if (this.stController) {
|
|
585
601
|
rv.clean = this.stController.CleanupRequired();
|
|
586
602
|
rv.errors = this.stController.getStashedErrors();
|
|
@@ -875,6 +891,9 @@ class Commands {
|
|
|
875
891
|
//const targetModel = msg.model ? msg.model : '';
|
|
876
892
|
}
|
|
877
893
|
else {
|
|
894
|
+
if (msg.getAllData) {
|
|
895
|
+
this.adapter.sendTo(from, command, this.stController.localConfig.localData, callback);
|
|
896
|
+
}
|
|
878
897
|
rv.error = `missing data in message ${JSON.stringify(msg)}`;
|
|
879
898
|
}
|
|
880
899
|
}
|
package/lib/developer.js
CHANGED
|
File without changes
|
package/lib/exposes.js
CHANGED
|
@@ -801,7 +801,7 @@ function createFromExposes(model, def, device, log) {
|
|
|
801
801
|
|
|
802
802
|
case 'climate':
|
|
803
803
|
for (const prop of expose.features) {
|
|
804
|
-
switch (prop.name) {
|
|
804
|
+
/* switch (prop.name) {
|
|
805
805
|
case 'away_mode':
|
|
806
806
|
pushToStates(statesDefs.climate_away_mode, prop.access);
|
|
807
807
|
break;
|
|
@@ -814,7 +814,8 @@ function createFromExposes(model, def, device, log) {
|
|
|
814
814
|
default:
|
|
815
815
|
pushToStates(genState(prop), prop.access);
|
|
816
816
|
break;
|
|
817
|
-
}
|
|
817
|
+
}*/
|
|
818
|
+
pushToStates(genState(prop), prop.access);
|
|
818
819
|
}
|
|
819
820
|
break;
|
|
820
821
|
|
package/lib/localConfig.js
CHANGED
|
@@ -329,6 +329,14 @@ class localConfig extends EventEmitter {
|
|
|
329
329
|
return rv;
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
getByModel(id) {
|
|
333
|
+
return this.localData.by_model[id] || {};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
getByDevice(id) {
|
|
337
|
+
return this.localData.by_id[id] || {};
|
|
338
|
+
}
|
|
339
|
+
|
|
332
340
|
}
|
|
333
341
|
|
|
334
342
|
module.exports = localConfig;
|
package/lib/ota.js
CHANGED
|
File without changes
|
package/lib/zbDeviceConfigure.js
CHANGED
|
File without changes
|
package/lib/zigbeecontroller.js
CHANGED
|
@@ -618,6 +618,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
618
618
|
device: coordinator,
|
|
619
619
|
endpoint: coordinator.getEndpoint(1),
|
|
620
620
|
name: 'Coordinator',
|
|
621
|
+
mapped: { model: 'Coordinator'},
|
|
621
622
|
options:{}
|
|
622
623
|
};
|
|
623
624
|
}
|
|
@@ -657,6 +658,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
657
658
|
return {
|
|
658
659
|
type: 'device',
|
|
659
660
|
device: device,
|
|
661
|
+
mapped: { model: 'Coordinator'},
|
|
660
662
|
endpoint: device.getEndpoint(1),
|
|
661
663
|
name: 'Coordinator',
|
|
662
664
|
};
|
|
@@ -736,6 +738,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
736
738
|
await this.herdsman.stop();
|
|
737
739
|
this.herdsmanStarted = false;
|
|
738
740
|
this.info('zigbecontroller stopped successfully');
|
|
741
|
+
return;
|
|
739
742
|
}
|
|
740
743
|
else this.info('zigbecontroller stopped successfully - ZH was not running');
|
|
741
744
|
} catch (error) {
|
|
@@ -759,6 +762,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
759
762
|
|
|
760
763
|
// Permit join
|
|
761
764
|
async permitJoin(permitTime, devid) {
|
|
765
|
+
if (!this.herdsmanStarted) return false;
|
|
762
766
|
try {
|
|
763
767
|
this._permitJoinTime = permitTime;
|
|
764
768
|
await this.herdsman.permitJoin(permitTime);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.6",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"uri-js": "^4.4.1",
|
|
30
30
|
"typescript": "^5.9.2",
|
|
31
31
|
"zigbee-herdsman": "^6.0.0",
|
|
32
|
-
"zigbee-herdsman-converters": "25.
|
|
32
|
+
"zigbee-herdsman-converters": "^25.37.0"
|
|
33
33
|
},
|
|
34
34
|
"description": "Zigbee devices",
|
|
35
35
|
"devDependencies": {
|