iobroker.lorawan 1.20.23 → 1.20.25

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 CHANGED
@@ -23,6 +23,12 @@ 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.25 (2026-01-28)
27
+ * (BenAhrdt) improve number of role detection
28
+
29
+ ### 1.20.24 (2026-01-28)
30
+ * (BenAhrdt) change info Form to Detail button
31
+
26
32
  ### 1.20.23 (2026-01-28)
27
33
  * (BenAhrdt) change role display and icons
28
34
 
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.20.23",
4
+ "version": "1.20.25",
5
5
  "news": {
6
+ "1.20.25": {
7
+ "en": "improve number of role detection",
8
+ "de": "verbesserung der anzahl der rollenerkennung",
9
+ "ru": "улучшение обнаружения ролей",
10
+ "pt": "melhorar o número de detecção de funções",
11
+ "nl": "het aantal roldetectie verbeteren",
12
+ "fr": "améliorer le nombre de détections de rôles",
13
+ "it": "migliorare il numero di rilevamento del ruolo",
14
+ "es": "mejorar el número de detección de funciones",
15
+ "pl": "zwiększenie liczby wykrywanych ról",
16
+ "uk": "поліпшення кількості визначення ролі",
17
+ "zh-cn": "改进角色检测数量"
18
+ },
19
+ "1.20.24": {
20
+ "en": "change info Form to Detail button",
21
+ "de": "änderungen Formular zum Detail Knopf",
22
+ "ru": "изменить информацию Форма для детализации кнопки",
23
+ "pt": "alterar informações Botão de Formulário para Detalhe",
24
+ "nl": "info wijzigen Vorm naar detailknop",
25
+ "fr": "modifier les informations Formulaire au bouton Détail",
26
+ "it": "cambiare le informazioni Modulo per Dettaglio pulsante",
27
+ "es": "cambio de información Forma al botón Detalle",
28
+ "pl": "zmiana informacji Format do przycisku Szczegóły",
29
+ "uk": "зміна інформації Форма для докладної кнопки",
30
+ "zh-cn": "更改信息 详细按钮的窗体"
31
+ },
6
32
  "1.20.23": {
7
33
  "en": "change role display and icons",
8
34
  "de": "rollenanzeige und icons ändern",
@@ -67,32 +93,6 @@
67
93
  "pl": "bugfix incon set",
68
94
  "uk": "виправлення помилок",
69
95
  "zh-cn": "装入套装错误"
70
- },
71
- "1.20.18": {
72
- "en": "bugfix nameing incomingTopic",
73
- "de": "bugfix Nameing eingehend Thema",
74
- "ru": "bugfix Имя входящего Тема",
75
- "pt": "correcção de erros a dar entrada Tópico",
76
- "nl": "bugfix-naam binnenkomend Onderwerp",
77
- "fr": "bugfix nominant entrant Thème",
78
- "it": "bugfix nome in arrivo Argomento",
79
- "es": "bugfix nombre entrante Tema",
80
- "pl": "nadchodzące nazewnictwo bugfix Temat",
81
- "uk": "виправлення ім'я користувача Головна",
82
- "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 [key, value] of Object.entries(this.adapter.objectStore.devices)) {
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: ${key}`);
29
+ this.adapter.log[this.adapter.logtypes.listDevices]?.(`List device started for device: ${devEUI}`);
29
30
  const res = {
30
- id: key,
31
- name: value.object.common.name,
32
- icon: await this.getIcon(value),
31
+ id: devEUI,
32
+ name: deviceValue.object.common.name,
33
+ icon: await this.getIcon(deviceValue),
33
34
  manufacturer: 'LoRaWAN',
34
- model: value.informations ? value.informations.devicetype.state.val : undefined, // - ${value.uplink.remaining.rxInfo[0].rssi.ts}`,
35
- status: await this.getStatus(value),
36
- hasDetails: false,
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, value),
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, value),
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;
@@ -102,16 +102,24 @@ class objectStoreClass {
102
102
  if (payload.object) {
103
103
  // Just Quere if role is not undefined
104
104
  if (payload.object.common.role !== undefined) {
105
- if (!deviceObject[deviceId].detectedRoles) {
106
- deviceObject[deviceId].detectedRoles = {};
107
- }
108
- if (!deviceObject[deviceId].detectedRoles[payload.object.common.role]) {
109
- deviceObject[deviceId].detectedRoles[payload.object.common.role] = {};
110
- }
111
- if (!deviceObject[deviceId].detectedRoles[payload.object.common.role][idSubfolder]) {
112
- deviceObject[deviceId].detectedRoles[payload.object.common.role][idSubfolder] = 1;
113
- } else {
114
- deviceObject[deviceId].detectedRoles[payload.object.common.role][idSubfolder] += 1;
105
+ if (!idObject[id].roleDetected) {
106
+ if (!deviceObject[deviceId].detectedRoles) {
107
+ deviceObject[deviceId].detectedRoles = {};
108
+ }
109
+ if (!deviceObject[deviceId].detectedRoles[payload.object.common.role]) {
110
+ deviceObject[deviceId].detectedRoles[payload.object.common.role] = {};
111
+ }
112
+ if (
113
+ !deviceObject[deviceId].detectedRoles[payload.object.common.role][idSubfolder]
114
+ ) {
115
+ deviceObject[deviceId].detectedRoles[payload.object.common.role][idSubfolder] =
116
+ 1;
117
+ } else {
118
+ deviceObject[deviceId].detectedRoles[payload.object.common.role][idSubfolder] +=
119
+ 1;
120
+ }
121
+ // Role for DeviceAssignes
122
+ idObject[id].roleDetected = true;
115
123
  }
116
124
  if (Object.hasOwn(this.roleAssignToDeviceInformations, payload.object.common.role)) {
117
125
  roleAssign = this.roleAssignToDeviceInformations[payload.object.common.role];
package/main.js CHANGED
@@ -906,7 +906,7 @@ class Lorawan extends utils.Adapter {
906
906
  role: 'json',
907
907
  read: true,
908
908
  write: true,
909
- def: '',
909
+ def: 'applications, devices, currentIds',
910
910
  },
911
911
  native: {},
912
912
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.20.23",
3
+ "version": "1.20.25",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",