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 +6 -0
- package/io-package.json +27 -27
- package/lib/modules/directorieshandler.js +5 -30
- package/lib/modules/downlinkConfighandler.js +50 -15
- package/lib/modules/downlinks/Dragino LT22222.json +131 -0
- package/lib/modules/downlinks/Dragino.json +35 -0
- package/lib/modules/downlinks/all.json +12 -0
- package/lib/modules/messagehandler.js +69 -51
- package/main.js +14 -3
- package/package.json +1 -1
- package/lib/modules/downlinks/downlinks.js +0 -52
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.
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
23
|
-
this.
|
|
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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
this.
|
|
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
|
|
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
|
-
|
|
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
|
+
]
|
|
@@ -24,70 +24,90 @@ class messagehandlerClass {
|
|
|
24
24
|
|
|
25
25
|
// Startup
|
|
26
26
|
async generateDownlinkstatesAtStatup(){
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,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;
|