iobroker.lorawan 1.19.29 → 1.19.30

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,9 @@ For now there is documentation in English here: https://wiki.hafenmeister.de
23
23
  Placeholder for the next version (at the beginning of the line):
24
24
  ### **WORK IN PROGRESS**
25
25
  -->
26
+ ### 1.19.30 (2026-01-16)
27
+ * (BenAhrdt) add simulation of Position for cover
28
+
26
29
  ### 1.19.29 (2026-01-16)
27
30
  * (BenAhrdt) bugfix tilt min & max
28
31
 
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "Rollo",
71
71
  "CoverShutter": "Rolladen",
72
72
  "CoverSignal": "Signale von Endschaltern",
73
+ "CoverSimulatePosition": "Position simulieren",
74
+ "CoverSimulatePositionTooltip": "Simuliert die Position abhängig von den Endschaltern (bei manchen Systemen erforderlich)",
73
75
  "CoverStop": "stoppen",
74
76
  "CoverStopText": "Befehls-ID stoppen",
75
77
  "CoverStopTooltip": "Ein zusätzlicher Status für den Stoppbefehl",
@@ -271,5 +271,7 @@
271
271
  "CoverShade": "shade",
272
272
  "CoverShutter": "shutter",
273
273
  "CoverWindow": "window",
274
- "deviceSuffix": "device Suffix"
274
+ "deviceSuffix": "device Suffix",
275
+ "CoverSimulatePosition": "simulate position",
276
+ "CoverSimulatePositionTooltip": "simulates the position depending on the limit switches (required for some systems)"
275
277
  }
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "sombra",
71
71
  "CoverShutter": "obturador",
72
72
  "CoverSignal": "Señales de finales de carrera",
73
+ "CoverSimulatePosition": "simular posición",
74
+ "CoverSimulatePositionTooltip": "Simula la posición en función de los finales de carrera (requeridos para algunos sistemas)",
73
75
  "CoverStop": "detener",
74
76
  "CoverStopText": "Detener ID de comando",
75
77
  "CoverStopTooltip": "Un estado adicional para el comando de parada",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "ombre",
71
71
  "CoverShutter": "obturateur",
72
72
  "CoverSignal": "Signaux des interrupteurs de fin de course",
73
+ "CoverSimulatePosition": "simuler la position",
74
+ "CoverSimulatePositionTooltip": "simule la position en fonction des fins de course (obligatoire pour certains systèmes)",
73
75
  "CoverStop": "arrêt",
74
76
  "CoverStopText": "ID de commande d'arrêt",
75
77
  "CoverStopTooltip": "Un état supplémentaire pour la commande d'arrêt",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "ombra",
71
71
  "CoverShutter": "otturatore",
72
72
  "CoverSignal": "Segnali dai finecorsa",
73
+ "CoverSimulatePosition": "simulare la posizione",
74
+ "CoverSimulatePositionTooltip": "simula la posizione in funzione dei finecorsa (richiesto per alcuni sistemi)",
73
75
  "CoverStop": "fermare",
74
76
  "CoverStopText": "Arresta l'ID del comando",
75
77
  "CoverStopTooltip": "Uno stato aggiuntivo per il comando di arresto",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "schaduw",
71
71
  "CoverShutter": "sluiter",
72
72
  "CoverSignal": "Signalen van eindschakelaars",
73
+ "CoverSimulatePosition": "positie simuleren",
74
+ "CoverSimulatePositionTooltip": "simuleert de positie afhankelijk van de eindschakelaars (vereist voor sommige systemen)",
73
75
  "CoverStop": "stop",
74
76
  "CoverStopText": "Stopopdracht-ID",
75
77
  "CoverStopTooltip": "Een extra status voor stopcommando",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "cień",
71
71
  "CoverShutter": "migawka",
72
72
  "CoverSignal": "Sygnały z wyłączników krańcowych",
73
+ "CoverSimulatePosition": "symulować pozycję",
74
+ "CoverSimulatePositionTooltip": "symuluje położenie w zależności od wyłączników krańcowych (wymagane w przypadku niektórych systemów)",
73
75
  "CoverStop": "zatrzymywać się",
