iobroker.lorawan 1.13.0 → 1.13.1

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,11 @@ 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.13.1 (2025-09-04)
27
+ * (BenAhrdt) More Debuglogging
28
+ * (BenAhrdt) General Nameing in the functions
29
+ * (BenAhrdt) Performance update fpr rediscover on cron.
30
+
26
31
  ### 1.13.0 (2025-09-03)
27
32
  * (BenAhrdt) Build fist Version of own Bridge MQTT Client
28
33
 
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.13.0",
4
+ "version": "1.13.1",
5
5
  "news": {
6
+ "1.13.1": {
7
+ "en": "More Debuglogging\nGeneral Nameing in the functions\nPerformance update fpr rediscover on cron.",
8
+ "de": "Mehr zum Debuglogging\nAllgemeine Bezeichnung in den Funktionen\nPerformance Update fpr rediscover auf cron.",
9
+ "ru": "Больше Debuglogging\nОбщее наименование в функциях\nОбновление производительности fpr вновь открывается на cron.",
10
+ "pt": "Mais Depuração\nNomeação Geral nas funções\nAtualização de desempenho fpr redescobrir no cron.",
11
+ "nl": "Meer debuggen\nAlgemene naamgeving in de functies\nPrestatie-update fpr herontdekken op cron.",
12
+ "fr": "Plus de débogage\nNom général dans les fonctions\nMise à jour de performance fpr redécouvrir sur cron.",
13
+ "it": "Altre informazioni\nNome generale nelle funzioni\nAggiornamento delle prestazioni fpr riscoprire su cron.",
14
+ "es": "Más Debuglogging\nNombre general en las funciones\nActualización de rendimiento fpr redescover en cron.",
15
+ "pl": "Więcej Debuglogging\nOgólne Napisywanie w funkcjach\nAktualizacja wydajności fpr ponownie odkryć na cron.",
16
+ "uk": "Детальніше Debuglog\nЗагальна назва функції\nОновлення продуктивності fpr rediscover на cron.",
17
+ "zh-cn": "更多调试日志\n函数中的名称\n性能更新 fpr 重新发现于 cron."
18
+ },
6
19
  "1.13.0": {
7
20
  "en": "Build fist Version of own Bridge MQTT Client",
8
21
  "de": "Erstellen Sie fist Version des eigenen Bridge MQTT Client",
@@ -80,19 +93,6 @@
80
93
  "pl": "adapter log Obiekty na początku",
81
94
  "uk": "адаптер Об'єкти при старті",
82
95
  "zh-cn": "日志适配器 起始对象"
83
- },
84
- "1.11.7": {
85
- "en": "more improov logging in case of deviceinformation at startup (debug)",
86
- "de": "mehr improov protokollierung bei geräteinformationen beim start (debug)",
87
- "ru": "более импровизированная регистрация в случае информации об устройстве при запуске (отладка)",
88
- "pt": "registro mais improov em caso de informação do dispositivo na inicialização (debug)",
89
- "nl": "meer improov loggen in geval van apparaatinformatie bij opstarten (debug)",
90
- "fr": "l'enregistrement plus improov en cas d'information de périphérique au démarrage (debug)",
91
- "it": "più improov registrazione in caso di informazioni del dispositivo all'avvio (debug)",
92
- "es": "logging más improov en caso de información de dispositivo al inicio (debug)",
93
- "pl": "więcej logowania improov w przypadku informacji deviceinformation at startup (debug)",
94
- "uk": "більше непроваджених журналів у разі реєстрації пристрою",
95
- "zh-cn": "在启动时发生设备信息( 调试) 时进行更多即兴记录"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -18,6 +18,7 @@ class bridgeClass {
18
18
  this.bridgeMqttClient = new bridgeMqttClientClass(this.adapter, this.adapter.config);
19
19
 
20
20
  // Structure of actual vaulues in Bridge (till las start of Adapter)
21
+ this.CheckedIds = {};
21
22
  this.DiscoveredIds = {};
22
23
  this.SubscribedTopics = {};
23
24
  this.PulishedIds = {};
@@ -28,75 +29,69 @@ class bridgeClass {
28
29
  this.DiscoveryCronjob = {};
29
30
  }
30
31
 
32
+ /*********************************************************************
33
+ * ********************* Message vom der Bridge **********************
34
+ * ******************************************************************/
35
+
31
36
  /**
32
- * @param ms deleay in ms
37
+ * @param topic topic of the foreign system message
38
+ * @param message message of the foreign system
33
39
  */
34
- async delay(ms) {
35
- return new Promise(resolve => setTimeout(resolve, ms));
40
+ async handleMessage(topic, message) {
41
+ const activeFunction = 'bridge.js - handleMessage';
42
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
43
+ try {
44
+ if (this.SubscribedTopics[topic]) {
45
+ this.SubscribedTopics[topic].val = message;
46
+ this.SubscribedTopics[topic].ts = Date.now();
47
+ if (
48
+ !this.PulishedIds[this.SubscribedTopics[topic].id] ||
49
+ this.PulishedIds[this.SubscribedTopics[topic].id].val !== message ||
50
+ Date.now() - this.PulishedIds[this.SubscribedTopics[topic].id].ts > this.MinTime
51
+ ) {
52
+ await this.adapter.setState(this.SubscribedTopics[topic].id, message);
53
+ }
54
+ }
55
+ } catch (error) {
56
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
57
+ }
36
58
  }
37
59
 
38
60
  /**
39
- * @param Id Id of actual element, handled in the bridge
61
+ * @param id Id of actual element, handled in the bridge
40
62
  * @param Stateval Value of the used Id
41
63
  * @param options Options for using spezial fuctions
42
64
  */
43
- async work(Id, Stateval, options) {
65
+ async work(id, Stateval, options) {
44
66
  const activeFunction = 'bridge.js - work';
45
67
  this.adapter.log.debug(`Function ${activeFunction} started.`);
46
68
  try {
47
69
  if (this.bridgeMqttClient.internalConnectionstate) {
48
- await this.discovery(Id, options);
49
- await this.publish(Id, Stateval);
70
+ await this.discovery(id, options);
71
+ await this.publishId(id, Stateval);
50
72
  }
51
73
  } catch (error) {
52
74
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
53
75
  }
54
76
  }
55
77
 
56
- /*********************************************************************
57
- * ***************** Discover all defined State **********************
58
- * ******************************************************************/
59
-
60
- /**
61
- * Discover all defined States (maby at Startup)
62
- *
63
- * @param options options to special functions
64
- */
65
- async discoverDefinedStates(options) {
66
- // Get all ids in adapterfolder
67
- // Generate Infos of all devices and decoded folders
68
- const adapterObjects = await this.adapter.getAdapterObjectsAsync();
69
- for (const adapterObject of Object.values(adapterObjects)) {
70
- if (
71
- adapterObject._id.includes(
72
- `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.`,
73
- ) ||
74
- adapterObject._id.includes(
75
- `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.downlinkControl}.`,
76
- )
77
- ) {
78
- if (adapterObject.type === 'state') {
79
- if (!options) {
80
- options = {};
81
- }
82
- options.common = adapterObject.common;
83
- await this.work(adapterObject._id, undefined, options);
84
- }
85
- }
86
- }
87
- }
88
-
89
78
  /*********************************************************************
90
79
  * ********************* Discover zur Bridge *************************
91
80
  * ******************************************************************/
92
81
 
93
82
  /**
94
- * @param Id Id, wich is to discover
83
+ * @param id Id, wich is to discover
95
84
  * @param options Options for using spezial fuctions
96
85
  */
97
- async discovery(Id, options) {
98
- if (!this.DiscoveredIds[Id] || (options && options.forceDiscovery)) {
99
- await this.buildDiscovery(Id, options);
86
+ async discovery(id, options) {
87
+ const activeFunction = 'bridge.js - discovery';
88
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
89
+ try {
90
+ if (!this.CheckedIds[id] || (options && options.forceDiscovery)) {
91
+ await this.buildDiscovery(id, options);
92
+ }
93
+ } catch (error) {
94
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
100
95
  }
101
96
  }
102
97
 
@@ -105,134 +100,139 @@ class bridgeClass {
105
100
  * ******************************************************************/
106
101
 
107
102
  /**
108
- * @param Id Id, wich is to discover
103
+ * @param id Id, wich is to discover
109
104
  * @param val Value of the used Id
110
105
  */
111
- async publish(Id, val) {
112
- if (this.PulishedIds[Id]) {
113
- if (val === undefined) {
114
- const State = await this.adapter.getState(Id);
115
- if (State) {
116
- val = State.val;
106
+ async publishId(id, val) {
107
+ const activeFunction = 'bridge.js - publish';
108
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
109
+ try {
110
+ if (this.PulishedIds[id]) {
111
+ if (val === undefined) {
112
+ const State = await this.adapter.getState(id);
113
+ if (State) {
114
+ val = State.val;
115
+ }
116
+ }
117
+ if (
118
+ !this.SubscribedTopics[this.PulishedIds[id].Topic] ||
119
+ this.SubscribedTopics[this.PulishedIds[id].Topic].val !== val ||
120
+ Date.now() - this.SubscribedTopics[this.PulishedIds[id].Topic].ts > this.MinTime
121
+ ) {
122
+ this.PulishedIds[id].ts = Date.now();
123
+ this.PulishedIds[id].val = val;
124
+ await this.bridgeMqttClient.publish(this.PulishedIds[id].Topic, JSON.stringify(val), {
125
+ retain: true,
126
+ });
117
127
  }
118
128
  }
119
- if (
120
- !this.SubscribedTopics[this.PulishedIds[Id].Topic] ||
121
- this.SubscribedTopics[this.PulishedIds[Id].Topic].val !== val ||
122
- Date.now() - this.SubscribedTopics[this.PulishedIds[Id].Topic].ts > this.MinTime
123
- ) {
124
- this.PulishedIds[Id].ts = Date.now();
125
- this.PulishedIds[Id].val = val;
126
- await this.bridgeMqttClient.publish(this.PulishedIds[Id].Topic, JSON.stringify(val), { retain: true });
127
- }
129
+ } catch (error) {
130
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
128
131
  }
129
132
  }
130
133
 
131
134
  /**
132
- * @param Id Id of actual element
135
+ * @param id Id of actual element
133
136
  * @param options Options for using spezial fuctions
134
137
  */
135
- async buildDiscovery(Id, options) {
136
- // Query for decoded Folder
137
- if (Id.indexOf(`${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.`) !== -1) {
138
- const changeInfo = await this.adapter.getChangeInfo(Id);
139
- const Bridgestate = {
140
- discover: false,
141
- publish: false,
142
- subscribe: false,
143
- };
144
- // Query for Stateconfig
145
- if (this.adapter.config.BridgeStateConfig) {
146
- for (const config of this.adapter.config.BridgeStateConfig) {
147
- if (
148
- (changeInfo.applicationId === config.Application || config.Application === '*') &&
149
- (changeInfo.deviceEUI === config.Device || config.Device === '*') &&
150
- (Id.includes(`.${config.Folder}.`) || config.Folder === '*') &&
151
- (Id.endsWith(
152
- `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.${config.State}`,
153
- ) ||
154
- config.State === '*')
155
- ) {
156
- Bridgestate.discover = !config.exclude;
157
- Bridgestate.publish = config.publish;
158
- if (config.exclude) {
159
- break;
138
+ async buildDiscovery(id, options) {
139
+ const activeFunction = 'bridge.js - publbuildDiscoveryish';
140
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
141
+ try {
142
+ // Query for decoded Folder
143
+ if (id.includes(`${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.`)) {
144
+ const changeInfo = await this.adapter.getChangeInfo(id);
145
+ const Bridgestate = {
146
+ discover: false,
147
+ publish: false,
148
+ subscribe: false,
149
+ };
150
+ // Query for Stateconfig
151
+ if (this.adapter.config.BridgeStateConfig) {
152
+ for (const config of this.adapter.config.BridgeStateConfig) {
153
+ if (
154
+ (changeInfo.applicationId === config.Application || config.Application === '*') &&
155
+ (changeInfo.deviceEUI === config.Device || config.Device === '*') &&
156
+ (id.includes(`.${config.Folder}.`) || config.Folder === '*') &&
157
+ (id.endsWith(
158
+ `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.${config.State}`,
159
+ ) ||
160
+ config.State === '*')
161
+ ) {
162
+ Bridgestate.discover = !config.exclude;
163
+ Bridgestate.publish = config.publish;
164
+ if (config.exclude) {
165
+ break;
166
+ }
160
167
  }
161
168
  }
162
- }
163
- if (Bridgestate.discover) {
164
- options.Bridgestate = Bridgestate;
165
- const DiscoveryObject = await this.getDiscoveryObject(Id, changeInfo, options);
166
- this.DiscoveredIds[Id] = DiscoveryObject;
167
- if (Bridgestate.publish) {
168
- this.PulishedIds[Id] = DiscoveryObject;
169
- this.PulishedIds[Id].val = 0;
170
- this.PulishedIds[Id].ts = Date.now();
171
- }
172
- if (Bridgestate.subscribe) {
173
- this.SubscribedTopics[DiscoveryObject.Topic] = {};
174
- this.SubscribedTopics[DiscoveryObject.Topic].id = Id;
175
- this.SubscribedTopics[DiscoveryObject.Topic].val = 0;
176
- this.SubscribedTopics[DiscoveryObject.Topic].ts = Date.now();
169
+ if (Bridgestate.discover) {
170
+ options.Bridgestate = Bridgestate;
171
+ const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
172
+ if (Bridgestate.publish) {
173
+ this.PulishedIds[id] = DiscoveryObject;
174
+ this.PulishedIds[id].val = 0;
175
+ this.PulishedIds[id].ts = Date.now();
176
+ }
177
+ if (Bridgestate.subscribe) {
178
+ this.SubscribedTopics[DiscoveryObject?.Topic] = {};
179
+ this.SubscribedTopics[DiscoveryObject?.Topic].id = id;
180
+ this.SubscribedTopics[DiscoveryObject?.Topic].val = 0;
181
+ this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now();
182
+ }
183
+ await this.publishDiscovery(id, DiscoveryObject);
177
184
  }
178
- await this.bridgeMqttClient.publish(
179
- DiscoveryObject.DiscoveryTopic,
180
- JSON.stringify(DiscoveryObject.DiscoveryPayload),
181
- {},
182
- );
183
185
  }
184
- }
185
186
 
186
- // Query for Control Folder
187
- } else if (
188
- Id.indexOf(`${this.adapter.messagehandler.directoryhandler.reachableSubfolders.downlinkControl}.`) !== -1
189
- ) {
190
- const changeInfo = await this.adapter.getChangeInfo(Id);
191
- const Bridgestate = {
192
- discover: false,
193
- publish: false,
194
- subscribe: false,
195
- };
196
- // Query for Stateconfig
197
- if (this.adapter.config.BridgeStateConfig) {
198
- for (const config of this.adapter.config.BridgeStateConfig) {
199
- if (
200
- (changeInfo.applicationId === config.Application || config.Application === '*') &&
201
- (changeInfo.deviceEUI === config.Device || config.Device === '*') &&
202
- (Id.includes(`.${config.Folder}.`) || config.Folder === '*') &&
203
- (Id.endsWith(
204
- `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.downlinkControl}.${config.State}`,
205
- ) ||
206
- config.State === '*')
207
- ) {
208
- Bridgestate.discover = !config.exclude;
209
- Bridgestate.publish = config.publish;
210
- Bridgestate.subscribe = config.subscribe;
211
- if (config.exclude) {
212
- break;
187
+ // Query for Control Folder
188
+ } else if (
189
+ id.includes(`${this.adapter.messagehandler.directoryhandler.reachableSubfolders.downlinkControl}.`)
190
+ ) {
191
+ const changeInfo = await this.adapter.getChangeInfo(id);
192
+ const Bridgestate = {
193
+ discover: false,
194
+ publish: false,
195
+ subscribe: false,
196
+ };
197
+ // Query for Stateconfig
198
+ if (this.adapter.config.BridgeStateConfig) {
199
+ for (const config of this.adapter.config.BridgeStateConfig) {
200
+ if (
201
+ (changeInfo.applicationId === config.Application || config.Application === '*') &&
202
+ (changeInfo.deviceEUI === config.Device || config.Device === '*') &&
203
+ (id.includes(`.${config.Folder}.`) || config.Folder === '*') &&
204
+ (id.endsWith(
205
+ `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.downlinkControl}.${config.State}`,
206
+ ) ||
207
+ config.State === '*')
208
+ ) {
209
+ Bridgestate.discover = !config.exclude;
210
+ Bridgestate.publish = config.publish;
211
+ Bridgestate.subscribe = config.subscribe;
212
+ if (config.exclude) {
213
+ break;
214
+ }
213
215
  }
214
216
  }
215
- }
216
- if (Bridgestate.discover) {
217
- options.Bridgestate = Bridgestate;
218
- const DiscoveryObject = await this.getDiscoveryObject(Id, changeInfo, options);
219
- this.DiscoveredIds[Id] = DiscoveryObject;
220
- if (Bridgestate.publish) {
221
- this.PulishedIds[Id] = DiscoveryObject;
222
- }
223
- if (Bridgestate.subscribe) {
224
- this.SubscribedTopics[DiscoveryObject.Topic] = {};
225
- this.SubscribedTopics[DiscoveryObject.Topic].id = Id;
226
- this.SubscribedTopics[DiscoveryObject.Topic].val = 0;
227
- this.SubscribedTopics[DiscoveryObject.Topic].ts = Date.now();
217
+ if (Bridgestate.discover) {
218
+ options.Bridgestate = Bridgestate;
219
+ const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
220
+ if (Bridgestate.publish) {
221
+ this.PulishedIds[id] = DiscoveryObject;
222
+ }
223
+ if (Bridgestate.subscribe) {
224
+ this.SubscribedTopics[DiscoveryObject?.Topic] = {};
225
+ this.SubscribedTopics[DiscoveryObject?.Topic].id = id;
226
+ this.SubscribedTopics[DiscoveryObject?.Topic].val = 0;
227
+ this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now();
228
+ }
229
+ await this.publishDiscovery(id, DiscoveryObject);
228
230
  }
229
- await this.bridgeMqttClient.publish(
230
- DiscoveryObject.DiscoveryTopic,
231
- JSON.stringify(DiscoveryObject.DiscoveryPayload),
232
- {},
233
- );
234
231
  }
235
232
  }
233
+ this.CheckedIds[id] = {};
234
+ } catch (error) {
235
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
236
236
  }
237
237
  }
238
238
 
@@ -241,39 +241,67 @@ class bridgeClass {
241
241
  * ******************************************************************/
242
242
 
243
243
  /**
244
- * @param Id Id of actual element
245
244
  * @param changeInfo changeInfo of Id
246
245
  * @param options Options for using spezial fuctions
247
246
  */
248
- async getDiscoveryObject(Id, changeInfo, options) {
249
- const DeviceIdentifier = await this.getDeviceIdentifier(changeInfo, this.adapter.config.DeviceIdentifiers);
250
- const ReplacedDeviceIdentifier = await this.replaceGermanSpecific(DeviceIdentifier);
251
- const ReplacedWithoutSpace = await this.replaceSpace(ReplacedDeviceIdentifier);
252
- const ReplaceWithoutSlash = await this.replaceSlash(ReplacedWithoutSpace);
253
- const Topic = `${this.bridgeMqttClient.BridgePrefix}${ReplacedDeviceIdentifier}/${changeInfo.changedState}`;
254
- const EntityType = await this.getEntityType(options);
255
- const AdditionalAttributes = await this.getStateAttributes(options.common, EntityType);
256
- const DiscoveryTopic = `${this.BridgeDiscoveryPrefix[this.adapter.config.BridgeType]}${EntityType}/${ReplaceWithoutSlash}/${changeInfo.changedState}/config`;
257
- const DiscoveryPayload = {
258
- name: changeInfo.changedState,
259
- unique_id: `${ReplaceWithoutSlash}_${changeInfo.changedState}`.toLowerCase(),
260
- device: { identifiers: [ReplaceWithoutSlash.toLowerCase()], name: DeviceIdentifier },
261
- unit_of_measurement: '',
262
- state_class: 'measurement',
263
- };
264
- // Add Topics
265
- if (options.Bridgestate.publish) {
266
- DiscoveryPayload.state_topic = Topic;
267
- }
268
- if (options.Bridgestate.subscribe) {
269
- DiscoveryPayload.command_topic = Topic;
247
+ async getDiscoveryObject(changeInfo, options) {
248
+ const activeFunction = 'bridge.js - getDiscoveryObject';
249
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
250
+ try {
251
+ const DeviceIdentifier = await this.getDeviceIdentifier(changeInfo, this.adapter.config.DeviceIdentifiers);
252
+ const ReplacedDeviceIdentifier = await this.replaceGermanSpecific(DeviceIdentifier);
253
+ const ReplacedWithoutSpace = await this.replaceSpace(ReplacedDeviceIdentifier);
254
+ const ReplaceWithoutSlash = await this.replaceSlash(ReplacedWithoutSpace);
255
+ const Topic = `${this.bridgeMqttClient.BridgePrefix}${ReplacedDeviceIdentifier}/${changeInfo.changedState}`;
256
+ const EntityType = await this.getEntityType(options);
257
+ const AdditionalAttributes = await this.getStateAttributes(options.common, EntityType);
258
+ const DiscoveryTopic = `${this.BridgeDiscoveryPrefix[this.adapter.config.BridgeType]}${EntityType}/${ReplaceWithoutSlash}/${changeInfo.changedState}/config`;
259
+ const DiscoveryPayload = {
260
+ name: changeInfo.changedState,
261
+ unique_id: `${ReplaceWithoutSlash}_${changeInfo.changedState}`.toLowerCase(),
262
+ device: { identifiers: [ReplaceWithoutSlash.toLowerCase()], name: DeviceIdentifier },
263
+ unit_of_measurement: '',
264
+ state_class: 'measurement',
265
+ };
266
+ // Add Topics
267
+ if (options.Bridgestate.publish) {
268
+ DiscoveryPayload.state_topic = Topic;
269
+ }
270
+ if (options.Bridgestate.subscribe) {
271
+ DiscoveryPayload.command_topic = Topic;
272
+ }
273
+
274
+ // Assign Attibute to Payload
275
+ for (const Attribute in AdditionalAttributes) {
276
+ DiscoveryPayload[Attribute] = AdditionalAttributes[Attribute];
277
+ }
278
+ return { Topic: Topic, DiscoveryTopic: DiscoveryTopic, DiscoveryPayload: DiscoveryPayload };
279
+ } catch (error) {
280
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
270
281
  }
282
+ }
283
+
284
+ /*********************************************************************
285
+ * ******************** Discovery Objekt bilden **********************
286
+ * ******************************************************************/
271
287
 
272
- // Assign Attibute to Payload
273
- for (const Attribute in AdditionalAttributes) {
274
- DiscoveryPayload[Attribute] = AdditionalAttributes[Attribute];
288
+ /**
289
+ * @param id Id, wich is used for this discovery
290
+ * @param DiscoveryObject Discoverobject, wicht is to discover
291
+ */
292
+ async publishDiscovery(id, DiscoveryObject) {
293
+ const activeFunction = 'bridge.js - publishDiscovery';
294
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
295
+ try {
296
+ this.DiscoveredIds[id] = DiscoveryObject;
297
+ await this.bridgeMqttClient.publish(
298
+ DiscoveryObject.DiscoveryTopic,
299
+ JSON.stringify(DiscoveryObject.DiscoveryPayload),
300
+ {},
301
+ );
302
+ } catch (error) {
303
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
275
304
  }
276
- return { Topic: Topic, DiscoveryTopic: DiscoveryTopic, DiscoveryPayload: DiscoveryPayload };
277
305
  }
278
306
 
279
307
  /*********************************************************************
@@ -284,37 +312,43 @@ class bridgeClass {
284
312
  * @param options Options for using spezial fuctions
285
313
  */
286
314
  async getEntityType(options) {
287
- const common = options.common;
288
- const isWritable = options.Bridgestate.subscribe;
289
- const type = common.type || '';
290
- const role = (common.role || '').toLowerCase();
291
- switch (type) {
292
- case 'boolean':
293
- if (role.includes('button') || role.includes('action')) {
294
- return 'button'; // Trigger-only
295
- } else if (role.includes('switch')) {
315
+ const activeFunction = 'bridge.js - getEntityType';
316
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
317
+ try {
318
+ const common = options.common;
319
+ const isWritable = options.Bridgestate.subscribe;
320
+ const type = common.type || '';
321
+ const role = (common.role || '').toLowerCase();
322
+ switch (type) {
323
+ case 'boolean':
324
+ if (role.includes('button') || role.includes('action')) {
325
+ return 'button'; // Trigger-only
326
+ } else if (role.includes('switch')) {
327
+ return isWritable ? 'switch' : 'binary_sensor';
328
+ }
296
329
  return isWritable ? 'switch' : 'binary_sensor';
297
- }
298
- return isWritable ? 'switch' : 'binary_sensor';
299
330
 
300
- case 'number':
301
- // if (role.includes('valve')) return 'valve';
302
- if (role.includes('value')) {
303
- return 'sensor';
304
- }
305
- return isWritable ? 'number' : 'sensor';
331
+ case 'number':
332
+ // if (role.includes('valve')) return 'valve';
333
+ if (role.includes('value')) {
334
+ return 'sensor';
335
+ }
336
+ return isWritable ? 'number' : 'sensor';
306
337
 
307
- case 'string':
308
- return isWritable ? 'text' : 'sensor';
338
+ case 'string':
339
+ return isWritable ? 'text' : 'sensor';
309
340
 
310
- case 'mixed':
311
- case 'array':
312
- case 'object':
313
- case 'file':
314
- return 'sensor';
341
+ case 'mixed':
342
+ case 'array':
343
+ case 'object':
344
+ case 'file':
345
+ return 'sensor';
315
346
 
316
- default:
317
- return 'sensor';
347
+ default:
348
+ return 'sensor';
349
+ }
350
+ } catch (error) {
351
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
318
352
  }
319
353
  }
320
354
 
@@ -327,136 +361,119 @@ class bridgeClass {
327
361
  * @param entityType Entity of State
328
362
  */
329
363
  async getStateAttributes(common, entityType) {
330
- const role = (common?.role || '').toLowerCase();
331
- const unit = common?.unit || '';
332
- const unitLower = unit.toLowerCase();
333
- const type = common?.type || '';
334
- const attributes = {};
335
-
336
- if (entityType === 'sensor' || entityType === 'number') {
337
- if (role.includes('temperature')) {
338
- attributes.device_class = 'temperature';
339
- attributes.unit_of_measurement = unit || '°C';
340
- } else if (role.includes('humidity')) {
341
- attributes.device_class = 'humidity';
342
- attributes.unit_of_measurement = unit || '%';
343
- } else if (role.includes('illuminance') || role.includes('brightness')) {
344
- attributes.device_class = 'illuminance';
345
- attributes.unit_of_measurement = 'lx'; //unit || 'lx';
346
- } else if (role.includes('battery')) {
347
- attributes.device_class = 'battery';
348
- attributes.unit_of_measurement = unit || '%';
349
- } else if (role.includes('power') && !unit.includes('Wh')) {
350
- // Sonoff mit value.power.consumtion und kWh ausnehmen
351
- attributes.device_class = 'power';
352
- attributes.unit_of_measurement = unit || 'W';
353
- } else if (unitLower === 'w' || unitLower === 'kw') {
354
- attributes.device_class = 'power';
355
- attributes.unit_of_measurement = unit;
356
- } else if (unitLower === 'v') {
357
- attributes.device_class = 'voltage';
358
- attributes.unit_of_measurement = unit;
359
- } else if (unitLower === 'a') {
360
- attributes.device_class = 'current';
361
- attributes.unit_of_measurement = unit;
362
- } else if (role.includes('energy') || (role.includes('power.consumption') && unit.includes('Wh'))) {
363
- // Sonoff speziefisch, wegen falscher Rolle
364
- attributes.device_class = 'energy';
365
- /* if(role.includes('consumed') || role.includes('produced')){
366
- attributes.state_class = 'total';
367
- attributes.last_reset = "1970-01-01T00:00:00+00:00";
364
+ const activeFunction = 'bridge.js - getStateAttributes';
365
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
366
+ try {
367
+ const role = (common?.role || '').toLowerCase();
368
+ const unit = common?.unit || '';
369
+ const unitLower = unit.toLowerCase();
370
+ const type = common?.type || '';
371
+ const attributes = {};
372
+
373
+ if (entityType === 'sensor' || entityType === 'number') {
374
+ if (role.includes('temperature')) {
375
+ attributes.device_class = 'temperature';
376
+ attributes.unit_of_measurement = unit || '°C';
377
+ } else if (role.includes('humidity')) {
378
+ attributes.device_class = 'humidity';
379
+ attributes.unit_of_measurement = unit || '%';
380
+ } else if (role.includes('illuminance') || role.includes('brightness')) {
381
+ attributes.device_class = 'illuminance';
382
+ attributes.unit_of_measurement = 'lx'; //unit || 'lx';
383
+ } else if (role.includes('battery')) {
384
+ attributes.device_class = 'battery';
385
+ attributes.unit_of_measurement = unit || '%';
386
+ } else if (role.includes('power') && !unit.includes('Wh')) {
387
+ // Sonoff mit value.power.consumtion und kWh ausnehmen
388
+ attributes.device_class = 'power';
389
+ attributes.unit_of_measurement = unit || 'W';
390
+ } else if (unitLower === 'w' || unitLower === 'kw') {
391
+ attributes.device_class = 'power';
392
+ attributes.unit_of_measurement = unit;
393
+ } else if (unitLower === 'v') {
394
+ attributes.device_class = 'voltage';
395
+ attributes.unit_of_measurement = unit;
396
+ } else if (unitLower === 'a') {
397
+ attributes.device_class = 'current';
398
+ attributes.unit_of_measurement = unit;
399
+ } else if (role.includes('energy') || (role.includes('power.consumption') && unit.includes('Wh'))) {
400
+ // Sonoff speziefisch, wegen falscher Rolle
401
+ attributes.device_class = 'energy';
402
+ /* if(role.includes('consumed') || role.includes('produced')){
403
+ attributes.state_class = 'total';
404
+ attributes.last_reset = "1970-01-01T00:00:00+00:00";
405
+ }
406
+ else{*/
407
+ attributes.state_class = 'total_increasing';
408
+ //}
409
+ attributes.unit_of_measurement = unit || 'Wh';
410
+ } else if (role.includes('weight')) {
411
+ // Sonoff mit value.power.consumtion und kWh ausnehmen
412
+ attributes.device_class = 'weight';
413
+ attributes.unit_of_measurement = unit || 'kg';
414
+ } else if (unitLower === 'g' || unitLower === 'kg') {
415
+ attributes.device_class = 'weight';
416
+ attributes.unit_of_measurement = unit;
417
+ } else {
418
+ attributes.unit_of_measurement = unit || '';
368
419
  }
369
- else{*/
370
- attributes.state_class = 'total_increasing';
371
- //}
372
- attributes.unit_of_measurement = unit || 'Wh';
373
- } else if (role.includes('weight')) {
374
- // Sonoff mit value.power.consumtion und kWh ausnehmen
375
- attributes.device_class = 'weight';
376
- attributes.unit_of_measurement = unit || 'kg';
377
- } else if (unitLower === 'g' || unitLower === 'kg') {
378
- attributes.device_class = 'weight';
379
- attributes.unit_of_measurement = unit;
380
- } else {
381
- attributes.unit_of_measurement = unit || '';
382
- }
383
420
 
384
- // Korrektur der Unit
385
- if (attributes.unit_of_measurement === 'm^3') {
386
- attributes.unit_of_measurement = 'm³';
387
- }
421
+ // Korrektur der Unit
422
+ if (attributes.unit_of_measurement === 'm^3') {
423
+ attributes.unit_of_measurement = 'm³';
424
+ }
388
425
 
389
- // Min und Max zuweisen
390
- if (common.min) {
391
- attributes.min = common.min;
392
- }
393
- if (common.max) {
394
- attributes.max = common.max;
395
- }
426
+ // Min und Max zuweisen
427
+ if (common.min) {
428
+ attributes.min = common.min;
429
+ }
430
+ if (common.max) {
431
+ attributes.max = common.max;
432
+ }
396
433
 
397
- // Es muss eine Device Class zugewiesen sein und der State darf kein String sein.
398
- // String ist kein Measurement
399
- if (!attributes.state_class && type !== 'string') {
400
- attributes.state_class = 'measurement';
434
+ // Es muss eine Device Class zugewiesen sein und der State darf kein String sein.
435
+ // String ist kein Measurement
436
+ if (!attributes.state_class && type !== 'string') {
437
+ attributes.state_class = 'measurement';
438
+ }
401
439
  }
402
- }
403
-
404
- if (entityType === 'valve') {
405
- attributes.unit_of_measurement = unit || '%';
406
- }
407
440
 
408
- if (entityType === 'switch') {
409
- attributes.state_on = 'true';
410
- attributes.state_off = 'false';
411
- attributes.payload_on = 'true';
412
- attributes.payload_off = 'false';
413
- }
414
- if (entityType === 'button') {
415
- attributes.state_on = 'true';
416
- attributes.state_off = 'false';
417
- attributes.payload_on = 'true';
418
- attributes.payload_off = 'false';
419
- }
420
- if (entityType === 'binary_sensor') {
421
- if (role.includes('motion')) {
422
- attributes.device_class = 'motion';
423
- } else if (role.includes('window') || role.includes('door')) {
424
- attributes.device_class = 'door';
425
- } else if (role.includes('smoke')) {
426
- attributes.device_class = 'smoke';
427
- } else if (role.includes('presence')) {
428
- attributes.device_class = 'presence';
429
- } else if (role.includes('moisture') || role.includes('leak')) {
430
- attributes.device_class = 'moisture';
441
+ if (entityType === 'valve') {
442
+ attributes.unit_of_measurement = unit || '%';
431
443
  }
432
- attributes.state_on = 'true';
433
- attributes.state_off = 'false';
434
- attributes.payload_on = 'true';
435
- attributes.payload_off = 'false';
436
- }
437
-
438
- return attributes;
439
- }
440
-
441
- /*********************************************************************
442
- * ********************* Message vom der Bridge **********************
443
- * ******************************************************************/
444
444
 
445
- /**
446
- * @param topic topic of the foreign system message
447
- * @param message message of the foreign system
448
- */
449
- async handleMessage(topic, message) {
450
- if (this.SubscribedTopics[topic]) {
451
- this.SubscribedTopics[topic].val = message;
452
- this.SubscribedTopics[topic].ts = Date.now();
453
- if (
454
- !this.PulishedIds[this.SubscribedTopics[topic].id] ||
455
- this.PulishedIds[this.SubscribedTopics[topic].id].val !== message ||
456
- Date.now() - this.PulishedIds[this.SubscribedTopics[topic].id].ts > this.MinTime
457
- ) {
458
- await this.adapter.setState(this.SubscribedTopics[topic].id, message);
445
+ if (entityType === 'switch') {
446
+ attributes.state_on = 'true';
447
+ attributes.state_off = 'false';
448
+ attributes.payload_on = 'true';
449
+ attributes.payload_off = 'false';
450
+ }
451
+ if (entityType === 'button') {
452
+ attributes.state_on = 'true';
453
+ attributes.state_off = 'false';
454
+ attributes.payload_on = 'true';
455
+ attributes.payload_off = 'false';
456
+ }
457
+ if (entityType === 'binary_sensor') {
458
+ if (role.includes('motion')) {
459
+ attributes.device_class = 'motion';
460
+ } else if (role.includes('window') || role.includes('door')) {
461
+ attributes.device_class = 'door';
462
+ } else if (role.includes('smoke')) {
463
+ attributes.device_class = 'smoke';
464
+ } else if (role.includes('presence')) {
465
+ attributes.device_class = 'presence';
466
+ } else if (role.includes('moisture') || role.includes('leak')) {
467
+ attributes.device_class = 'moisture';
468
+ }
469
+ attributes.state_on = 'true';
470
+ attributes.state_off = 'false';
471
+ attributes.payload_on = 'true';
472
+ attributes.payload_off = 'false';
459
473
  }
474
+ return attributes;
475
+ } catch (error) {
476
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
460
477
  }
461
478
  }
462
479
 
@@ -465,80 +482,143 @@ class bridgeClass {
465
482
  * @param DeviceIdentifiers configed deviceidentifier
466
483
  */
467
484
  getDeviceIdentifier(changeInfo, DeviceIdentifiers) {
468
- let DeviceIdentifier = '';
469
- let Separator = '';
470
- switch (this.adapter.config.separator) {
471
- case 'no':
472
- Separator = '';
473
- break;
474
- case 'space':
475
- Separator = ' ';
476
- break;
477
- case 'underline':
478
- Separator = '_';
479
- break;
480
- case 'minus':
481
- Separator = '-';
482
- break;
483
- }
484
- for (const element of Object.values(DeviceIdentifiers)) {
485
- if (DeviceIdentifier !== '') {
486
- DeviceIdentifier += Separator;
487
- }
488
- switch (element.DeviceIdentifier) {
489
- case 'applicationId':
490
- DeviceIdentifier += changeInfo.applicationId;
491
- break;
492
-
493
- case 'applicationName':
494
- DeviceIdentifier += changeInfo.applicationName;
495
- break;
496
-
497
- case 'usedApplicationName':
498
- DeviceIdentifier += changeInfo.usedApplicationName;
485
+ const activeFunction = 'bridge.js - getDeviceIdentifier';
486
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
487
+ try {
488
+ let DeviceIdentifier = '';
489
+ let Separator = '';
490
+ switch (this.adapter.config.separator) {
491
+ case 'no':
492
+ Separator = '';
499
493
  break;
500
-
501
- case 'deviceEUI':
502
- DeviceIdentifier += changeInfo.deviceEUI;
494
+ case 'space':
495
+ Separator = ' ';
503
496
  break;
504
-
505
- case 'deviceId':
506
- DeviceIdentifier += changeInfo.deviceId;
497
+ case 'underline':
498
+ Separator = '_';
507
499
  break;
508
-
509
- case 'usedDeviceId':
510
- DeviceIdentifier += changeInfo.usedDeviceId;
500
+ case 'minus':
501
+ Separator = '-';
511
502
  break;
512
503
  }
504
+ for (const element of Object.values(DeviceIdentifiers)) {
505
+ if (DeviceIdentifier !== '') {
506
+ DeviceIdentifier += Separator;
507
+ }
508
+ switch (element.DeviceIdentifier) {
509
+ case 'applicationId':
510
+ DeviceIdentifier += changeInfo.applicationId;
511
+ break;
512
+
513
+ case 'applicationName':
514
+ DeviceIdentifier += changeInfo.applicationName;
515
+ break;
516
+
517
+ case 'usedApplicationName':
518
+ DeviceIdentifier += changeInfo.usedApplicationName;
519
+ break;
520
+
521
+ case 'deviceEUI':
522
+ DeviceIdentifier += changeInfo.deviceEUI;
523
+ break;
524
+
525
+ case 'deviceId':
526
+ DeviceIdentifier += changeInfo.deviceId;
527
+ break;
528
+
529
+ case 'usedDeviceId':
530
+ DeviceIdentifier += changeInfo.usedDeviceId;
531
+ break;
532
+ }
533
+ }
534
+ return DeviceIdentifier;
535
+ } catch (error) {
536
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
513
537
  }
514
- return DeviceIdentifier;
515
538
  }
516
539
 
517
540
  /**
518
541
  * @param Inputstring string to replace the vorbidden chars
519
542
  */
520
543
  replaceGermanSpecific(Inputstring) {
521
- return Inputstring.replace(/ä/g, 'ae')
522
- .replace(/ö/g, 'oe')
523
- .replace(/ü/g, 'ue')
524
- .replace(/Ä/g, 'Ae')
525
- .replace(/Ö/g, 'Oe')
526
- .replace(/Ü/g, 'Ue')
527
- .replace(/ß/g, 'ss');
544
+ const activeFunction = 'bridge.js - replaceGermanSpecific';
545
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
546
+ try {
547
+ return Inputstring.replace(/ä/g, 'ae')
548
+ .replace(/ö/g, 'oe')
549
+ .replace(/ü/g, 'ue')
550
+ .replace(/Ä/g, 'Ae')
551
+ .replace(/Ö/g, 'Oe')
552
+ .replace(/Ü/g, 'Ue')
553
+ .replace(/ß/g, 'ss');
554
+ } catch (error) {
555
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
556
+ }
528
557
  }
529
558
 
530
559
  /**
531
560
  * @param Inputstring string to replace the vorbidden chars
532
561
  */
533
562
  replaceSpace(Inputstring) {
534
- return Inputstring.replace(/ /g, '_');
563
+ const activeFunction = 'bridge.js - replaceSpace';
564
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
565
+ try {
566
+ return Inputstring.replace(/ /g, '_');
567
+ } catch (error) {
568
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
569
+ }
535
570
  }
536
571
 
537
572
  /**
538
573
  * @param Inputstring string to replace the vorbidden chars
539
574
  */
540
575
  replaceSlash(Inputstring) {
541
- return Inputstring.replace(/\//g, '_');
576
+ const activeFunction = 'bridge.js - replaceSlash';
577
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
578
+ try {
579
+ return Inputstring.replace(/\//g, '_');
580
+ } catch (error) {
581
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
582
+ }
583
+ }
584
+
585
+ /*********************************************************************
586
+ * ***************** Discover all defined State **********************
587
+ * ******************************************************************/
588
+
589
+ /**
590
+ * Discover all defined States (maby at Startup)
591
+ *
592
+ * @param options options to special functions
593
+ */
594
+ async checkAllStatesForBridgeWork(options) {
595
+ const activeFunction = 'bridge.js - checkAllStatesForBridgeWork';
596
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
597
+ try {
598
+ // Get all ids in adapterfolder
599
+ // Generate Infos of all devices and decoded folders
600
+ const adapterObjects = await this.adapter.getAdapterObjectsAsync();
601
+ for (const adapterObject of Object.values(adapterObjects)) {
602
+ if (
603
+ adapterObject._id.includes(
604
+ `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.`,
605
+ ) ||
606
+ adapterObject._id.includes(
607
+ `${this.adapter.messagehandler.directoryhandler.reachableSubfolders.downlinkControl}.`,
608
+ )
609
+ ) {
610
+ if (adapterObject.type === 'state') {
611
+ if (!options) {
612
+ options = {};
613
+ }
614
+ options.common = adapterObject.common;
615
+ await this.work(adapterObject._id, undefined, options);
616
+ }
617
+ }
618
+ }
619
+ } catch (error) {
620
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
621
+ }
542
622
  }
543
623
 
544
624
  // create schedule Jobs for online and historic values
@@ -546,25 +626,44 @@ class bridgeClass {
546
626
  * Build the cronJob
547
627
  */
548
628
  createScheduleJobs() {
549
- this.DiscoveryCronjob = schedule.scheduleJob(
550
- this.adapter.config.RefreshDiscoveryCronJob,
551
- this.startScheduledDiscovery.bind(this),
552
- );
629
+ const activeFunction = 'bridge.js - createScheduleJobs';
630
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
631
+ try {
632
+ this.DiscoveryCronjob = schedule.scheduleJob(
633
+ this.adapter.config.RefreshDiscoveryCronJob,
634
+ this.startScheduledDiscovery.bind(this),
635
+ );
636
+ } catch (error) {
637
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
638
+ }
553
639
  }
554
640
 
555
641
  /**
556
- * Call the discovery function
642
+ * Publish the discovered Ids again
557
643
  */
558
644
  async startScheduledDiscovery() {
559
- this.adapter.log.error('cycle');
560
- await this.adapter.bridge.discoverDefinedStates({ forceDiscovery: true });
645
+ const activeFunction = 'bridge.js - startScheduledDiscovery';
646
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
647
+ try {
648
+ for (const DiscoveredId in this.DiscoveredIds) {
649
+ await this.publishDiscovery(DiscoveredId, this.DiscoveredIds[DiscoveredId]);
650
+ }
651
+ } catch (error) {
652
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
653
+ }
561
654
  }
562
655
 
563
656
  /**
564
657
  * Clear schedule
565
658
  */
566
659
  clearAllSchedules() {
567
- schedule.cancelJob(this.DiscoveryCronjob);
660
+ const activeFunction = 'bridge.js - clearAllSchedules';
661
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
662
+ try {
663
+ schedule.cancelJob(this.DiscoveryCronjob);
664
+ } catch (error) {
665
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
666
+ }
568
667
  }
569
668
  }
570
669
  module.exports = bridgeClass;
@@ -40,7 +40,7 @@ class bridgeMqttClientClass {
40
40
  }
41
41
  });
42
42
 
43
- await this.adapter.bridge.discoverDefinedStates({ forceDiscovery: true });
43
+ await this.adapter.bridge.checkAllStatesForBridgeWork({ forceDiscovery: true });
44
44
  this.adapter.bridge.createScheduleJobs();
45
45
  });
46
46
 
package/main.js CHANGED
@@ -522,7 +522,7 @@ class Lorawan extends utils.Adapter {
522
522
  this.setState(id, state.val, true);
523
523
  }
524
524
  } else {
525
- await this.bridge?.publish(id, state.val);
525
+ await this.bridge?.publishId(id, state.val);
526
526
  }
527
527
  } else {
528
528
  // The state was deleted
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.13.0",
3
+ "version": "1.13.1",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",