iobroker.lorawan 0.0.15 → 0.0.17

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
@@ -19,6 +19,12 @@ Adapter was created in collaboration with Joerg Froehner LoraWan@hafenmeister.co
19
19
  Placeholder for the next version (at the beginning of the line):
20
20
  ### **WORK IN PROGRESS**
21
21
  -->
22
+ ### 0.0.17 (2024-01-25)
23
+ * (BenAhrdt) changed Handling of standard configurations
24
+
25
+ ### 0.0.16 (2024-01-22)
26
+ * (BenAhrdt) romeve reacheble object directory / improoved object === NULL
27
+
22
28
  ### 0.0.15 (2024-01-21)
23
29
  * (BenAhrdt) bugfix chirpstack directory at downlink queued
24
30
 
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "0.0.15",
4
+ "version": "0.0.17",
5
5
  "news": {
6
+ "0.0.17": {
7
+ "en": "changed Handling of standard configurations",
8
+ "de": "geänderte Handhabung von Standardkonfigurationen",
9
+ "ru": "изменение обращения со стандартными конфигурациями",
10
+ "pt": "manipulação alterada de configurações padrão",
11
+ "nl": "veranderde verwerking van standaardconfiguraties",
12
+ "fr": "changement Gestion des configurations standard",
13
+ "it": "gestione delle configurazioni standard",
14
+ "es": "cambiado Manejo de configuraciones estándar",
15
+ "pl": "zmiana obsługi konfiguracji standardowych",
16
+ "uk": "змінено Обробка стандартних конфігурацій",
17
+ "zh-cn": "更改标准配置的处理"
18
+ },
19
+ "0.0.16": {
20
+ "en": "romeve reacheble object directory / improoved object === NULL",
21
+ "de": "romeve toucheble Objektverzeichnis / improoviertes Objekt == NULL",
22
+ "ru": "romeve reacheble object Directory / improoved object === NULL",
23
+ "pt": "romeve reacheble object diretório / objeto improoved - Sim",
24
+ "nl": "roeve bereikbare object directory / improoved object === NULL",
25
+ "fr": "romeve attele object directory / objet improvisé === NULL",
26
+ "it": "romeve catcheble object directory / oggetto improvato Traduzione:",
27
+ "es": "romeve reacheble objeto directorio / objeto improvisado === NULL",
28
+ "pl": "romeve Reacheble katalog obiektów / obiekt nieprofaworyzowany = = = NULL",
29
+ "uk": "romeve досягає каталогу об'єктів / об'єкт об'єкта ==== NULL",
30
+ "zh-cn": "romeve 达到对象目录/ 无法对象 QQ NULL 语言"
31
+ },
6
32
  "0.0.15": {
7
33
  "en": "bugfix chirpstack directory at downlink queued",
8
34
  "de": "bugfix chirpstack verzeichnis bei downlink queued",
@@ -67,32 +93,6 @@
67
93
  "pl": "toSend und lastSend dodany do folderów",
68
94
  "uk": "toSend und lastSend додано до папок",
69
95
  "zh-cn": "到文件夹中发送最后的发送"
70
- },
71
- "0.0.10": {
72
- "en": "changes in length calculation",
73
- "de": "änderungen der längenberechnung",
74
- "ru": "изменения в расчете длины",
75
- "pt": "alterações no cálculo de comprimento",
76
- "nl": "wijzigingen in de lengteberekening",
77
- "fr": "changements dans le calcul de la longueur",
78
- "it": "variazioni del calcolo della lunghezza",
79
- "es": "cambios en el cálculo de longitud",
80
- "pl": "zmiany w obliczeniach długości",
81
- "uk": "зміни розрахунку довжини",
82
- "zh-cn": "长度计算的变化"
83
- },
84
- "0.0.9": {
85
- "en": "first version for beta",
86
- "de": "erste version für beta",
87
- "ru": "первая версия для бета",
88
- "pt": "primeira versão para beta",
89
- "nl": "eerste versie voor beta",
90
- "fr": "première version pour bêta",
91
- "it": "prima versione per beta",
92
- "es": "primera versión para beta",
93
- "pl": "pierwsza wersja dla beta",
94
- "uk": "перша версія для бета",
95
- "zh-cn": "β的第一个版本"
96
96
  }
97
97
  },
98
98
  "title": "LoRaWAN",
@@ -38,8 +38,6 @@ class directorieshandlerClass {
38
38
  downlinkLastSend: "downlink.lastSend"
39
39
  };
40
40
 
41
- this.reachableDirectories = {};
42
-
43
41
  this.uplinks = new uplinkClass();
44
42
 
45
43
  // declare the directory structre