74
76
  "CoverStopText": "Zatrzymaj identyfikator polecenia",
75
77
  "CoverStopTooltip": "Dodatkowy stan dla polecenia stop",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "sombra",
71
71
  "CoverShutter": "obturador",
72
72
  "CoverSignal": "Sinais de interruptores de limite",
73
+ "CoverSimulatePosition": "simular posição",
74
+ "CoverSimulatePositionTooltip": "simula a posição dependendo dos interruptores de limite (necessário para alguns sistemas)",
73
75
  "CoverStop": "parar",
74
76
  "CoverStopText": "ID do comando de parada",
75
77
  "CoverStopTooltip": "Um estado adicional para comando de parada",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "оттенок",
71
71
  "CoverShutter": "затвор",
72
72
  "CoverSignal": "Сигналы концевых выключателей",
73
+ "CoverSimulatePosition": "имитировать положение",
74
+ "CoverSimulatePositionTooltip": "имитирует положение в зависимости от концевых выключателей (требуется для некоторых систем)",
73
75
  "CoverStop": "останавливаться",
74
76
  "CoverStopText": "Идентификатор команды остановки",
75
77
  "CoverStopTooltip": "Дополнительное состояние для команды остановки",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "відтінок",
71
71
  "CoverShutter": "затвор",
72
72
  "CoverSignal": "Сигнали від кінцевих вимикачів",
73
+ "CoverSimulatePosition": "імітувати положення",
74
+ "CoverSimulatePositionTooltip": "імітує положення в залежності від кінцевих вимикачів (необхідно для деяких систем)",
73
75
  "CoverStop": "СТІЙ",
74
76
  "CoverStopText": "Ідентифікатор команди зупинки",
75
77
  "CoverStopTooltip": "Додатковий стан для команди зупинки",
@@ -70,6 +70,8 @@
70
70
  "CoverShade": "阴影",
71
71
  "CoverShutter": "快门",
72
72
  "CoverSignal": "来自限位开关的信号",
73
+ "CoverSimulatePosition": "模拟位置",
74
+ "CoverSimulatePositionTooltip": "根据限位开关模拟位置(某些系统需要)",
73
75
  "CoverStop": "停止",
74
76
  "CoverStopText": "停止命令ID",
75
77
  "CoverStopTooltip": "停止命令的附加状态",
@@ -2065,7 +2065,6 @@
2065
2065
  "type": "checkbox",
2066
2066
  "attr": "CoverPosition",
2067
2067
  "label": "CoverPosition",
2068
- "customFilter": {"common": { "type": [ "number", "mixed" ] } },
2069
2068
  "tooltip": "CoverPositionTooltip",
2070
2069
  "newLine": true,
2071
2070
  "default": true,
@@ -2245,6 +2244,20 @@
2245
2244
  "md": 4,
2246
2245
  "lg": 4,
2247
2246
  "xl": 4
2247
+ },
2248
+ {
2249
+ "type": "checkbox",
2250
+ "attr": "CoverSimulatePosition",
2251
+ "label": "CoverSimulatePosition",
2252
+ "tooltip": "CoverSimulatePositionTooltip",
2253
+ "hidden": "data.CoverPosition === true",
2254
+ "newLine": true,
2255
+ "default": false,
2256
+ "xs": 12,
2257
+ "sm": 2,
2258
+ "md": 2,
2259
+ "lg": 2,
2260
+ "xl": 2
2248
2261
  }
2249
2262
  ]
