homematic-manager 3.1.2 → 3.1.4

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.
Files changed (26) hide show
  1. package/data/profiles/ACCESS_RECEIVER.json +12 -12
  2. package/data/profiles/ACOUSTIC_SIGNAL_VIRTUAL_RECEIVER.json +14 -14
  3. package/data/profiles/ALARM_COND_SWITCH_RECEIVER.json +2 -2
  4. package/data/profiles/BLIND_VIRTUAL_RECEIVER.json +214 -214
  5. package/data/profiles/DIMMER_VIRTUAL_RECEIVER.json +21 -21
  6. package/data/profiles/DOOR_LOCK_TRANSCEIVER.json +26 -26
  7. package/data/profiles/DOOR_RECEIVER.json +28 -28
  8. package/data/profiles/RGBW_COLOR.json +1 -1
  9. package/data/profiles/SERVO_VIRTUAL_RECEIVER.json +1 -1
  10. package/data/profiles/SHUTTER_VIRTUAL_RECEIVER.json +224 -224
  11. package/data/profiles/SIMPLE_SWITCH_RECEIVER.json +3 -3
  12. package/data/profiles/SWITCH_VIRTUAL_RECEIVER.json +38 -38
  13. package/data/profiles/UNIVERSAL_ACTOR.json +21 -21
  14. package/data/profiles/UNIVERSAL_LIGHT_RECEIVER_LSC.json +20 -20
  15. package/data/profiles/UNIVERSAL_LIGHT_RECEIVER_PWM.json +21 -21
  16. package/data/profiles/UNIVERSAL_LIGHT_RECEIVER_RGB(W).json +16 -16
  17. package/data/profiles/UNIVERSAL_LIGHT_RECEIVER_RGBW_DALI.json +16 -16
  18. package/data/profiles/WATER_SWITCH_VIRTUAL_RECEIVER.json +23 -23
  19. package/data/profiles/WINDOW_DRIVE_RECEIVER.json +22 -22
  20. package/node_modules/@homematic-manager/backend/dist/interfaces/manager.d.ts +21 -0
  21. package/node_modules/@homematic-manager/backend/dist/interfaces/manager.js +79 -7
  22. package/node_modules/@homematic-manager/backend/package.json +1 -1
  23. package/node_modules/@homematic-manager/core/package.json +1 -1
  24. package/package.json +4 -4
  25. package/ui/assets/{index-sv7OiesL.js → index-h3gSBtM8.js} +14 -14
  26. package/ui/index.html +1 -1
@@ -1842,7 +1842,7 @@
1842
1842
  "subsets": [1, 2],
1843
1843
  "label": {"de": "Schalten bei", "en": "Switching at"},