@@ -62,7 +60,6 @@ class directorieshandlerClass {
62
60
  objectCommonName: "device ID",
63
61
  objectType:"channel",
64
62
  configuration:{
65
- safeDirectory: this.safeableDirectories.configuration,
66
63
  devicetype:{
67
64
  isState: true,
68
65
  stateCommonType: "string",
@@ -71,24 +68,18 @@ class directorieshandlerClass {
71
68
  },
72
69
  uplink:{
73
70
  raw:{
74
- safeDirectory: this.safeableDirectories.uplinkRaw
75
71
  },
76
72
  decoded:{
77
- safeDirectory: this.safeableDirectories.uplinkDecoded
78
73
  },
79
74
  remaining:{
80
- safeDirectory: this.safeableDirectories.uplinkRemaining
81
75
  }
82
76
  },
83
77
  downlink:{
84
78
  raw:{
85
- safeDirectory: this.safeableDirectories.downlinkRaw
86
79
  },
87
80
  control:{
88
- safeDirectory: this.safeableDirectories.downlinkControl
89
81
  },
90
82
  configuration:{
91
- safeDirectory: this.safeableDirectories.downlinkConfiguration,
92
83
  },
93
84
  nextSend:{
94
85
  hex:{
@@ -103,7 +94,6 @@ class directorieshandlerClass {
103
94
  }
104
95
  },
105
96
  remaining:{
106
- safeDirectory: this.safeableDirectories.downlinkRemaining
107
97
  }
108
98
  },
109
99
  },
@@ -120,7 +110,6 @@ class directorieshandlerClass {
120
110
  stateCommonWrite: "stateCommonWrite",
121
111
  stateCommonUnit: "stateCommonUnit",
122
112
  isState: "isState",
123
- safeDirectory: "safeDirectory",
124
113
  subscribe: "subscribe"
125
114
  };
126
115
  }
@@ -133,7 +122,7 @@ class directorieshandlerClass {
133
122
  * ************************ Objectstring *****************************
134
123
  * ******************************************************************/
135
124
 
136
- async generateRekursivObjects(obj,startDirectory,topic,message,options = undefined){
125
+ async generateRekursivObjects(obj,startDirectory,topic,message,options){
137
126
  const activeFunction = "generateRekursivObjects";
138
127
  try{
139
128
  // just proceed with ojects
@@ -141,34 +130,23 @@ class directorieshandlerClass {
141
130
  // go to every element in the object
142
131
  for(const elementName in obj){
143
132
  // Check the the elementname is not in ignored object
144
- // @ts-ignore
145
133
  if(!this.ignoredElementNames[elementName] && !options?.ignoredElementNames[elementName]){
146
134
  // Check if the element is an object
147
135
  if(typeof obj[elementName] === "object" && !(obj[elementName] && obj[elementName].isState)){
148
136
  // if there is an declared ObjectStateName (must be a function)=> take it
149
137
  let objectId = `${startDirectory}.${elementName}`;
150
138
  let internalObjectId = elementName;
151
- if(obj[elementName].objectStateName){
139
+ if(obj[elementName] && obj[elementName].objectStateName){
152
140
  internalObjectId = `${await obj[elementName].objectStateName(topic,message)}`;
153
141
  objectId = `${startDirectory}.${internalObjectId}`;
154
142
  }
155
143
  if(objectId.indexOf(".") === 0){
156
144
  objectId = objectId.substring(1,objectId.length);
157
145
  }
158
- if(obj[elementName].safeDirectory){
159
- if(!this.reachableDirectories){
160
- this.reachableDirectories = {};
161
- }
162
- if(!this.reachableDirectories[await this.getObjectDirectory(topic,message,this.searchableAttributeNames.deviceId)]){
163
- this.reachableDirectories[await this.getObjectDirectory(topic,message,this.searchableAttributeNames.deviceId)] = {};
164
- }
165
- this.reachableDirectories[await this.getObjectDirectory(topic,message,this.searchableAttributeNames.deviceId)][obj[elementName].safeDirectory] = objectId;
166
- }
167
146
  await this.adapter.setObjectNotExistsAsync(objectId,{
168
- // @ts-ignore
169
- type: obj[elementName].objectType? obj[elementName].objectType : "folder",
147
+ type: obj[elementName]? obj[elementName].objectType? obj[elementName].objectType : "folder" : "folder",
170
148
  common: {
171
- name: obj[elementName].objectCommonName? obj[elementName].objectCommonName : ""
149
+ name: obj[elementName]? obj[elementName].objectCommonName? obj[elementName].objectCommonName : "" : ""
172
150
  },
173
151
  native : {},
174
152
  });
@@ -415,9 +393,8 @@ class directorieshandlerClass {
415
393
  if(adapterObject.type === "channel" && adapterObject.common.name !== "Information"){
416
394
  adapterObject._id = this.adapter.removeNamespace(adapterObject._id);
417
395
  const baseDeviceInfo = this.adapter.getBaseDeviceInfo(`${adapterObject._id}.deviceInfo`);
418
- if(baseDeviceInfo.obectStartDirectory === adapterObject._id){
396
+ if(adapterObject._id.indexOf(topicResolved.deviceUid) !== -1){
419
397
  devId = baseDeviceInfo.device_id;
420
- this.adapter.log.warn("Intern: " + devId);
421
398
  break;
422
399
  }
423
400
  }
@@ -453,12 +430,10 @@ class directorieshandlerClass {
453
430
  {
454
431
  devUid = message.devEui;
455
432
  }
456
- this.adapter.log.warn("DEV UID: " + devUid);
457
433
  if(devUid !== undefined){
458
434
  if(typeof message !== "string"){
459
435
  switch(resolvetype){
460
436
  case this.searchableAttributeNames.deviceId:
461
- this.adapter.log.warn(await this.getChirpstackAttributValue(topic,message,this.searchableAttributeNames.deviceId));
462
437
  return `${topicResolved?.applicationId}.devices.${devUid}.${await this.getChirpstackAttributValue(topic,message,this.searchableAttributeNames.deviceId)}`; // Hier muss die device id rein. (mussnoch mit async geholt werden)
463
438
 
464
439
  default:
@@ -1,35 +1,66 @@
1
- const downlinkClass = require("./downlinks/downlinks");
1
+ const fs = require("fs");
2
2
 
3
3
  class downlinkConfighandlerClass {
4
4
  constructor(adapter) {
5
5
  this.adapter = adapter;
6
-
7
- this.downlinks = new downlinkClass(adapter);
8
6
  this.activeDownlinkConfigs = {};
9
7
  }
10
8
 
11
-
12
9
  /*********************************************************************
13
10
  * *************************** General ******************************
14
11
  * ******************************************************************/
15
12
 
16
13
  addAndMergeDownlinkConfigs(){
14
+ const activeFunction = "addAndMergeDownlinkConfigs";
17
15
  this.adapter.log.silly(`the standard and configed downlinks will be merged`);
18
- // @ts-ignore
19
- for(const downlinkConfig of Object.values(this.downlinks.internalDownlinks)){
20
- this.addDownlinkConfigByType(downlinkConfig);
16
+ try{
17
+ const internalDownlinks = this.getJsonArrayFromDirectoryfiles(`${this.adapter.adapterDir}/lib/modules/downlinks`);
18
+ if(Array.isArray(internalDownlinks)){
19
+ for(const downlinkConfig of Object.values(internalDownlinks)){
20
+ this.addDownlinkConfigByType(downlinkConfig);
21
+ }
22
+ }
23
+ for(const downlinkConfig of Object.values(this.adapter.config.downlinkConfigAccordion)){
24
+ this.addDownlinkConfigByType(downlinkConfig);
25
+ }
21
26
  }
22
- for(const downlinkConfig of Object.values(this.adapter.config.downlinkConfigAccordion)){
23
- this.addDownlinkConfigByType(downlinkConfig);
27
+ catch(error){
28
+ this.adapter.log.error(`error at ${activeFunction}: ` + error);
29
+ return undefined;
24
30
  }
25
31
  }
26
32
 
27
33
  addDownlinkConfigByType(downlinkConfig){
28
- if(!this.activeDownlinkConfigs[downlinkConfig.deviceType]){
29
- this.activeDownlinkConfigs[downlinkConfig.deviceType] = {};
34
+ const activeFunction = "addDownlinkConfigByType";
35
+ try{
36
+ if(!this.activeDownlinkConfigs[downlinkConfig.deviceType]){
37
+ this.activeDownlinkConfigs[downlinkConfig.deviceType] = {};
38
+ }
39
+ if(!this.activeDownlinkConfigs[downlinkConfig.deviceType][downlinkConfig.name]){
40
+ this.activeDownlinkConfigs[downlinkConfig.deviceType][downlinkConfig.name] = downlinkConfig;
41
+ }
30
42
  }
31
- if(!this.activeDownlinkConfigs[downlinkConfig.deviceType][downlinkConfig.name]){
32
- this.activeDownlinkConfigs[downlinkConfig.deviceType][downlinkConfig.name] = downlinkConfig;
43
+ catch(error){
44
+ this.adapter.log.error(`error at ${activeFunction}: ` + error);
45
+ return undefined;
46
+ }
47
+ }
48
+
49
+ getJsonArrayFromDirectoryfiles(directory){
50
+ const activeFunction = "getJsonArrayFromDirectoryfiles";
51
+ this.adapter.log.silly(`the standard configs will readout from json files.`);
52
+ try{
53
+ let myJsonArray = [];
54
+ fs.readdirSync(directory).forEach(file => {
55
+ if(file.endsWith(".json")){
56
+ myJsonArray = myJsonArray.concat(JSON.parse(fs.readFileSync(`${directory}/${file}`, "utf-8")));
57
+ }
58
+ });
59
+ return myJsonArray;
60
+ }
61
+ catch(error){
62
+ this.adapter.log.error(`error at ${activeFunction}: ` + error);
63
+ return undefined;
33
64
  }
34
65
  }
35
66
 
@@ -38,11 +69,15 @@ class downlinkConfighandlerClass {
38
69
  this.adapter.log.silly(`the downlinkconfig is requested for the following changeinfo: ${JSON.stringify(changeInfo)}`);
39
70
  try{
40
71
  let downlinkConfig = undefined;
72
+ let foundLength = 0;
41
73
  for(const deviceType in this.activeDownlinkConfigs){
42
- if(changeInfo.deviceType.indexOf(deviceType) === 0 || deviceType === "all"){
74
+ if((deviceType === "all" || changeInfo.deviceType.indexOf(deviceType) === 0) && deviceType.length > foundLength){
43
75
  if(this.activeDownlinkConfigs[deviceType][changeInfo.changedState]){
44
76
  downlinkConfig = this.activeDownlinkConfigs[deviceType][changeInfo.changedState];
45
- break;
77
+ if(deviceType !== "all"){
78
+ foundLength = deviceType.length;
79
+ this.adapter.log.warn(deviceType + " state:" + changeInfo.changedState + " fl: " + foundLength);
80
+ }
46
81
  }
47
82
  }
48
83
  }
@@ -0,0 +1,131 @@
1
+ [
2
+ {
3
+ "name": "RO1_target",
4
+ "port": 1,
5
+ "priority": "NORMAL",
6
+ "type": "boolean",
7
+ "confirmed": true,
8
+ "front": "030111",
9
+ "end": "11",
10
+ "length": 8,
11
+ "on": "030111",
12
+ "off": "030011",
13
+ "multiplyfaktor": "1",
14
+ "unit": "",
15
+ "deviceType": "Dragino LT22222",
16
+ "onClick": "030111"
17
+ },
18
+ {
19
+ "name": "Intervall",
20
+ "port": 1,
21
+ "priority": "NORMAL",
22
+ "type": "number",
23
+ "confirmed": false,
24
+ "front": "01",
25
+ "end": "",
26
+ "length": 8,
27
+ "on": "11",
28
+ "off": "11",
29
+ "multiplyfaktor": 60,
30
+ "unit": "Minuten",
31
+ "deviceType": "Dragino LT22222",
32
+ "onClick": "030111",
33
+ "isConfiguration": true
34
+ },
35
+ {
36
+ "name": "RO2_target",
37
+ "port": 1,
38
+ "priority": "NORMAL",
39
+ "type": "boolean",
40
+ "confirmed": true,
41
+ "front": "03",
42
+ "end": "11",
43
+ "length": 2,
44
+ "on": "031101",
45
+ "off": "031100",
46
+ "multiplyfaktor": "1",
47
+ "unit": "",
48
+ "deviceType": "Dragino LT22222",
49
+ "onClick": "030111"
50
+ },
51
+ {
52
+ "name": "RPC_Level",
53
+ "port": 2,
54
+ "priority": "NORMAL",
55
+ "type": "boolean",
56
+ "confirmed": false,
57
+ "front": "03",
58
+ "end": "11",
59
+ "length": 2,
60
+ "on": "2104",
61
+ "off": "2100",
62
+ "multiplyfaktor": "1",
63
+ "unit": "",
64
+ "deviceType": "Dragino LT22222",
65
+ "onClick": "030111"
66
+ },
67
+ {
68
+ "name": "DO1_target",
69
+ "port": 1,
70
+ "priority": "NORMAL",
71
+ "type": "boolean",
72
+ "confirmed": true,
73
+ "front": "03",
74
+ "end": "11",
75
+ "length": 2,
76
+ "on": "02011111",
77
+ "off": "02001111",
78
+ "multiplyfaktor": "1",
79
+ "unit": "",
80
+ "deviceType": "Dragino LT22222",
81
+ "onClick": "030111"
82
+ },
83
+ {
84
+ "name": "DO2_target",
85
+ "port": 1,
86
+ "priority": "NORMAL",
87
+ "type": "boolean",
88
+ "confirmed": true,
89
+ "front": "03",
90
+ "end": "11",
91
+ "length": 2,
92
+ "on": "02110111",
93
+ "off": "02110011",
94
+ "multiplyfaktor": "1",
95
+ "unit": "",
96
+ "deviceType": "Dragino LT22222",
97
+ "onClick": "030111"
98
+ },
99
+ {
100
+ "name": "DO1_L_FOR_2_SEC",
101
+ "port": 1,
102
+ "priority": "NORMAL",
103
+ "type": "boolean",
104
+ "confirmed": false,
105
+ "front": "03",
106
+ "end": "11",
107
+ "length": 2,
108
+ "on": "A90001111107D0",
109
+ "off": "",
110
+ "multiplyfaktor": "1",
111
+ "unit": "",
112
+ "deviceType": "Dragino LT22222",
113
+ "onClick": "030111"
114
+ },
115
+ {
116
+ "name": "RO2_On_FOR_1_Min",
117
+ "port": 1,
118
+ "priority": "NORMAL",
119
+ "type": "boolean",
120
+ "confirmed": true,
121
+ "front": "03",
122
+ "end": "11",
123
+ "length": 2,
124
+ "on": "050021EA60",
125
+ "off": "",
126
+ "multiplyfaktor": "1",
127
+ "unit": "",
128
+ "deviceType": "Dragino LT22222",
129
+ "onClick": "030111"
130
+ }
131
+ ]
@@ -0,0 +1,35 @@
1
+ [
2
+ {
3
+ "name": "Intervall",
4
+ "port": 1,
5
+ "priority": "NORMAL",
6
+ "type": "number",
7
+ "confirmed": false,
8
+ "front": "01",
9
+ "end": "",
10
+ "length": 8,
11
+ "on": "",
12
+ "off": "",
13
+ "multiplyfaktor": 60,
14
+ "unit": "min",
15
+ "deviceType": "Dragino",
16
+ "isConfiguration": true
17
+ },
18
+ {
19
+ "name": "Reboot",
20
+ "port": 1,
21
+ "priority": "NORMAL",
22
+ "type": "button",
23
+ "confirmed": false,
24
+ "front": "",
25
+ "end": "",
26
+ "length": 4,
27
+ "on": "",
28
+ "off": "",
29
+ "onClick": "04FF",
30
+ "multiplyfaktor": "1",
31
+ "unit": "",
32
+ "deviceType": "Dragino",
33
+ "isConfiguration": true
34
+ }
35
+ ]
@@ -0,0 +1,12 @@
1
+ [
2
+ {
3
+ "name": "push",
4
+ "type": "json",
5
+ "deviceType": "all"
6
+ },
7
+ {
8
+ "name": "replace",
9
+ "type": "json",
10
+ "deviceType": "all"
11
+ }
12
+ ]
@@ -24,70 +24,90 @@ class messagehandlerClass {
24
24
 
25
25
  // Startup
26
26
  async generateDownlinkstatesAtStatup(){
27
- const adapterObjectsAtStart = await this.adapter.getAdapterObjectsAsync();
28
- for(const adapterObject of Object.values(adapterObjectsAtStart)){
29
- if(adapterObject.type === "channel" && adapterObject.common.name !== "Information"){
30
- const stateId = this.adapter.removeNamespace(adapterObject._id);
31
- await this.fillWithDownlinkConfig(stateId);
32
- await this.addDirectoriesToPresentDirectory(`${stateId}`);
27
+ const activeFunction = "generateDownlinkstatesAtStatup";
28
+ try{
29
+ const adapterObjectsAtStart = await this.adapter.getAdapterObjectsAsync();
30
+ for(const adapterObject of Object.values(adapterObjectsAtStart)){
31
+ if(adapterObject.type === "channel" && adapterObject.common.name !== "Information"){
32
+ const stateId = this.adapter.removeNamespace(adapterObject._id);
33
+ await this.fillWithDownlinkConfig(stateId);
34
+ await this.addDirectoriesToPresentDirectory(`${stateId}`);
35
+ }
33
36
  }
34
- }
35
37
 
36
- // remove not configed states
37
- for(const adapterObject of Object.values(adapterObjectsAtStart)){
38
- if(adapterObject.type === "state" && (adapterObject._id.indexOf("downlink.control") !== -1 || adapterObject._id.indexOf("downlink.configuration") !== -1)){
39
- const changeInfo = await this.adapter.getChangeInfo(adapterObject._id);
40
- const downlinkConfig = this.adapter.downlinkConfighandler.getDownlinkConfig(changeInfo,{startupCheck:true});
41
- if(!downlinkConfig){
42
- this.adapter.delObjectAsync(this.adapter.removeNamespace(adapterObject._id));
38
+ // remove not configed states
39
+ for(const adapterObject of Object.values(adapterObjectsAtStart)){
40
+ if(adapterObject.type === "state" && (adapterObject._id.indexOf("downlink.control") !== -1 || adapterObject._id.indexOf("downlink.configuration") !== -1)){
41
+ const changeInfo = await this.adapter.getChangeInfo(adapterObject._id);
42
+ const downlinkConfig = this.adapter.downlinkConfighandler.getDownlinkConfig(changeInfo,{startupCheck:true});
43
+ if(!downlinkConfig){
44
+ await this.adapter.delObjectAsync(this.adapter.removeNamespace(adapterObject._id));
45
+ }
43
46
  }
44
47
  }
45
48
  }
49
+ catch(error){
50
+ this.adapter.log.error(`error at ${activeFunction}: ` + error);
51
+ }
46
52
  }
47
53
 
54
+ //Add directories at startup (so theyare present before next upload)
48
55
  async addDirectoriesToPresentDirectory(startDirectory){
49
- this.directoryhandler.generateRekursivObjects(this.directoryhandler.directories.application.devices.deviceUid.deviceId.downlink.nextSend,`${startDirectory}.${this.directoryhandler.directoryStructur.downlinkNextSend}`,"","");
50
- this.directoryhandler.generateRekursivObjects(this.directoryhandler.directories.application.devices.deviceUid.deviceId.downlink.lastSend,`${startDirectory}.${this.directoryhandler.directoryStructur.downlinkLastSend}`,"","");
56
+ await this.directoryhandler.generateRekursivObjects(this.directoryhandler.directories.application.devices.deviceUid.deviceId.downlink.nextSend,`${startDirectory}.${this.directoryhandler.directoryStructur.downlinkNextSend}`,"","");
57
+ await this.directoryhandler.generateRekursivObjects(this.directoryhandler.directories.application.devices.deviceUid.deviceId.downlink.lastSend,`${startDirectory}.${this.directoryhandler.directoryStructur.downlinkLastSend}`,"","");
51
58
  }
52
59
 
53
60
  async fillWithDownlinkConfig(deviceStartdirectory){
54
- for(const downlinkDevices of Object.values(this.adapter.downlinkConfighandler.activeDownlinkConfigs)){
55
- for(const downlinkConfig of Object.values(downlinkDevices)){
56
- this.adapter.log.silly(`the downlinkconfig ${JSON.stringify(downlinkConfig)}, will checked.`);
57
- let startDirectory = "";
58
- if(!downlinkConfig.isConfiguration){
59
- startDirectory = `${deviceStartdirectory}.downlink.control`;
60
- }
61
- else{
62
- startDirectory = `${deviceStartdirectory}.downlink.configuration`;
63
- }
64
- const changeInfo = await this.adapter.getChangeInfo(`${startDirectory}.${downlinkConfig.name}`);
65
- if(downlinkConfig.deviceType === "all" || downlinkConfig.deviceType === changeInfo.deviceType || changeInfo.deviceType.indexOf(downlinkConfig.deviceType) === 0){
66
- let commonStateRole = "value";
67
- let commonStateType = downlinkConfig.type;
68
- if(commonStateType === "button"){
69
- commonStateType = "boolean";
70
- commonStateRole = "button";
61
+ const activeFunction = "fillWithDownlinkConfig";
62
+ try{
63
+ const foundLength = {};
64
+ for(const downlinkDevices of Object.values(this.adapter.downlinkConfighandler.activeDownlinkConfigs)){
65
+ for(const downlinkConfig of Object.values(downlinkDevices)){
66
+ this.adapter.log.silly(`the downlinkconfig ${JSON.stringify(downlinkConfig)}, will checked.`);
67
+ let startDirectory = "";
68
+ if(!downlinkConfig.isConfiguration){
69
+ startDirectory = `${deviceStartdirectory}.downlink.control`;
71
70
  }
72
- else if(commonStateType === "ascii"){
73
- commonStateType = "string";
71
+ else{
72
+ startDirectory = `${deviceStartdirectory}.downlink.configuration`;
73
+ }
74
+ const changeInfo = await this.adapter.getChangeInfo(`${startDirectory}.${downlinkConfig.name}`);
75
+ if(!foundLength[changeInfo.changedState]){
76
+ foundLength[changeInfo.changedState] = 0;
77
+ }
78
+ if((downlinkConfig.deviceType === "all" || changeInfo.deviceType.indexOf(downlinkConfig.deviceType) === 0) && downlinkConfig.deviceType.length > foundLength[changeInfo.changedState]){
79
+ let commonStateRole = "value";
80
+ let commonStateType = downlinkConfig.type;
81
+ if(commonStateType === "button"){
82
+ commonStateType = "boolean";
83
+ commonStateRole = "button";
84
+ }
85
+ else if(commonStateType === "ascii"){
86
+ commonStateType = "string";
87
+ }
88
+ await this.adapter.setObjectAsync(`${startDirectory}.${downlinkConfig.name}`,{
89
+ type: "state",
90
+ common: {
91
+ name: "",
92
+ type: commonStateType,
93
+ role: commonStateRole,
94
+ read: true,
95
+ write: true,
96
+ unit: downlinkConfig.unit? downlinkConfig.unit:"",
97
+ def: commonStateType === "boolean"? false : commonStateType === "number"? 0: "",
98
+ },
99
+ native: {},
100
+ });
101
+ if(downlinkDevices !=="all"){
102
+ foundLength[changeInfo.changedState] = downlinkConfig.deviceType.length;
103
+ }
74
104
  }
75
- await this.adapter.setObjectNotExistsAsync(`${startDirectory}.${downlinkConfig.name}`,{
76
- type: "state",
77
- common: {
78
- name: "",
79
- type: commonStateType,
80
- role: commonStateRole,
81
- read: true,
82
- write: true,
83
- unit: downlinkConfig.unit? downlinkConfig.unit:"",
84
- def: commonStateType === "boolean"? false : commonStateType === "number"? 0: "",
85
- },
86
- native: {},
87
- });
88
105
  }
89
106
  }
90
107
  }
108
+ catch(error){
109
+ this.adapter.log.error(`error at ${activeFunction}: ` + error);
110
+ }
91
111
  }
92
112
 
93
113
  /*****************************************************************************************************************
@@ -222,7 +242,7 @@ class messagehandlerClass {
222
242
 
223
243
  startDirectory = `${deviceStartdirectory}.${this.directoryhandler.reachableSubfolders.uplinkRemaining}`;
224
244
  this.adapter.log.silly(`write remaining uplink data`);
225
- // @ts-ignore
245
+
226
246
  await this.directoryhandler.generateRekursivObjects(message.uplink_message,startDirectory,topic,message,{ignoredElementNames:{decoded_payload:{},frm_payload:{}}});
227
247
  }
228
248
 
@@ -315,7 +335,6 @@ class messagehandlerClass {
315
335
 
316
336
  startDirectory = `${deviceStartdirectory}.${this.directoryhandler.reachableSubfolders.downlinkRemaining}`;
317
337
  this.adapter.log.silly(`write remaining downlink data`);
318
- // @ts-ignore
319
338
  await this.directoryhandler.generateRekursivObjects(message[downlinkType],startDirectory,topic,message,{ignoredElementNames:{frm_payload:{}}});
320
339
  }
321
340
 
@@ -458,7 +477,6 @@ class messagehandlerClass {
458
477
 
459
478
  startDirectory = `${deviceStartdirectory}.${this.directoryhandler.reachableSubfolders.uplinkRemaining}`;
460
479
  this.adapter.log.silly(`write remaining uplink data`);
461
- // @ts-ignore
462
480
  await this.directoryhandler.generateRekursivObjects(message,startDirectory,topic,message,{ignoredElementNames:{deduplicationId:{},deviceInfo:{},data:{},object:{}}});
463
481
  }
464
482
 
package/main.js CHANGED
@@ -53,8 +53,9 @@ class Lorawan extends utils.Adapter {
53
53
  this.subscribeStatesAsync("*.configuration.*");
54
54
  this.subscribeStatesAsync("*downlink.control.*");
55
55
  this.log.debug(`the adapter start with the config: ${JSON.stringify(this.config)}.`);
56
+ this.log.silly(`the whole reacable downlinkconfigs are: ${JSON.stringify(this.downlinkConfighandler.activeDownlinkConfigs)}`);
56
57
 
57
- /* setTimeout(async () => {
58
+ /*setTimeout(async () => {
58
59
  await this.startSimulation();
59
60
  }, 5000);*/
60
61
  }
@@ -65,10 +66,20 @@ class Lorawan extends utils.Adapter {
65
66
 
66
67
  async startSimulation(){
67
68
 
69
+ // const topic ="v3/hafi-ttn-lorawan@ttn/devices/eui-lobaro-modbus/up";
70
+ // const message = {"end_device_ids":{"device_id":"eui-lobaro-modbus","application_ids":{"application_id":"hafi-ttn-lorawan"},"dev_eui":"70B3D5E050013950","join_eui":"D55B58C0DDC074DE","dev_addr":"260B5972"},"correlation_ids":["gs:uplink:01HMQZVSCX4D7JRDNFA7GJ9D4W"],"received_at":"2024-01-22T07:06:25.260676101Z","uplink_message":{"session_key_id":"AY0v/ZirzRkpNW0Cgjdhig==","f_port":20,"f_cnt":2,"frm_payload":"AA5BAf0AxwIAAQ==","decoded_payload":{"airhumidity":50.9,"airtemperature":19.9,"port":20,"relais1":0,"relais2":1,"relais3":null,"relais5":null,"volt":3.649,"zisternenpegel":2},"rx_metadata":[{"gateway_ids":{"gateway_id":"hafenmeister-port2ttn-ng","eui":"50313953530A4750"},"time":"2024-01-22T07:06:25.013878Z","timestamp":995696116,"rssi":-37,"channel_rssi":-37,"snr":8.5,"location":{"latitude":53.5548443059465,"longitude":9.92155426743724,"altitude":10,"source":"SOURCE_REGISTRY"},"uplink_token":"CiYKJAoYaGFmZW5tZWlzdGVyLXBvcnQydHRuLW5nEghQMTlTUwpHUBD0u+TaAxoLCPGnuK0GEM3uvhkgoIL0oP24Sg==","channel_index":5,"received_at":"2024-01-22T07:06:25.032492359Z"}],"settings":{"data_rate":{"lora":{"bandwidth":125000,"spreading_factor":9,"coding_rate":"4/5"}},"frequency":"867500000","timestamp":995696116,"time":"2024-01-22T07:06:25.013878Z"},"received_at":"2024-01-22T07:06:25.054442349Z","consumed_airtime":"0.205824s","network_ids":{"net_id":"000013","ns_id":"EC656E0000000181","tenant_id":"ttn","cluster_id":"eu1","cluster_address":"eu1.cloud.thethings.network"}}};
71
+
72
+
68
73
  //const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a84041f621857cd2/event/up";
69
74
  //const message = {"deduplicationId":"96e4a065-ad5e-402d-a997-7b261072a33c","time":"2024-01-21T17:01:36.641008+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"d63c10b6-9263-4ab3-9299-4308fa19a2ad","applicationName":"Benjamin Schmidt","deviceProfileId":"0b46400f-37ec-4f17-8005-168b06159347","deviceProfileName":"Dragino Feuchtesenor","deviceName":"Skimmer","devEui":"a84041f621857cd2","deviceClassEnabled":"CLASS_A","tags":{}},"devAddr":"01fd9738","adr":true,"dr":5,"fCnt":2,"fPort":2,"confirmed":false,"data":"DPYBAAD//wAA","object":{"soilconductivity":0.0,"soiltemperature":-0.1,"volt":3.318,"soilmoisture":0.0},"rxInfo":[{"gatewayId":"50303541b0344750","uplinkId":39169,"gwTime":"2024-01-21T17:01:36.641008+00:00","nsTime":"2024-01-21T17:01:37.695656999+00:00","rssi":-89,"snr":6.25,"rfChain":1,"location":{"latitude":50.69344693065449,"longitude":8.476783633232118},"context":"qESemw==","metadata":{"region_config_id":"eu868","region_common_name":"EU868"},"crcStatus":"CRC_OK"}],"txInfo":{"frequency":868100000,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5"}}}};
70
- const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a84041f621857cd2/command/down";
71
- const message = {"devEui":"a84041f621857cd2","confirmed":false,"fPort":1,"data":"AQAqMA=="};
75
+ //const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a84041f621857cd2/command/down";
76
+ //const message = {"devEui":"a84041f621857cd2","confirmed":false,"fPort":1,"data":"AQAqMA=="};
77
+
78
+ // Chirpstack LT222222
79
+ //const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a8404127a188d826/event/up";
80
+ //const message = {"deduplicationId":"bd3fdb3b-af86-4617-b9f2-da07075d2bc5","time":"2024-01-24T16:47:01.573381+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"d63c10b6-9263-4ab3-9299-4308fa19a2ad","applicationName":"Benjamin Schmidt","deviceProfileId":"f1c0ae0e-b4a2-4547-b360-7cfa15e85734","deviceProfileName":"Dragino LT22222","deviceName":"Relaistestgerät","devEui":"a8404127a188d826","deviceClassEnabled":"CLASS_C","tags":{}},"devAddr":"01dfbaf2","adr":true,"dr":5,"fCnt":12,"fPort":2,"confirmed":false,"data":"AAAAAAAAAAA8/0E=","object":{"RO1_status":"OFF","DO2_status":"H","ACI2_mA":0.0,"DO1_status":"H","Hardware_mode":"LT22222","RO2_status":"OFF","AVI2_V":0.0,"ACI1_mA":0.0,"DI1_status":"H","DI2_status":"H","Work_mode":"2ACI+2AVI","AVI1_V":0.0},"rxInfo":[{"gatewayId":"50303541b0344750","uplinkId":57857,"gwTime":"2024-01-24T16:47:01.573381+00:00","nsTime":"2024-01-24T16:47:02.370171527+00:00","rssi":-54,"snr":8.5,"channel":6,"location":{"latitude":50.69344693065449,"longitude":8.476783633232118},"context":"2tr9BA==","metadata":{"region_config_id":"eu868","region_common_name":"EU868"},"crcStatus":"CRC_OK"}],"txInfo":{"frequency":867700000,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5"}}}};
81
+ const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a8404127a188d826/command/down";
82
+ const message = {"devEui":"a8404127a188d826","confirmed":false,"fPort":1,"data":"AQACWA=="};
72
83
  await this.messagehandler?.handleMessage(topic, message);
73
84
  }
74
85
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",
@@ -1,52 +0,0 @@
1
-
2
- class downlinksClass {
3
- constructor(adapter) {
4
- this.internalDownlinks = [
5
- {
6
- name: "Intervall",
7
- port: 1,
8
- priority: "NORMAL",
9
- type: "number",
10
- confirmed: false,
11
- front: "01",
12
- end: "",
13
- length: 8,
14
- on: "11",
15
- off: "11",
16
- multiplyfaktor: 60,
17
- unit: "min",
18
- deviceType: "Dragino",
19
- isConfiguration: true
20
- }
21
- ];
22
- // Select downlink in case of origin
23
- switch(adapter.config.origin){
24
- case "ttn":
25
- this.internalDownlinks.unshift(
26
- // @ts-ignore
27
- {
28
- name: "push",
29
- type: "json",
30
- deviceType: "all"
31
- },
32
- {
33
- name: "replace",
34
- type: "json",
35
- deviceType: "all"
36
- });
37
- break;
38
- case "chirpstack":
39
- this.internalDownlinks.unshift(
40
- // @ts-ignore
41
- {
42
- name: "push",
43
- type: "json",
44
- deviceType: "all"
45
- });
46
- }
47
- }
48
-
49
-
50
- }
51
-
52
- module.exports = downlinksClass;