2250
2263
  },
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.19.29",
4
+ "version": "1.19.30",
5
5
  "news": {
6
+ "1.19.30": {
7
+ "en": "add simulation of Position for cover",
8
+ "de": "simulation von Position für Cover hinzufügen",
9
+ "ru": "добавить моделирование позиции для покрытия",
10
+ "pt": "adicionar simulação de Posição para cobertura",
11
+ "nl": "simulatie van positie voor dekking toevoegen",
12
+ "fr": "ajouter la simulation de la position pour la couverture",
13
+ "it": "aggiungere la simulazione di posizione per il coperchio",
14
+ "es": "añadir simulación de la posición para la cubierta",
15
+ "pl": "dodać symulację pozycji dla pokrycia",
16
+ "uk": "додати моделювання позиції для покриття",
17
+ "zh-cn": "添加覆盖位置模拟"
18
+ },
6
19
  "1.19.29": {
7
20
  "en": "bugfix tilt min & max",
8
21
  "de": "bugfix neigung min & max",
@@ -80,19 +93,6 @@
80
93
  "pl": "przypisz filtr przy starcie\nbugfix przypisać id temperatury koloru w przypadku braku koloru jest configed",
81
94
  "uk": "призначте фільтр на старті\nвиправлення призначає колірну температуру при відсутності кольору",
82
95
  "zh-cn": "启动时指定过滤器\n在无颜色时指定颜色温度 id"
83
- },
84
- "1.19.23": {
85
- "en": "more debuglogging in foreignDiscover",
86
- "de": "mehr Debuglogging im Ausland Entdecken",
87
- "ru": "больше дебюггинга в иностранных Открыть",
88
- "pt": "mais depuração em estrangeiro Descobrir",
89
- "nl": "meer debuggen in het buitenland Ontdekken",
90
- "fr": "plus de débogage à l'étranger Découvrir",
91
- "it": "più debuglog in straniero Scopri di più",
92
- "es": "más depuración en el extranjero Descubre",
93
- "pl": "więcej debuglogging w zagranicznych Odkryj",
94
- "uk": "більш детальна інформація Про нас",
95
- "zh-cn": "更多外国调试日志 发现"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -586,7 +586,7 @@
586
586
  "name": "internal logging types",
587
587
  "read": true,
588
588
  "write": true,
589
- "def": "{\"discovery\":false, \"assign\": false}"
589
+ "def": "{\"discovery\":false, \"assign\": false, \"messageTo\": false}"
590
590
  },
591
591
  "native": {}
592
592
  },