1844
1844
  "names": [
1845
- {"de": "%DCberschreiten der oberen Helligkeitsschwelle", "en": "Reaching the upper brightness threshold"},
1845
+ {"de": "Überschreiten der oberen Helligkeitsschwelle", "en": "Reaching the upper brightness threshold"},
1846
1846
  {
1847
1847
  "de": "Unterschreiten der unteren Helligkeitsschwelle",
1848
1848
  "en": "Value falls below lower brightness threshold"
@@ -1902,7 +1902,7 @@
1902
1902
  "subsets": [1, 2],
1903
1903
  "label": {"de": "Schalten bei", "en": "Switching at"},
1904
1904
  "names": [
1905
- {"de": "%DCberschreiten der oberen Helligkeitsschwelle", "en": "Reaching the upper brightness threshold"},
1905
+ {"de": "Überschreiten der oberen Helligkeitsschwelle", "en": "Reaching the upper brightness threshold"},
1906
1906
  {
1907
1907
  "de": "Unterschreiten der unteren Helligkeitsschwelle",
1908
1908
  "en": "Value falls below lower brightness threshold"
@@ -1961,7 +1961,7 @@
1961
1961
  "subsets": [1, 2],
1962
1962
  "label": {"de": "Schalten bei", "en": "Switching at"},
1963
1963
  "names": [
1964
- {"de": "%DCberschreiten der oberen Helligkeitsschwelle", "en": "Reaching the upper brightness threshold"},
1964
+ {"de": "Überschreiten der oberen Helligkeitsschwelle", "en": "Reaching the upper brightness threshold"},
1965
1965
  {
1966
1966
  "de": "Unterschreiten der unteren Helligkeitsschwelle",
1967
1967
  "en": "Value falls below lower brightness threshold"
@@ -2056,7 +2056,7 @@
2056
2056
  "subsets": [1, 2],
2057
2057
  "label": {"de": "Schalten bei", "en": "Switching at"},
2058
2058
  "names": [
2059
- {"de": "%DCberschreiten der oberen Feuchtigkeitsschwelle", "en": "Reaching the upper humidity threshold"},
2059
+ {"de": "Überschreiten der oberen Feuchtigkeitsschwelle", "en": "Reaching the upper humidity threshold"},
2060
2060
  {
2061
2061
  "de": "Unterschreiten der unteren Feuchtigkeitsschwelle",
2062
2062
  "en": "Value falls below lower humidity threshold"
@@ -2116,7 +2116,7 @@
2116
2116
  "subsets": [1, 2],
2117
2117
  "label": {"de": "Schalten bei", "en": "Switching at"},
2118
2118
  "names": [
2119
- {"de": "%DCberschreiten der oberen Feuchtigkeitsschwelle", "en": "Reaching the upper humidity threshold"},
2119
+ {"de": "Überschreiten der oberen Feuchtigkeitsschwelle", "en": "Reaching the upper humidity threshold"},
2120
2120
  {
2121
2121
  "de": "Unterschreiten der unteren Feuchtigkeitsschwelle",
2122
2122
  "en": "Value falls below lower humidity threshold"
@@ -2175,7 +2175,7 @@
2175
2175
  "subsets": [1, 2],
2176
2176
  "label": {"de": "Schalten bei", "en": "Switching at"},
2177
2177
  "names": [
2178
- {"de": "%DCberschreiten der oberen Feuchtigkeitsschwelle", "en": "Reaching the upper humidity threshold"},
2178
+ {"de": "Überschreiten der oberen Feuchtigkeitsschwelle", "en": "Reaching the upper humidity threshold"},
2179
2179
  {
2180
2180
  "de": "Unterschreiten der unteren Feuchtigkeitsschwelle",
2181
2181
  "en": "Value falls below lower humidity threshold"
@@ -2271,7 +2271,7 @@
2271
2271
  "label": {"de": "Schalten bei", "en": "Switching at"},
2272
2272
  "names": [
2273
2273
  {
2274
- "de": "%DCberschreiten der oberen Feinstaubkonzentration",
2274
+ "de": "Überschreiten der oberen Feinstaubkonzentration",
2275
2275
  "en": "Reaching the upper particulate matter threshold"
2276
2276
  },
2277
2277
  {
@@ -2334,7 +2334,7 @@
2334
2334
  "label": {"de": "Schalten bei", "en": "Switching at"},
2335
2335
  "names": [
2336
2336
  {
2337
- "de": "%DCberschreiten der oberen Feinstaubkonzentration",
2337
+ "de": "Überschreiten der oberen Feinstaubkonzentration",
2338
2338
  "en": "Reaching the upper particulate matter threshold"
2339
2339
  },
2340
2340
  {
@@ -2396,7 +2396,7 @@
2396
2396
  "label": {"de": "Schalten bei", "en": "Switching at"},
2397
2397
  "names": [
2398
2398
  {
2399
- "de": "%DCberschreiten der oberen Feinstaubkonzentration",
2399
+ "de": "Überschreiten der oberen Feinstaubkonzentration",
2400
2400
  "en": "Reaching the upper particulate matter threshold"
2401
2401
  },
2402
2402
  {
@@ -2867,7 +2867,7 @@
2867
2867
  "subsets": [1, 2],
2868
2868
  "label": {"de": "Schalten bei", "en": "Switching at"},
2869
2869
  "names": [
2870
- {"de": "%DCberschreiten der oberen Temperaturschwelle", "en": "Reaching the upper temperature threshold"},
2870
+ {"de": "Überschreiten der oberen Temperaturschwelle", "en": "Reaching the upper temperature threshold"},
2871
2871
  {
2872
2872
  "de": "Unterschreiten der unteren Temperaturschwelle",
2873
2873
  "en": "Value falls below lower temperature threshold"
@@ -2927,7 +2927,7 @@
2927
2927
  "subsets": [1, 2],
2928
2928
  "label": {"de": "Schalten bei", "en": "Switching at"},
2929
2929
  "names": [
2930
- {"de": "%DCberschreiten der oberen Temperaturschwelle", "en": "Reaching the upper temperature threshold"},
2930
+ {"de": "Überschreiten der oberen Temperaturschwelle", "en": "Reaching the upper temperature threshold"},
2931
2931
  {
2932
2932
  "de": "Unterschreiten der unteren Temperaturschwelle",
2933
2933
  "en": "Value falls below lower temperature threshold"
@@ -2986,17 +2986,17 @@
2986
2986
  "subsets": [1, 2, 3, 4],
2987
2987
  "label": {"de": "Schalten bei", "en": "Switching at"},
2988
2988
  "names": [
2989
- {"de": "%DCberschreiten der oberen Temperaturschwelle", "en": "Reaching the upper temperature threshold"},
2989
+ {"de": "Überschreiten der oberen Temperaturschwelle", "en": "Reaching the upper temperature threshold"},
2990
2990
  {
2991
2991
  "de": "Unterschreiten der unteren Temperaturschwelle",
2992
2992
  "en": "Value falls below lower temperature threshold"
2993
2993
  },
2994
2994
  {
2995
- "de": "Obere Temperaturschwelle %FCberschritten ein / untere -schwelle unterschritten aus",
2995
+ "de": "Obere Temperaturschwelle überschritten ein / untere -schwelle unterschritten aus",
2996
2996
  "en": "Reaching the upper temperature threshold on - Value falls below lower threshold off"
2997
2997
  },
2998
2998
  {
2999
- "de": "Obere Temperaturschwelle %FCberschritten aus / untere -schwelle unterschritten ein",
2999
+ "de": "Obere Temperaturschwelle überschritten aus / untere -schwelle unterschritten ein",
3000
3000
  "en": "Reaching the upper temperature threshold off - Value falls below lower threshold on"
3001
3001
  }
3002
3002
  ]
@@ -3089,7 +3089,7 @@
3089
3089
  "subsets": [1, 2],
3090
3090
  "label": {"de": "Schalten bei", "en": "Switching at"},
3091
3091
  "names": [
3092
- {"de": "%DCberschreiten des oberen Wertes", "en": "Reaching the upper value"},
3092
+ {"de": "Überschreiten des oberen Wertes", "en": "Reaching the upper value"},
3093
3093
  {"de": "Unterschreiten des unteren Wertes", "en": "Reaching the lower value"}
3094
3094
  ]
3095
3095
  },
@@ -3146,7 +3146,7 @@
3146
3146
  "subsets": [1, 2],
3147
3147
  "label": {"de": "Schalten bei", "en": "Switching at"},
3148
3148
  "names": [
3149
- {"de": "%DCberschreiten des oberen Wertes", "en": "Reaching the upper value"},
3149
+ {"de": "Überschreiten des oberen Wertes", "en": "Reaching the upper value"},
3150
3150
  {"de": "Unterschreiten des unteren Wertes", "en": "Reaching the lower value"}
3151
3151
  ]
3152
3152
  },
@@ -3202,7 +3202,7 @@
3202
3202
  "subsets": [1, 2],
3203
3203
  "label": {"de": "Schalten bei", "en": "Switching at"},
3204
3204
  "names": [
3205
- {"de": "%DCberschreiten des oberen Wertes", "en": "Reaching the upper value"},
3205
+ {"de": "Überschreiten des oberen Wertes", "en": "Reaching the upper value"},
3206
3206
  {"de": "Unterschreiten des unteren Wertes", "en": "Reaching the lower value"}
3207
3207
  ]
3208
3208
  },
@@ -3294,7 +3294,7 @@
3294
3294
  "subsets": [1, 2],
3295
3295
  "label": {"de": "Schalten bei", "en": "Switching at"},
3296
3296
  "names": [
3297
- {"de": "%DCberschreiten der oberen Windschwelle", "en": "Reaching the upper wind threshhold"},
3297
+ {"de": "Überschreiten der oberen Windschwelle", "en": "Reaching the upper wind threshhold"},
3298
3298
  {"de": "Unterschreiten der unteren Windschwelle", "en": "Reaching the lower wind threshold"}
3299
3299
  ]
3300
3300
  },
@@ -3351,7 +3351,7 @@
3351
3351
  "subsets": [1, 2],
3352
3352
  "label": {"de": "Schalten bei", "en": "Switching at"},
3353
3353
  "names": [
3354
- {"de": "%DCberschreiten der oberen Windschwelle", "en": "Reaching the upper wind threshhold"},
3354
+ {"de": "Überschreiten der oberen Windschwelle", "en": "Reaching the upper wind threshhold"},
3355
3355
  {"de": "Unterschreiten der unteren Windschwelle", "en": "Reaching the lower wind threshold"}
3356
3356
  ]
3357
3357
  },
@@ -3407,7 +3407,7 @@
3407
3407
  "subsets": [1, 2],
3408
3408
  "label": {"de": "Schalten bei", "en": "Switching at"},
3409
3409
  "names": [
3410
- {"de": "%DCberschreiten der oberen Windschwelle", "en": "Reaching the upper wind threshhold"},
3410
+ {"de": "Überschreiten der oberen Windschwelle", "en": "Reaching the upper wind threshhold"},
3411
3411
  {"de": "Unterschreiten der unteren Windschwelle", "en": "Reaching the lower wind threshold"}
3412
3412
  ]
3413
3413
  },
@@ -8820,7 +8820,7 @@
8820
8820
  "key": "switch_on",
8821
8821
  "name": {"de": "Bewässerungsaktor ein", "en": "Irrigation actuator - on"},
8822
8822
  "description": {
8823
- "de": "Bei Bet%E4tigung des Bewässerungsaktors wird der Schaltaktor für die festgelegte Zeit eingeschaltet. Ist eine Verzögerungszeit eingestellt, erfolgt eine Schaltung erst nach Ablauf dieser Zeit .",
8823
+ "de": "Bei Betätigung des Bewässerungsaktors wird der Schaltaktor für die festgelegte Zeit eingeschaltet. Ist eine Verzögerungszeit eingestellt, erfolgt eine Schaltung erst nach Ablauf dieser Zeit .",
8824
8824
  "en": "When closing the switch the irrigation actuator will be switched on for the set time. If a delay is set switching will be performed after the delay time has expired."
8825
8825
  },
8826
8826
  "params": {
@@ -8897,7 +8897,7 @@
8897
8897
  "key": "switch_off",
8898
8898
  "name": {"de": "Bewässerungsaktor aus", "en": "Irrigation actuator - off"},
8899
8899
  "description": {
8900
- "de": "Bei Bet%E4tigung des Bewässerungsaktors wird der Schaltaktor für die festgelegte Zeit ausgeschaltet. Ist eine Verzögerungszeit eingestellt, erfolgt eine Schaltung erst nach Ablauf dieser Zeit .",
8900
+ "de": "Bei Betätigung des Bewässerungsaktors wird der Schaltaktor für die festgelegte Zeit ausgeschaltet. Ist eine Verzögerungszeit eingestellt, erfolgt eine Schaltung erst nach Ablauf dieser Zeit .",
8901
8901
  "en": "When closing the switch the irrigation actuator will be switched off for the set time. If a delay time is set switching will be performed after the time has expired."
8902
8902
  },
8903
8903
  "params": {
@@ -8979,7 +8979,7 @@
8979
8979
  "key": "switch_on_off",
8980
8980
  "name": {"de": "Bewässerungsaktor ein / aus", "en": "Irrigation actuator - on / off"},
8981
8981
  "description": {
8982
- "de": "Bei Bet%E4tigung des Bewässerungsaktors wird der Schaltaktor für die festgelegte Zeit ein- oder ausgeschaltet (Toggle-Funktion). Ist eine Verzögerungszeit eingestellt, erfolgt eine Schaltung erst nach Ablauf dieser Zeit .",
8982
+ "de": "Bei Betätigung des Bewässerungsaktors wird der Schaltaktor für die festgelegte Zeit ein- oder ausgeschaltet (Toggle-Funktion). Ist eine Verzögerungszeit eingestellt, erfolgt eine Schaltung erst nach Ablauf dieser Zeit .",
8983
8983
  "en": "If the switch is closed the irrigation actuator will be switched on or off for the time set (toggle function). If a delay time is set switching will be performed after the time has expired."
8984
8984
  },
8985
8985
  "params": {
@@ -14,7 +14,7 @@
14
14
  "key": "switch_toggle",
15
15
  "name": {"de": "Toggle", "en": "Toggle"},
16
16
  "description": {
17
- "de": "Bei Empfang des gewählten Entscheidungswertes wird ein geschlossenes Fenster für die festgelegte Zeit ge%F6ffnet bzw. ein göffnetes Fenster geschlossen (Toggle-Funktion). Ist eine Verzögerungszeit eingestellt, erfolgt das %D6ffnen/Schlie%DFen erst nach Ablauf dieser Zeit.",
17
+ "de": "Bei Empfang des gewählten Entscheidungswertes wird ein geschlossenes Fenster für die festgelegte Zeit geöffnet bzw. ein göffnetes Fenster geschlossen (Toggle-Funktion). Ist eine Verzögerungszeit eingestellt, erfolgt das Öffnen/Schließen erst nach Ablauf dieser Zeit.",
18
18
  "en": "When receiving the selected decision value, a closed window is opened for the specified time or an open window is closed (toggle function). If a delay time is set, opening/closing will be performed only after this time has expired."
19
19
  },
20
20
  "params": {
@@ -61,7 +61,7 @@
61
61
  "kind": "time",
62
62
  "prefix": "SHORT_ONDELAY_TIME",
63
63
  "selector": "delay",
64
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
64
+ "label": {"de": "Verzögerung", "en": "Delay"}
65
65
  },
66
66
  {
67
67
  "kind": "time",
@@ -74,7 +74,7 @@
74
74
  {
75
75
  "id": 2,
76
76
  "key": "switch_on_off",
77
- "name": {"de": "Fenster %F6ffnen/schlie%DFen", "en": "Open/Close window"},
77
+ "name": {"de": "Fenster öffnen/schließen", "en": "Open/Close window"},
78
78
  "description": {
79
79
  "de": "Bei Empfang des gewählten Entscheidungswertes wird das Fenster für die festgelegte Zeit je nach Einstellung des Parameters 'Entscheidungswert' geöffnet oder geschlossen.",
80
80
  "en": "When receiving the selected decision value, the window is opened or closed for the specified time according to the setting of the 'Decision value' parameter."
@@ -125,7 +125,7 @@
125
125
  "kind": "time",
126
126
  "prefix": "SHORT_ONDELAY_TIME",
127
127
  "selector": "delay",
128
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
128
+ "label": {"de": "Verzögerung", "en": "Delay"}
129
129
  },
130
130
  {
131
131
  "kind": "time",
@@ -138,7 +138,7 @@
138
138
  {
139
139
  "id": 3,
140
140
  "key": "profile_3",
141
- "name": {"de": "Fenster schlie%DFen", "en": "Close window"},
141
+ "name": {"de": "Fenster schließen", "en": "Close window"},
142
142
  "description": {},
143
143
  "params": {
144
144
  "SHORT_COND_VALUE_HI": {"kind": "fixed", "value": 200},
@@ -236,7 +236,7 @@
236
236
  "kind": "time",
237
237
  "prefix": "SHORT_ONDELAY_TIME",
238
238
  "selector": "delay",
239
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
239
+ "label": {"de": "Verzögerung", "en": "Delay"}
240
240
  },
241
241
  {
242
242
  "kind": "time",
@@ -248,7 +248,7 @@
248
248
  "kind": "time",
249
249
  "prefix": "LONG_ONDELAY_TIME",
250
250
  "selector": "delay",
251
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
251
+ "label": {"de": "Verzögerung", "en": "Delay"}
252
252
  },
253
253
  {
254
254
  "kind": "time",
@@ -318,7 +318,7 @@
318
318
  "kind": "time",
319
319
  "prefix": "SHORT_ONDELAY_TIME",
320
320
  "selector": "delay",
321
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
321
+ "label": {"de": "Verzögerung", "en": "Delay"}
322
322
  },
323
323
  {
324
324
  "kind": "time",
@@ -330,7 +330,7 @@
330
330
  "kind": "time",
331
331
  "prefix": "LONG_ONDELAY_TIME",
332
332
  "selector": "delay",
333
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
333
+ "label": {"de": "Verzögerung", "en": "Delay"}
334
334
  },
335
335
  {
336
336
  "kind": "time",
@@ -400,7 +400,7 @@
400
400
  "kind": "time",
401
401
  "prefix": "SHORT_ONDELAY_TIME",
402
402
  "selector": "delay",
403
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
403
+ "label": {"de": "Verzögerung", "en": "Delay"}
404
404
  },
405
405
  {
406
406
  "kind": "time",
@@ -412,7 +412,7 @@
412
412
  "kind": "time",
413
413
  "prefix": "LONG_ONDELAY_TIME",
414
414
  "selector": "delay",
415
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
415
+ "label": {"de": "Verzögerung", "en": "Delay"}
416
416
  },
417
417
  {
418
418
  "kind": "time",
@@ -436,7 +436,7 @@
436
436
  "key": "switch_toggle",
437
437
  "name": {"de": "Toggle", "en": "Toggle"},
438
438
  "description": {
439
- "de": "Mit einem kurzen oder langen Tastendruck wird das Fenster für die festgelegte Zeit ge%F6ffnet oder geschlossen (Toggle-Funktion). Ist eine Verzögerungszeit eingestellt, erfolgt das %D6ffnen/Schlie%DFen erst nach Ablauf dieser Zeit.",
439
+ "de": "Mit einem kurzen oder langen Tastendruck wird das Fenster für die festgelegte Zeit geöffnet oder geschlossen (Toggle-Funktion). Ist eine Verzögerungszeit eingestellt, erfolgt das Öffnen/Schließen erst nach Ablauf dieser Zeit.",
440
440
  "en": "Short or long pressing of the button opens or closes the window for the specified time (toggle function). If a delay time is set, opening/closing will be performed only after this time has expired."
441
441
  },
442
442
  "params": {
@@ -494,7 +494,7 @@
494
494
  "kind": "time",
495
495
  "prefix": "SHORT_ONDELAY_TIME",
496
496
  "selector": "delay",
497
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
497
+ "label": {"de": "Verzögerung", "en": "Delay"}
498
498
  },
499
499
  {
500
500
  "kind": "time",
@@ -506,7 +506,7 @@
506
506
  "kind": "time",
507
507
  "prefix": "LONG_ONDELAY_TIME",
508
508
  "selector": "delay",
509
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
509
+ "label": {"de": "Verzögerung", "en": "Delay"}
510
510
  },
511
511
  {
512
512
  "kind": "time",
@@ -519,9 +519,9 @@
519
519
  {
520
520
  "id": 2,
521
521
  "key": "switch_on",
522
- "name": {"de": "Fenster %F6ffnen", "en": "Open window"},
522
+ "name": {"de": "Fenster öffnen", "en": "Open window"},
523
523
  "description": {
524
- "de": "Mit einem kurzen oder langen Tastendruck wird das Fenster für die festgelegte Zeit ge%F6ffnet. Ist eine Verzögerungszeit eingestellt, erfolgt das %D6ffnen erst nach Ablauf dieser Zeit.",
524
+ "de": "Mit einem kurzen oder langen Tastendruck wird das Fenster für die festgelegte Zeit geöffnet. Ist eine Verzögerungszeit eingestellt, erfolgt das Öffnen erst nach Ablauf dieser Zeit.",
525
525
  "en": "Short or long pressing of the button opens the window for the specified time. If a delay time is set, opening will be performed only after this time has expired."
526
526
  },
527
527
  "params": {
@@ -579,7 +579,7 @@
579
579
  "kind": "time",
580
580
  "prefix": "SHORT_ONDELAY_TIME",
581
581
  "selector": "delay",
582
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
582
+ "label": {"de": "Verzögerung", "en": "Delay"}
583
583
  },
584
584
  {
585
585
  "kind": "time",
@@ -591,7 +591,7 @@
591
591
  "kind": "time",
592
592
  "prefix": "LONG_ONDELAY_TIME",
593
593
  "selector": "delay",
594
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
594
+ "label": {"de": "Verzögerung", "en": "Delay"}
595
595
  },
596
596
  {
597
597
  "kind": "time",
@@ -604,9 +604,9 @@
604
604
  {
605
605
  "id": 3,
606
606
  "key": "switch_off",
607
- "name": {"de": "Fenster schlie%DFen", "en": "Close window"},
607
+ "name": {"de": "Fenster schließen", "en": "Close window"},
608
608
  "description": {
609
- "de": "Mit einem kurzen oder langen Tastendruck wird das Fenster für die festgelegte Zeit geschlossen. Ist eine Verzögerungszeit eingestellt, erfolgt das Schlie%DFen erst nach Ablauf dieser Zeit.",
609
+ "de": "Mit einem kurzen oder langen Tastendruck wird das Fenster für die festgelegte Zeit geschlossen. Ist eine Verzögerungszeit eingestellt, erfolgt das Schließen erst nach Ablauf dieser Zeit.",
610
610
  "en": "Short or long pressing of the button closes the window for the specified time. If a delay time is set, closing will be performed only after this time has expired."
611
611
  },
612
612
  "params": {
@@ -664,7 +664,7 @@
664
664
  "kind": "time",
665
665
  "prefix": "SHORT_ONDELAY_TIME",
666
666
  "selector": "delay",
667
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
667
+ "label": {"de": "Verzögerung", "en": "Delay"}
668
668
  },
669
669
  {
670
670
  "kind": "time",
@@ -676,7 +676,7 @@
676
676
  "kind": "time",
677
677
  "prefix": "LONG_ONDELAY_TIME",
678
678
  "selector": "delay",
679
- "label": {"de": "Verz%F6gerung", "en": "Delay"}
679
+ "label": {"de": "Verzögerung", "en": "Delay"}
680
680
  },
681
681
  {
682
682
  "kind": "time",
@@ -14,6 +14,9 @@
14
14
  * D-58): its port is tried every 3 s for 90 s after the start (or after it went missing) and then
15
15
  * every 15 s, a TCP connect first and the `init` only when the port answers; at the start the
16
16
  * interface shows *waiting*, and when another interface appears every missing one is tried at once.
17
+ * An `init` that times out while the port answers is a busy process, not a missing one (B-89): the
18
+ * next attempt waits 15 s, doubling up to 5 min. There is never more than one `init` per interface
19
+ * in flight; whatever asks for another one meanwhile joins it.
17
20
  * HmIP-RF has a liveness ping of its own besides (B-56, D-53): after 30 s of silence it is
18
21
  * pinged, and a missing PONG 10 s later means hmipserver has restarted - it reads its handler
19
22
  * list back but sends nothing until the client calls `init` again - so the interface shows
@@ -68,6 +71,17 @@ export declare const START_RETRY_INTERVAL_MS = 3000;
68
71
  * no log line (task 13's four ERROR lines a minute came from the `init` calls).
69
72
  */
70
73
  export declare const MISSING_RETRY_INTERVAL_MS = 15000;
74
+ /**
75
+ * B-89: the first wait after an `init` that timed out while the port answers; it doubles per further
76
+ * timeout up to {@link MAX_INIT_BACKOFF_MS}.
77
+ *
78
+ * Such an interface is there and busy, not missing. Seen on an openccu-lite system where the group
79
+ * process behind VirtualDevices ran without HmIP-RF: an `init` took about 10 s to come back there,
80
+ * the quick retries of a missing interface (3 s) and the watchdog sent the next ones before the
81
+ * earlier ones were through, they queued up past the RPC timeout, and the app subscribed again
82
+ * every 10 s - for as long as it ran.
83
+ */
84
+ export declare const INIT_TIMEOUT_BACKOFF_MS = 15000;
71
85
  /**
72
86
  * Task 56, task 83 (D-58): how long after `start()` (or a D-31 resubscribe, or the moment an interface
73
87
  * went missing) it is tried every {@link START_RETRY_INTERVAL_MS}. At the start an interface that
@@ -99,6 +113,13 @@ export interface ManagedInterface {
99
113
  lastSeenMono: number;
100
114
  /** Consecutive failed `init` calls; 0 as soon as one succeeds. */
101
115
  failures: number;
116
+ /**
117
+ * B-89: the `init` call in flight, which every other attempt joins instead of sending another
118
+ * one - the watchdog, a retry timer, another interface appearing, a lost PONG, the user.
119
+ */
120
+ initInFlight: Promise<void> | undefined;
121
+ /** B-89: consecutive `init` calls that timed out while the port answered; 0 once one succeeds or the port closes. */
122
+ initTimeouts: number;
102
123
  /** On the monotonic clock (B-65): the moment before which the watchdog does not try `init` again. */
103
124
  retryAt: number;
104
125
  /** Task 56: failed attempts (a closed port or a failed `init`) while waiting at the start; 0 once it answered. */
@@ -14,6 +14,9 @@
14
14
  * D-58): its port is tried every 3 s for 90 s after the start (or after it went missing) and then
15
15
  * every 15 s, a TCP connect first and the `init` only when the port answers; at the start the
16
16
  * interface shows *waiting*, and when another interface appears every missing one is tried at once.
17
+ * An `init` that times out while the port answers is a busy process, not a missing one (B-89): the
18
+ * next attempt waits 15 s, doubling up to 5 min. There is never more than one `init` per interface
19
+ * in flight; whatever asks for another one meanwhile joins it.
17
20
  * HmIP-RF has a liveness ping of its own besides (B-56, D-53): after 30 s of silence it is
18
21
  * pinged, and a missing PONG 10 s later means hmipserver has restarted - it reads its handler
19
22
  * list back but sends nothing until the client calls `init` again - so the interface shows
@@ -75,6 +78,17 @@ export const START_RETRY_INTERVAL_MS = 3000;
75
78
  * no log line (task 13's four ERROR lines a minute came from the `init` calls).
76
79
  */
77
80
  export const MISSING_RETRY_INTERVAL_MS = 15_000;
81
+ /**
82
+ * B-89: the first wait after an `init` that timed out while the port answers; it doubles per further
83
+ * timeout up to {@link MAX_INIT_BACKOFF_MS}.
84
+ *
85
+ * Such an interface is there and busy, not missing. Seen on an openccu-lite system where the group
86
+ * process behind VirtualDevices ran without HmIP-RF: an `init` took about 10 s to come back there,
87
+ * the quick retries of a missing interface (3 s) and the watchdog sent the next ones before the
88
+ * earlier ones were through, they queued up past the RPC timeout, and the app subscribed again
89
+ * every 10 s - for as long as it ran.
90
+ */
91
+ export const INIT_TIMEOUT_BACKOFF_MS = 15_000;
78
92
  /**
79
93
  * Task 56, task 83 (D-58): how long after `start()` (or a D-31 resubscribe, or the moment an interface
80
94
  * went missing) it is tried every {@link START_RETRY_INTERVAL_MS}. At the start an interface that
@@ -118,6 +132,10 @@ export function callbackBindHost(connection) {
118
132
  const { ip } = connection.callback;
119
133
  return ip === LOOPBACK_IP || (ip === '' && connection.local === true) ? LOOPBACK_IP : undefined;
120
134
  }
135
+ /** B-89: the `init` in flight, read through a function so that a check after an `await` is not narrowed away. */
136
+ function inFlight(entry) {
137
+ return entry.initInFlight;
138
+ }
121
139
  /** Connects, watches and disconnects every configured interface. */
122
140
  export class InterfaceManager {
123
141
  #options;
@@ -385,6 +403,7 @@ export class InterfaceManager {
385
403
  if (entry.state.absent !== true) {
386
404
  entry.failures = 0;
387
405
  }
406
+ entry.initTimeouts = 0;
388
407
  entry.retryAt = 0;
389
408
  entry.waitingAttempts = 0;
390
409
  entry.answered = false;
@@ -417,7 +436,9 @@ export class InterfaceManager {
417
436
  entry.missingSince = undefined;
418
437
  this.#update(entry, { idle: false });
419
438
  }
420
- await Promise.all([...this.#interfaces.keys()].map((name) => this.#init(name)));
439
+ // B-89: an `init` still in flight from before the idle period may have reached the interface
440
+ // before the de-registration did, so it does not count
441
+ await Promise.all([...this.#interfaces.keys()].map((name) => this.#init(name, { fresh: true })));
421
442
  this.#startWatchdog();
422
443
  this.#options.onStateChanged(this.states());
423
444
  }
@@ -635,6 +656,8 @@ export class InterfaceManager {
635
656
  lastEvent: 0,
636
657
  lastSeenMono: Number.NEGATIVE_INFINITY,
637
658
  failures: 0,
659
+ initInFlight: undefined,
660
+ initTimeouts: 0,
638
661
  retryAt: 0,
639
662
  waitingAttempts: 0,
640
663
  retryTimer: undefined,
@@ -719,7 +742,39 @@ export class InterfaceManager {
719
742
  });
720
743
  this.#options.onStateChanged(this.states());
721
744
  }
722
- async #init(interfaceName) {
745
+ /**
746
+ * Subscribes one interface. B-89: never twice at once - an attempt while an `init` for the same
747
+ * interface is in flight joins that one. `fresh` waits for it and sends a new one: a resubscribe
748
+ * after the idle period must not count an `init` that the de-registration may have overtaken.
749
+ */
750
+ async #init(interfaceName, { fresh = false } = {}) {
751
+ const entry = this.#interfaces.get(interfaceName);
752
+ if (entry?.initInFlight !== undefined) {
753
+ if (!fresh) {
754
+ return entry.initInFlight;
755
+ }
756
+ await entry.initInFlight.catch(() => undefined);
757
+ const next = inFlight(entry);
758
+ if (next !== undefined) {
759
+ // someone else started a new one meanwhile, after the wait: that one is fresh
760
+ return next;
761
+ }
762
+ }
763
+ const attempt = this.#initOnce(interfaceName);
764
+ if (entry === undefined) {
765
+ return attempt;
766
+ }
767
+ entry.initInFlight = attempt;
768
+ try {
769
+ await attempt;
770
+ }
771
+ finally {
772
+ if (entry.initInFlight === attempt) {
773
+ entry.initInFlight = undefined;
774
+ }
775
+ }
776
+ }
777
+ async #initOnce(interfaceName) {
723
778
  const entry = this.#interfaces.get(interfaceName);
724
779
  if (!entry || this.#stopping) {
725
780
  return;
@@ -758,6 +813,7 @@ export class InterfaceManager {
758
813
  // task 83: it was not there a moment ago - at the start, after an outage or a lost subscription
759
814
  const appeared = !entry.answered || wasFailing;
760
815
  entry.failures = 0;
816
+ entry.initTimeouts = 0;
761
817
  entry.retryAt = 0;
762
818
  entry.waitingAttempts = 0;
763
819
  entry.answered = true;
@@ -820,6 +876,8 @@ export class InterfaceManager {
820
876
  const message = errorMessage(error);
821
877
  const absent = isConnectionRefused(error);
822
878
  if (absent || isNotAnswering(error)) {
879
+ // B-89: an `init` that did not come back in time; the next one waits longer each time
880
+ entry.initTimeouts = absent ? 0 : entry.initTimeouts + 1;
823
881
  this.#noteMissing(entry, message, absent);
824
882
  return;
825
883
  }
@@ -884,9 +942,17 @@ export class InterfaceManager {
884
942
  #missingDelay(entry) {
885
943
  const window = this.#options.startWindowMs ?? START_WINDOW_MS;
886
944
  const since = entry.missingSince ?? entry.windowStart;
887
- return window > 0 && this.#monotonicNow() - since < window
888
- ? START_RETRY_INTERVAL_MS
889
- : MISSING_RETRY_INTERVAL_MS;
945
+ return this.#timeoutDelay(entry, window > 0 && this.#monotonicNow() - since < window ? START_RETRY_INTERVAL_MS : MISSING_RETRY_INTERVAL_MS);
946
+ }
947
+ /**
948
+ * B-89: after an `init` that timed out while the port answered, the process is busy rather than
949
+ * missing - {@link INIT_TIMEOUT_BACKOFF_MS}, doubling per further timeout, instead of `delay`.
950
+ */
951
+ #timeoutDelay(entry, delay) {
952
+ if (entry.initTimeouts === 0) {
953
+ return delay;
954
+ }
955
+ return Math.max(delay, Math.min(INIT_TIMEOUT_BACKOFF_MS * 2 ** (entry.initTimeouts - 1), MAX_INIT_BACKOFF_MS));
890
956
  }
891
957
  /** Task 83: the next attempt of a missing interface, on a timer the watchdog leaves alone. */
892
958
  #scheduleRetry(entry, delay) {
@@ -926,6 +992,8 @@ export class InterfaceManager {
926
992
  await this.#init(entry.name);
927
993
  return;
928
994
  }
995
+ // B-89: the port itself is gone now - a missing process, on the quick schedule again
996
+ entry.initTimeouts = 0;
929
997
  const where = `${entry.state.host}:${String(entry.state.port)}`;
930
998
  this.#noteMissing(entry, result === 'refused' ? `connect ECONNREFUSED ${where}` : `${where} does not answer`, result === 'refused');
931
999
  this.#options.onStateChanged(this.states());
@@ -936,7 +1004,11 @@ export class InterfaceManager {
936
1004
  */
937
1005
  #retryMissingNow(except) {
938
1006
  for (const entry of this.#interfaces.values()) {
939
- if (entry.name !== except && entry.retryTimer !== undefined && !entry.state.connected) {
1007
+ // B-89: not one whose `init` timed out - it is busy, and the other one appearing changes nothing
1008
+ if (entry.name !== except &&
1009
+ entry.retryTimer !== undefined &&
1010
+ !entry.state.connected &&
1011
+ entry.initTimeouts === 0) {
940
1012
  this.#clearRetryTimer(entry);
941
1013
  void this.#retryMissing(entry);
942
1014
  }
@@ -977,7 +1049,7 @@ export class InterfaceManager {
977
1049
  else {
978
1050
  this.#options.onNotice('debug', `${entry.name}: still waiting (attempt ${String(entry.waitingAttempts)}: ${message})`, entry.name);
979
1051
  }
980
- this.#scheduleRetry(entry, START_RETRY_INTERVAL_MS);
1052
+ this.#scheduleRetry(entry, this.#timeoutDelay(entry, START_RETRY_INTERVAL_MS));
981
1053
  }
982
1054
  /**
983
1055
  * B-56 (D-53): the liveness ping of an interface that has one (HmIP-RF). After
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homematic-manager/backend",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "type": "module",
5
5
  "description": "Homematic Manager backend: XML-RPC/BIN-RPC clients and callback servers, caches, optional ReGa",
6
6
  "license": "AGPL-3.0-or-later",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homematic-manager/core",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "type": "module",
5
5
  "description": "Pure domain logic of the Homematic Manager: no I/O, no DOM",
6
6
  "license": "AGPL-3.0-or-later",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homematic-manager",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "type": "module",
5
5
  "description": "Configure and administer Homematic and HomematicIP devices - devices and channels, direct links, paramsets, RSSI, service messages, events and an RPC console - from a local HTTP/WebSocket server that also serves the web UI",
6
6
  "keywords": [
@@ -64,11 +64,11 @@
64
64
  },
65
65
  "devDependencies": {
66
66
  "@cyclonedx/cyclonedx-npm": "^4.2.1",
67
- "hm-simulator": "^1.3.0"
67
+ "hm-simulator": "^1.4.0"
68
68
  },
69
69
  "dependencies": {
70
- "@homematic-manager/backend": "3.1.2",
71
- "@homematic-manager/core": "3.1.2",
70
+ "@homematic-manager/backend": "3.1.4",
71
+ "@homematic-manager/core": "3.1.4",
72
72
  "binrpc": "^4.2.0",
73
73
  "homematic-rega": "^2.0.0",
74
74
  "homematic-xmlrpc": "^2.0.0",