iobroker.lorawan 1.20.23 → 1.20.24
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 +3 -0
- package/io-package.json +14 -14
- package/lib/modules/deviceManager.js +137 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,9 @@ For now there is documentation in English here: https://wiki.hafenmeister.de
|
|
|
23
23
|
Placeholder for the next version (at the beginning of the line):
|
|
24
24
|
### **WORK IN PROGRESS**
|
|
25
25
|
-->
|
|
26
|
+
### 1.20.24 (2026-01-28)
|
|
27
|
+
* (BenAhrdt) change info Form to Detail button
|
|
28
|
+
|
|
26
29
|
### 1.20.23 (2026-01-28)
|
|
27
30
|
* (BenAhrdt) change role display and icons
|
|
28
31
|
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "lorawan",
|
|
4
|
-
"version": "1.20.
|
|
4
|
+
"version": "1.20.24",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.20.24": {
|
|
7
|
+
"en": "change info Form to Detail button",
|
|
8
|
+
"de": "änderungen Formular zum Detail Knopf",
|
|
9
|
+
"ru": "изменить информацию Форма для детализации кнопки",
|
|
10
|
+
"pt": "alterar informações Botão de Formulário para Detalhe",
|
|
11
|
+
"nl": "info wijzigen Vorm naar detailknop",
|
|
12
|
+
"fr": "modifier les informations Formulaire au bouton Détail",
|
|
13
|
+
"it": "cambiare le informazioni Modulo per Dettaglio pulsante",
|
|
14
|
+
"es": "cambio de información Forma al botón Detalle",
|
|
15
|
+
"pl": "zmiana informacji Format do przycisku Szczegóły",
|
|
16
|
+
"uk": "зміна інформації Форма для докладної кнопки",
|
|
17
|
+
"zh-cn": "更改信息 详细按钮的窗体"
|
|
18
|
+
},
|
|
6
19
|
"1.20.23": {
|
|
7
20
|
"en": "change role display and icons",
|
|
8
21
|
"de": "rollenanzeige und icons ändern",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "nadchodzące nazewnictwo bugfix Temat",
|
|
81
94
|
"uk": "виправлення ім'я користувача Головна",
|
|
82
95
|
"zh-cn": "正在接收错误修正名称 专题"
|
|
83
|
-
},
|
|
84
|
-
"1.20.17": {
|
|
85
|
-
"en": "implement Device details",
|
|
86
|
-
"de": "durchführung Gerätedetails",
|
|
87
|
-
"ru": "осуществлять Детали устройства",
|
|
88
|
-
"pt": "implementar Detalhes do dispositivo",
|
|
89
|
-
"nl": "implementeren Apparaatdetails",
|
|
90
|
-
"fr": "mise en œuvre Détails du périphérique",
|
|
91
|
-
"it": "attuazione Dettagli del dispositivo",
|
|
92
|
-
"es": "aplicación Detalles del dispositivo",
|
|
93
|
-
"pl": "wdrożenie Szczegóły dotyczące urządzenia",
|
|
94
|
-
"uk": "реалізація Деталі пристрою",
|
|
95
|
-
"zh-cn": "执行 设备细节"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
|
@@ -16,6 +16,7 @@ class LoRaWANDeviceManagement extends DeviceManagement {
|
|
|
16
16
|
this.adapter = adapter;
|
|
17
17
|
this.x = adapter;
|
|
18
18
|
}
|
|
19
|
+
|
|
19
20
|
/**
|
|
20
21
|
* List all LoRaWAN devices
|
|
21
22
|
*/
|
|
@@ -23,36 +24,36 @@ class LoRaWANDeviceManagement extends DeviceManagement {
|
|
|
23
24
|
// @ts-expect-error
|
|
24
25
|
async listDevices() {
|
|
25
26
|
const arrDevices = [];
|
|
26
|
-
for (const [
|
|
27
|
+
for (const [devEUI, deviceValue] of Object.entries(this.adapter.objectStore.devices)) {
|
|
27
28
|
// Check for logging
|
|
28
|
-
this.adapter.log[this.adapter.logtypes.listDevices]?.(`List device started for device: ${
|
|
29
|
+
this.adapter.log[this.adapter.logtypes.listDevices]?.(`List device started for device: ${devEUI}`);
|
|
29
30
|
const res = {
|
|
30
|
-
id:
|
|
31
|
-
name:
|
|
32
|
-
icon: await this.getIcon(
|
|
31
|
+
id: devEUI,
|
|
32
|
+
name: deviceValue.object.common.name,
|
|
33
|
+
icon: await this.getIcon(deviceValue),
|
|
33
34
|
manufacturer: 'LoRaWAN',
|
|
34
|
-
model:
|
|
35
|
-
status: await this.getStatus(
|
|
36
|
-
hasDetails:
|
|
35
|
+
model: deviceValue.informations ? deviceValue.informations.devicetype.state.val : undefined, // - ${value.uplink.remaining.rxInfo[0].rssi.ts}`,
|
|
36
|
+
status: await this.getStatus(deviceValue),
|
|
37
|
+
hasDetails: true,
|
|
37
38
|
actions: [
|
|
38
39
|
{
|
|
39
40
|
id: 'rename',
|
|
40
41
|
icon: 'edit',
|
|
41
42
|
description: this.adapter.i18nTranslation['Rename this device'],
|
|
42
|
-
handler: async (_id, context) => await this.handleRenameDevice(_id, context,
|
|
43
|
+
handler: async (_id, context) => await this.handleRenameDevice(_id, context, deviceValue),
|
|
43
44
|
},
|
|
44
45
|
{
|
|
45
46
|
id: 'config',
|
|
46
47
|
icon: 'settings',
|
|
47
48
|
description: this.adapter.i18nTranslation['Config this device'],
|
|
48
|
-
handler: async (_id, context) => await this.handleConfigDevice(_id, context,
|
|
49
|
+
handler: async (_id, context) => await this.handleConfigDevice(_id, context, deviceValue),
|
|
49
50
|
},
|
|
50
|
-
{
|
|
51
|
+
/* {
|
|
51
52
|
id: 'Info',
|
|
52
53
|
icon: 'lines',
|
|
53
54
|
description: this.adapter.i18nTranslation['Info of this device'],
|
|
54
55
|
handler: async (_id, context) => await this.handleInfo(_id, context),
|
|
55
|
-
},
|
|
56
|
+
}, Outcommented at 28.01.2026 (use Details)*/
|
|
56
57
|
],
|
|
57
58
|
};
|
|
58
59
|
arrDevices.push(res);
|
|
@@ -249,7 +250,7 @@ class LoRaWANDeviceManagement extends DeviceManagement {
|
|
|
249
250
|
* @param id ID to rename
|
|
250
251
|
* @param context context sendet from Backend
|
|
251
252
|
*/
|
|
252
|
-
async handleInfo(id, context) {
|
|
253
|
+
/*async handleInfo(id, context) {
|
|
253
254
|
const generalItems = {};
|
|
254
255
|
const data = {};
|
|
255
256
|
const lastUplinkTs = new Date(
|
|
@@ -364,7 +365,7 @@ class LoRaWANDeviceManagement extends DeviceManagement {
|
|
|
364
365
|
};
|
|
365
366
|
await context.showForm(schema, options);
|
|
366
367
|
return { refresh: true };
|
|
367
|
-
}
|
|
368
|
+
} Outcommented at 28.01.2026 (use Details)*/
|
|
368
369
|
|
|
369
370
|
/**
|
|
370
371
|
*
|
|
@@ -386,6 +387,128 @@ class LoRaWANDeviceManagement extends DeviceManagement {
|
|
|
386
387
|
|
|
387
388
|
return object;
|
|
388
389
|
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* @param {string} id ID from device
|
|
393
|
+
* @returns {Promise<import('@iobroker/dm-utils').DeviceDetails>} return the right value
|
|
394
|
+
*/
|
|
395
|
+
async getDeviceDetails(id) {
|
|
396
|
+
// eslint-disable-next-line jsdoc/check-tag-names
|
|
397
|
+
/** @type {Record<string, import('@iobroker/dm-utils').ConfigItemAny>} */
|
|
398
|
+
const generalItems = {};
|
|
399
|
+
const data = {};
|
|
400
|
+
const lastUplinkTs = new Date(
|
|
401
|
+
this.adapter.objectStore.devices[id].informations.lastUplink.state.ts,
|
|
402
|
+
).toLocaleString('de-DE', {
|
|
403
|
+
weekday: 'long', // Mo
|
|
404
|
+
year: 'numeric', // 2026
|
|
405
|
+
month: '2-digit', // 01
|
|
406
|
+
day: '2-digit', // 24
|
|
407
|
+
hour: '2-digit', // 14
|
|
408
|
+
minute: '2-digit', // 32
|
|
409
|
+
second: '2-digit', // 10
|
|
410
|
+
});
|
|
411
|
+
generalItems['Timestamp_value'] = {
|
|
412
|
+
type: 'staticInfo',
|
|
413
|
+
label: 'LastUplink',
|
|
414
|
+
size: 16,
|
|
415
|
+
data: lastUplinkTs,
|
|
416
|
+
};
|
|
417
|
+
if (this.adapter.objectStore.devices[id].join?.raw?.json?.state?.lc) {
|
|
418
|
+
const lastJoinedLc = new Date(this.adapter.objectStore.devices[id].join.raw.json.state.lc).toLocaleString(
|
|
419
|
+
'de-DE',
|
|
420
|
+
{
|
|
421
|
+
weekday: 'long', // Mo
|
|
422
|
+
year: 'numeric', // 2026
|
|
423
|
+
month: '2-digit', // 01
|
|
424
|
+
day: '2-digit', // 24
|
|
425
|
+
hour: '2-digit', // 14
|
|
426
|
+
minute: '2-digit', // 32
|
|
427
|
+
second: '2-digit', // 10
|
|
428
|
+
},
|
|
429
|
+
);
|
|
430
|
+
generalItems['Join_value'] = {
|
|
431
|
+
type: 'staticInfo',
|
|
432
|
+
label: 'lastJoined',
|
|
433
|
+
size: 16,
|
|
434
|
+
data: lastJoinedLc,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
generalItems['uplinkDecodedHeader'] = {
|
|
439
|
+
newLine: true,
|
|
440
|
+
type: 'header',
|
|
441
|
+
text: 'Uplink Decoded',
|
|
442
|
+
size: 3,
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
generalItems['uplinkDecoded'] = {
|
|
446
|
+
type: 'text',
|
|
447
|
+
readOnly: true,
|
|
448
|
+
minRows: 10,
|
|
449
|
+
maxRows: 40,
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
let subfolders = {};
|
|
453
|
+
for (const [key, value] of Object.entries(this.adapter.objectStore.devices[id].detectedRoles)) {
|
|
454
|
+
if (key === 'state') {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
for (const subfolder in value) {
|
|
458
|
+
if (!subfolder.startsWith('uplink') && subfolder !== 'downlink.control') {
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
if (!subfolders[subfolder]) {
|
|
462
|
+
subfolders[subfolder] = {};
|
|
463
|
+
}
|
|
464
|
+
subfolders[subfolder][key] = value[subfolder];
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
subfolders = this.sortObjectDeep(subfolders);
|
|
468
|
+
// eslint-disable-next-line jsdoc/check-tag-names
|
|
469
|
+
/** @type {Record<string, import('@iobroker/dm-utils').ConfigItemAny>} */
|
|
470
|
+
const roleItems = {};
|
|
471
|
+
for (const subfolder in subfolders) {
|
|
472
|
+
roleItems[subfolder] = {
|
|
473
|
+
newLine: true,
|
|
474
|
+
type: 'header',
|
|
475
|
+
text: subfolder,
|
|
476
|
+
size: 3,
|
|
477
|
+
};
|
|
478
|
+
const detectedRoles = Object.entries(subfolders[subfolder])
|
|
479
|
+
.map(([key, value]) => `${key}(${value})`)
|
|
480
|
+
.join(' ');
|
|
481
|
+
roleItems[`${subfolder.replace(/\./g, '_')}Roles`] = {
|
|
482
|
+
type: 'text',
|
|
483
|
+
minRows: 2,
|
|
484
|
+
readOnly: true,
|
|
485
|
+
};
|
|
486
|
+
data[`${subfolder.replace(/\./g, '_')}Roles`] = detectedRoles;
|
|
487
|
+
}
|
|
488
|
+
// eslint-disable-next-line jsdoc/check-tag-names
|
|
489
|
+
/** @type {import('@iobroker/dm-utils').JsonFormSchema} */
|
|
490
|
+
const schema = {
|
|
491
|
+
type: 'tabs',
|
|
492
|
+
items: {
|
|
493
|
+
generalTab: {
|
|
494
|
+
type: 'panel',
|
|
495
|
+
label: 'generalInformations',
|
|
496
|
+
items: generalItems,
|
|
497
|
+
},
|
|
498
|
+
roleTab: {
|
|
499
|
+
type: 'panel',
|
|
500
|
+
label: 'detectedRoles',
|
|
501
|
+
items: roleItems,
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
let deviceInfo = await this.adapter.getStateAsync('info.deviceinformations');
|
|
507
|
+
deviceInfo = JSON.parse(deviceInfo.val);
|
|
508
|
+
const sortedUplinkDecoded = this.sortObjectDeep(deviceInfo[id].uplink.decoded);
|
|
509
|
+
data.uplinkDecoded = JSON.stringify(sortedUplinkDecoded, null, 2);
|
|
510
|
+
return { id, schema, data };
|
|
511
|
+
}
|
|
389
512
|
}
|
|
390
513
|
|
|
391
514
|
module.exports = LoRaWANDeviceManagement;
|