@@ -44,6 +44,7 @@ class bridgeClass {
44
44
  this.EndingVirtualLock = '.virtual_lock';
45
45
  this.EndingVirtualLight = '.virtual_light';
46
46
  this.EndingVirtualMode = '.virtual_mode';
47
+ this.EndingVirtualPosition = '.virtual_position';
47
48
  this.NotificationId = '.notification';
48
49
  this.GeneralId = '.general';
49
50
  this.OfflineId = '.offline';
@@ -181,6 +182,7 @@ class bridgeClass {
181
182
  this.logging = {
182
183
  discovery: 'discovery',
183
184
  assign: 'assign',
185
+ messageTo: 'messageTo',
184
186
  };
185
187
  }
186
188
 
@@ -276,7 +278,7 @@ class bridgeClass {
276
278
  // Cover
277
279
  if (this.SubscribedTopics[topic].cover) {
278
280
  if (this.SubscribedTopics[topic].messageAssign) {
279
- if (this.SubscribedTopics[topic].messageAssign[message]) {
281
+ if (Object.hasOwn(this.SubscribedTopics[topic].messageAssign, message)) {
280
282
  message = this.SubscribedTopics[topic].messageAssign[message];
281
283
  } else {
282
284
  this.adapter.log.warn(
@@ -290,7 +292,7 @@ class bridgeClass {
290
292
  // Lock
291
293
  if (this.SubscribedTopics[topic].lock) {
292
294
  if (this.SubscribedTopics[topic].messageAssign) {
293
- if (this.SubscribedTopics[topic].messageAssign[message]) {
295
+ if (Object.hasOwn(this.SubscribedTopics[topic].messageAssign, message)) {
294
296
  message = this.SubscribedTopics[topic].messageAssign[message];
295
297
  } else {
296
298
  this.adapter.log.warn(
@@ -826,24 +828,37 @@ class bridgeClass {
826
828
  val = State.val;
827
829
  }
828
830
  }
829
-
830
831
  // Iterate the state_topics
831
832
  for (const element in this.PublishedIds[id].publish) {
833
+ let value = val;
832
834
  const topic = element;
833
835
  const publish = this.PublishedIds[id].publish[element];
834
-
836
+ // Query for messageTo
837
+ if (publish.messageTo) {
838
+ if (Object.hasOwn(publish.messageAssign, value)) {
839
+ value = publish.messageAssign[value];
840
+ }
841
+ // Check for logging
842
+ this.adapter.log[this.adapter.logtypes.messageTo]?.(
843
+ `The change of Id: ${id} will forwarded to id: ${publish.messageTo}`,
844
+ );
845
+ await this.publishId(publish.messageTo, value, options);
846
+ return;
847
+ }
835
848
  // Light
836
849
  if (publish.light) {
837
- val = {};
838
- val.state = (await this.adapter.getForeignStateAsync(publish.LightIds.onOff)).val;
839
- val.state = val.state === true ? 'ON' : 'OFF';
850
+ value = {};
851
+ value.state = (await this.adapter.getForeignStateAsync(publish.LightIds.onOff)).val;
852
+ value.state = value.state === true ? 'ON' : 'OFF';
840
853
  // 16.12. Change: Read and Send always all attributes
841
854
  if (publish.LightIds.brightness) {
842
- val.brightness = (await this.adapter.getForeignStateAsync(publish.LightIds.brightness)).val;
855
+ value.brightness = (
856
+ await this.adapter.getForeignStateAsync(publish.LightIds.brightness)
857
+ ).val;
843
858
  }
844
859
  if (publish.LightIds.color && id !== publish.LightIds.colorTemperature) {
845
- val.color_mode = 'rgb';
846
- val.color = this.hexToRgb(
860
+ value.color_mode = 'rgb';
861
+ value.color = this.hexToRgb(
847
862
  (await this.adapter.getForeignStateAsync(publish.LightIds.color)).val,
848
863
  );
849
864
  }
@@ -851,16 +866,16 @@ class bridgeClass {
851
866
  publish.LightIds.colorTemperature &&
852
867
  (id === publish.LightIds.colorTemperature || !publish.LightIds.color)
853
868
  ) {
854
- val.color_mode = 'color_temp';
855
- val.color_temp = (
869
+ value.color_mode = 'color_temp';
870
+ value.color_temp = (
856
871
  await this.adapter.getForeignStateAsync(publish.LightIds.colorTemperature)
857
872
  ).val;
858
873
  }
859
874
  if (publish.LightIds.effects) {
860
875
  const effect = (await this.adapter.getForeignStateAsync(publish.LightIds.effects)).val;
861
- val.effect = '';
876
+ value.effect = '';
862
877
  if (publish.effects[effect]) {
863
- val.effect = publish.effects[effect];
878
+ value.effect = publish.effects[effect];
864
879
  }
865
880
  }
866
881
  }
@@ -868,8 +883,8 @@ class bridgeClass {
868
883
  // Cover
869
884
  if (publish.cover) {
870
885
  if (publish.messageAssign) {
871
- if (publish.messageAssign[val]) {
872
- val = publish.messageAssign[val];
886
+ if (Object.hasOwn(publish.messageAssign, value)) {
887
+ value = publish.messageAssign[value];
873
888
  } else {
874
889
  return;
875
890
  }
@@ -879,8 +894,8 @@ class bridgeClass {
879
894
  // Lock
880
895
  if (publish.lock) {
881
896
  if (publish.messageAssign) {
882
- if (publish.messageAssign[val]) {
883
- val = publish.messageAssign[val];
897
+ if (Object.hasOwn(publish.messageAssign, value)) {
898
+ value = publish.messageAssign[value];
884
899
  } else {
885
900
  return;
886
901
  }
@@ -900,7 +915,7 @@ class bridgeClass {
900
915
  if (!publish.values) {
901
916
  publish.values = {};
902
917
  }
903
- publish.values.val = val;
918
+ publish.values.val = value;
904
919
  publish.values.ts = Date.now();
905
920
  publish.values.time = new Date(Date.now()).toLocaleString(
906
921
  this.Timeoutput.Argument,
@@ -908,15 +923,15 @@ class bridgeClass {
908
923
  // @ts-expect-error
909
924
  this.Timeoutput.Format,
910
925
  );
911
- if (typeof val !== 'string') {
912
- val = JSON.stringify(val);
926
+ if (typeof value !== 'string') {
927
+ value = JSON.stringify(value);
913
928
  }
914
929
  if (!options) {
915
930
  options = { retain: true };
916
931
  } else if (options.retain === undefined) {
917
932
  options.retain = true;
918
933
  }
919
- await this.bridgeMqttClient.publish(topic, val, options);
934
+ await this.bridgeMqttClient.publish(topic, value, options);
920
935
  await this.adapter.setState('info.publishedIds', JSON.stringify(this.PublishedIds), true);
921
936
  }
922
937
 
@@ -1186,10 +1201,12 @@ class bridgeClass {
1186
1201
  if (!assignObject[indexId]) {
1187
1202
  assignObject[indexId] = { discovery: [], publish: {} };
1188
1203
  }
1189
- assignObject[indexId].discovery.push({
1190
- topic: topic,
1191
- payload: structuredClone(payload),
1192
- });
1204
+ if (topic !== undefined && payload !== undefined) {
1205
+ assignObject[indexId].discovery.push({
1206
+ topic: topic,
1207
+ payload: structuredClone(payload),
1208
+ });
1209
+ }
1193
1210
  /* alt 26.11.2025
1194
1211
  assignObject[indexId].state_topic = state_topic;
1195
1212
  assignObject[indexId].informations = structuredClone(informations);
@@ -2316,7 +2333,7 @@ class bridgeClass {
2316
2333
  climateIds.mode = config.ModeId;
2317
2334
  }
2318
2335
  for (const id of Object.values(climateIds)) {
2319
- // Just lock to object, if it does not end with Virtual Mode
2336
+ // Just look to object, if it does not end with Virtual Mode
2320
2337
  if (!id.endsWith(this.EndingVirtualMode)) {
2321
2338
  if (!(await this.adapter.foreignObjectExists(id))) {
2322
2339
  this.adapter.log.debug(`Id: ${id} does not exsit.`);
@@ -2989,6 +3006,30 @@ class bridgeClass {
2989
3006
  `${this.bridgeMqttClient.BridgePrefix}${Cover.position.uniqueString?.path}`.toLowerCase();
2990
3007
  }
2991
3008
 
3009
+ // Assign deviceIdentifier
3010
+ let deviceIdentifier = '';
3011
+ if (Cover.open) {
3012
+ deviceIdentifier = Cover.open.DeviceIdentifier;
3013
+ } else if (Cover.command) {
3014
+ deviceIdentifier = Cover.command.DeviceIdentifier;
3015
+ } else if (Cover.number) {
3016
+ deviceIdentifier = Cover.number.DeviceIdentifier;
3017
+ } else if (Cover.position) {
3018
+ deviceIdentifier = Cover.position.DeviceIdentifier;
3019
+ }
3020
+
3021
+ // Simulate Position
3022
+ if (config.CoverIds.simulatePosition) {
3023
+ Cover.simulatePosition = {};
3024
+ Cover.simulatePosition.DeviceIdentifier = deviceIdentifier;
3025
+ Cover.simulatePosition.uniqueString = await this.getUniqueString(
3026
+ config.CoverIds.simulatePosition,
3027
+ Cover.simulatePosition.DeviceIdentifier,
3028
+ );
3029
+ Cover.simulatePosition.Topic =
3030
+ `${this.bridgeMqttClient.BridgePrefix}${Cover.simulatePosition.uniqueString?.path}`.toLowerCase();
3031
+ }
3032
+
2992
3033
  // Tilt
2993
3034
  if (config.CoverIds.tilt) {
2994
3035
  Cover.tilt = {};
@@ -3022,18 +3063,6 @@ class bridgeClass {
3022
3063
  )?.parentName;
3023
3064
  }
3024
3065
 
3025
- // Assign deviceIdentifier
3026
- let deviceIdentifier = '';
3027
- if (Cover.open) {
3028
- deviceIdentifier = Cover.open.DeviceIdentifier;
3029
- } else if (Cover.command) {
3030
- deviceIdentifier = Cover.command.DeviceIdentifier;
3031
- } else if (Cover.number) {
3032
- deviceIdentifier = Cover.number.DeviceIdentifier;
3033
- } else if (Cover.position) {
3034
- deviceIdentifier = Cover.position.DeviceIdentifier;
3035
- }
3036
-
3037
3066
  // unique string
3038
3067
  const coverUniqueString = await this.getUniqueString(
3039
3068
  `${this.adapter.namespace}.${config.CoverName}`,
@@ -3063,6 +3092,9 @@ class bridgeClass {
3063
3092
  DiscoveryPayload.set_position_topic = `${Cover.position.Topic}${this.EndingSet}`;
3064
3093
  DiscoveryPayload.position_topic = `${Cover.position.Topic}${this.EndingState}`;
3065
3094
  }
3095
+ if (config.CoverIds.simulatePosition) {
3096
+ DiscoveryPayload.position_topic = `${Cover.simulatePosition.Topic}${this.EndingState}`;
3097
+ }
3066
3098
  if (config.CoverIds.tilt) {
3067
3099
  DiscoveryPayload.tilt_command_topic = `${Cover.tilt.Topic}${this.EndingSet}`;
3068
3100
  DiscoveryPayload.tilt_status_topic = `${Cover.tilt.Topic}${this.EndingState}`;
@@ -3143,6 +3175,21 @@ class bridgeClass {
3143
3175
  );
3144
3176
  }
3145
3177
 
3178
+ // Simulate Position
3179
+ if (config.CoverIds.simulatePosition) {
3180
+ this.assignIdStructure(
3181
+ this.PublishedIds,
3182
+ config.CoverIds.simulatePosition,
3183
+ {
3184
+ usedDeviceId: Cover.simulatePosition.DeviceIdentifier,
3185
+ },
3186
+ DiscoveryTopic,
3187
+ DiscoveryPayload,
3188
+ `${Cover.simulatePosition.Topic}${this.EndingState}`,
3189
+ { cover: true, simulatePosition: true },
3190
+ );
3191
+ }
3192
+
3146
3193
  // Tilt
3147
3194
  if (config.CoverIds.tilt) {
3148
3195
  this.assignIdStructure(
@@ -3185,6 +3232,21 @@ class bridgeClass {
3185
3232
  `${coverTopic}${this.EndingState}`,
3186
3233
  { cover: true, messageAssign: numberSignalAssign },
3187
3234
  );
3235
+ // In case of simulation of the position assign additional
3236
+ const simulateAssign = { 0: 0, 1: 100 };
3237
+ if (config.CoverIds.simulatePosition) {
3238
+ this.assignIdStructure(
3239
+ this.PublishedIds,
3240
+ config.CoverIds.numberSignal,
3241
+ {
3242
+ usedDeviceId: Cover.numberSignal.DeviceIdentifier,
3243
+ },
3244
+ undefined,
3245
+ undefined,
3246
+ `${Cover.simulatePosition.Topic}${this.EndingState}`,
3247
+ { cover: true, messageTo: config.CoverIds.simulatePosition, messageAssign: simulateAssign },
3248
+ );
3249
+ }
3188
3250
  } else {
3189
3251
  // Open limit switch
3190
3252
  if (config.CoverIds.openSignal) {
@@ -3201,6 +3263,24 @@ class bridgeClass {
3201
3263
  `${coverTopic}${this.EndingState}`,
3202
3264
  { cover: true, messageAssign: { [openKey]: 'open', [closingKey]: 'closing' } },
3203
3265
  );
3266
+ // In case of simulation of the position assign additional
3267
+ const simulateAssign = { [openKey]: 100, [closingKey]: 0 };
3268
+ if (config.CoverIds.closedSignal) {
3269
+ simulateAssign[closingKey] = 75;
3270
+ }
3271
+ if (config.CoverIds.simulatePosition) {
3272
+ this.assignIdStructure(
3273
+ this.PublishedIds,
3274
+ config.CoverIds.openSignal,
3275
+ {
3276
+ usedDeviceId: Cover.openSignal.DeviceIdentifier,
3277
+ },
3278
+ undefined,
3279
+ undefined,
3280
+ `${Cover.simulatePosition.Topic}${this.EndingState}`,
3281
+ { cover: true, messageTo: config.CoverIds.simulatePosition, messageAssign: simulateAssign },
3282
+ );
3283
+ }
3204
3284
  }
3205
3285
 
3206
3286
  // Closed limit switch
@@ -3221,6 +3301,24 @@ class bridgeClass {
3221
3301
  messageAssign: { [closedKey]: 'closed', [openingKey]: 'opening' },
3222
3302
  },
3223
3303
  );
3304
+ // In case of simulation of the position assign additional
3305
+ const simulateAssign = { [closedKey]: 0, [openingKey]: 100 };
3306
+ if (config.CoverIds.closedSignal) {
3307
+ simulateAssign[openingKey] = 25;
3308
+ }
3309
+ if (config.CoverIds.simulatePosition) {
3310
+ this.assignIdStructure(
3311
+ this.PublishedIds,
3312
+ config.CoverIds.closedSignal,
3313
+ {
3314
+ usedDeviceId: Cover.closedSignal.DeviceIdentifier,
3315
+ },
3316
+ undefined,
3317
+ undefined,
3318
+ `${Cover.simulatePosition.Topic}${this.EndingState}`,
3319
+ { cover: true, messageTo: config.CoverIds.simulatePosition, messageAssign: simulateAssign },
3320
+ );
3321
+ }
3224
3322
  }
3225
3323
  }
3226
3324
 
@@ -3243,6 +3341,9 @@ class bridgeClass {
3243
3341
  await this.publishId(config.CoverIds.position, undefined, {});
3244
3342
  await this.adapter.subscribeForeignStatesAsync(config.CoverIds.position);
3245
3343
  }
3344
+ if (config.CoverIds.simulatePosition) {
3345
+ await this.publishId(config.CoverIds.simulatePosition, 0, {});
3346
+ }
3246
3347
  if (config.CoverIds.tilt) {
3247
3348
  await this.publishId(config.CoverIds.tilt, undefined, {});
3248
3349
  await this.adapter.subscribeForeignStatesAsync(config.CoverIds.tilt);
@@ -3277,14 +3378,18 @@ class bridgeClass {
3277
3378
  this.adapter.log.silly(`Function ${activeFunction} started.`);
3278
3379
  try {
3279
3380
  const CoverIds = {};
3381
+ let baseId = undefined;
3280
3382
  if (config.CoverSeparate === 'string') {
3281
3383
  CoverIds.command = config.CommandId;
3384
+ baseId = config.CommandId;
3282
3385
  }
3283
3386
  if (config.CoverSeparate === 'number') {
3284
3387
  CoverIds.number = config.NumberId;
3388
+ baseId = config.NumberId;
3285
3389
  }
3286
3390
  if (config.CoverSeparate === 'separate') {
3287
3391
  CoverIds.open = config.OpenId;
3392
+ baseId = config.OpenId;
3288
3393
  CoverIds.close = config.CloseId;
3289
3394
  if (config.CoverStop) {
3290
3395
  CoverIds.stop = config.StopId;
@@ -3292,7 +3397,12 @@ class bridgeClass {
3292
3397
  }
3293
3398
  if (config.CoverPosition) {
3294
3399
  CoverIds.position = config.PositionId;
3400
+ } else {
3401
+ if (config.CoverSimulatePosition) {
3402
+ CoverIds.simulatePosition = baseId + this.EndingVirtualPosition;
3403
+ }
3295
3404
  }
3405
+
3296
3406
  if (config.CoverTilt) {
3297
3407
  CoverIds.tilt = config.TiltId;
3298
3408
  }
@@ -3307,9 +3417,12 @@ class bridgeClass {
3307
3417
  }
3308
3418
  }
3309
3419
  for (const id of Object.values(CoverIds)) {
3310
- if (!(await this.adapter.foreignObjectExists(id))) {
3311
- this.adapter.log.debug(`Id: ${id} does not exsit.`);
3312
- return false;
3420
+ // Just look to object, if it does not end with Virtual Position
3421
+ if (!id.endsWith(this.EndingVirtualPosition)) {
3422
+ if (!(await this.adapter.foreignObjectExists(id))) {
3423
+ this.adapter.log.debug(`Id: ${id} does not exsit.`);
3424
+ return false;
3425
+ }
3313
3426
  }
3314
3427
  }
3315
3428
  if (config.CoverName === '') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.19.29",
3
+ "version": "1.19.30",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",