iobroker.acinfinity 0.3.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.
@@ -0,0 +1,212 @@
1
+ /**
2
+ * PortSettingsHandler für AC Infinity Adapter
3
+ * Verarbeitet Änderungen an den erweiterten Port-Einstellungen
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const {
9
+ ADVANCED_SETTINGS_KEY,
10
+ DEVICE_LOAD_TYPE_OPTIONS,
11
+ DYNAMIC_RESPONSE_OPTIONS
12
+ } = require('../constants');
13
+
14
+ class PortSettingsHandler {
15
+ /**
16
+ * Erstellt einen neuen PortSettingsHandler
17
+ * @param {object} stateManager - Referenz zum StateManager
18
+ */
19
+ constructor(stateManager) {
20
+ this.stateManager = stateManager;
21
+ this.adapter = stateManager.adapter;
22
+ this.client = null; // API-Client-Referenz wird später gesetzt
23
+ }
24
+
25
+ /**
26
+ * Setzt den API-Client für diesen Handler
27
+ * @param {object} client - AC Infinity API-Client
28
+ */
29
+ setClient(client) {
30
+ this.client = client;
31
+ this.adapter.log.debug("API-Client erfolgreich an PortSettingsHandler übergeben");
32
+ }
33
+
34
+ /**
35
+ * Verarbeitet Änderungen an erweiterten Port-Einstellungen
36
+ * @param {string} deviceId - Geräte-ID
37
+ * @param {number} portId - Port-ID
38
+ * @param {Array} path - Pfadkomponenten
39
+ * @param {any} value - Neuer Wert
40
+ */
41
+ async handlePortAdvancedSettingsChange(deviceId, portId, path, value) {
42
+ if (path.length < 1) {
43
+ this.adapter.log.warn(`Ungültiger Pfad für erweiterte Port-Einstellungen: ${path.join('.')}`);
44
+ return;
45
+ }
46
+
47
+ const setting = path[0];
48
+ const statePath = `devices.${deviceId}.ports.${portId}.settings.${setting}`;
49
+
50
+ // UI sofort aktualisieren, um Flackern zu vermeiden
51
+ await this.stateManager.updateUIState(statePath, value);
52
+
53
+ try {
54
+ // Prüfen, ob der Client gesetzt ist
55
+ if (!this.client) {
56
+ throw new Error("API-Client nicht gesetzt. Kann Port-Einstellungen nicht aktualisieren.");
57
+ }
58
+
59
+ // Hole den Port-Namen für den Aktualisierungsaufruf
60
+ let portName = await this.adapter.getStateAsync(`devices.${deviceId}.ports.${portId}.info.name`);
61
+ portName = portName && portName.val ? portName.val : `Port ${portId}`;
62
+
63
+ // Aktuelle Temperatureinheit abrufen
64
+ const tempUnitState = await this.adapter.getStateAsync(`devices.${deviceId}.settings.temperatureUnit`);
65
+ const isUnitC = tempUnitState && tempUnitState.val === "C";
66
+
67
+ this.adapter.log.debug(`Verarbeite Port-Einstellungsänderung: deviceId=${deviceId}, portId=${portId}, setting=${setting}, value=${value}`);
68
+
69
+ try {
70
+ switch (setting) {
71
+ case 'deviceType':
72
+ // Finde die Last-Typ-ID für den angegebenen Gerätetyp-Namen
73
+ let loadTypeId = null;
74
+ for (const [id, name] of Object.entries(DEVICE_LOAD_TYPE_OPTIONS)) {
75
+ if (name === value) {
76
+ loadTypeId = parseInt(id);
77
+ break;
78
+ }
79
+ }
80
+
81
+ if (loadTypeId !== null) {
82
+ this.adapter.log.debug(`Sende Gerätetyp an API: deviceId=${deviceId}, portId=${portId}, type=${value}, loadTypeId=${loadTypeId}`);
83
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
84
+ [ADVANCED_SETTINGS_KEY.DEVICE_LOAD_TYPE, loadTypeId]
85
+ ]);
86
+ this.adapter.log.debug(`API-Antwort für Gerätetyp erfolgreich`);
87
+ } else {
88
+ this.adapter.log.warn(`Ungültiger Gerätetyp: ${value}`);
89
+ }
90
+ break;
91
+
92
+ case 'dynamicResponse':
93
+ const responseTypeIndex = DYNAMIC_RESPONSE_OPTIONS.indexOf(value);
94
+ if (responseTypeIndex >= 0) {
95
+ this.adapter.log.debug(`Sende dynamischen Antworttyp an API: deviceId=${deviceId}, portId=${portId}, type=${value}, index=${responseTypeIndex}`);
96
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
97
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_RESPONSE_TYPE, responseTypeIndex]
98
+ ]);
99
+ this.adapter.log.debug(`API-Antwort für dynamischen Antworttyp erfolgreich`);
100
+ } else {
101
+ this.adapter.log.warn(`Ungültiger dynamischer Antworttyp: ${value}`);
102
+ }
103
+ break;
104
+
105
+ case 'dynamicTransitionTemp':
106
+ const transitionTempValue = parseInt(value);
107
+ this.adapter.log.debug(`Sende dynamische Übergangstemperatur an API: deviceId=${deviceId}, portId=${portId}, temp=${transitionTempValue}, isUnitC=${isUnitC}`);
108
+
109
+ if (isUnitC) {
110
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
111
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_TRANSITION_TEMP, transitionTempValue],
112
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_TRANSITION_TEMP_F, transitionTempValue * 2]
113
+ ]);
114
+ } else {
115
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
116
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_TRANSITION_TEMP, Math.floor(transitionTempValue / 2)],
117
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_TRANSITION_TEMP_F, transitionTempValue]
118
+ ]);
119
+ }
120
+
121
+ this.adapter.log.debug(`API-Antwort für dynamische Übergangstemperatur erfolgreich`);
122
+ break;
123
+
124
+ case 'dynamicBufferTemp':
125
+ const bufferTempValue = parseInt(value);
126
+ this.adapter.log.debug(`Sende dynamische Puffertemperatur an API: deviceId=${deviceId}, portId=${portId}, temp=${bufferTempValue}, isUnitC=${isUnitC}`);
127
+
128
+ if (isUnitC) {
129
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
130
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_BUFFER_TEMP, bufferTempValue],
131
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_BUFFER_TEMP_F, bufferTempValue * 2]
132
+ ]);
133
+ } else {
134
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
135
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_BUFFER_TEMP, Math.floor(bufferTempValue / 2)],
136
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_BUFFER_TEMP_F, bufferTempValue]
137
+ ]);
138
+ }
139
+
140
+ this.adapter.log.debug(`API-Antwort für dynamische Puffertemperatur erfolgreich`);
141
+ break;
142
+
143
+ // Weitere Fälle für andere Einstellungen...
144
+ case 'dynamicTransitionHumidity':
145
+ this.adapter.log.debug(`Sende dynamische Übergangsfeuchtigkeit an API: deviceId=${deviceId}, portId=${portId}, humidity=${parseInt(value)}`);
146
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
147
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_TRANSITION_HUMIDITY, parseInt(value)]
148
+ ]);
149
+ this.adapter.log.debug(`API-Antwort für dynamische Übergangsfeuchtigkeit erfolgreich`);
150
+ break;
151
+
152
+ case 'dynamicBufferHumidity':
153
+ this.adapter.log.debug(`Sende dynamische Pufferfeuchtigkeit an API: deviceId=${deviceId}, portId=${portId}, humidity=${parseInt(value)}`);
154
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
155
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_BUFFER_HUMIDITY, parseInt(value)]
156
+ ]);
157
+ this.adapter.log.debug(`API-Antwort für dynamische Pufferfeuchtigkeit erfolgreich`);
158
+ break;
159
+
160
+ case 'dynamicTransitionVPD':
161
+ const transitionVpdValue = Math.round(parseFloat(value) * 10);
162
+ this.adapter.log.debug(`Sende dynamisches Übergangs-VPD an API: deviceId=${deviceId}, portId=${portId}, vpd=${value}, scaledValue=${transitionVpdValue}`);
163
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
164
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_TRANSITION_VPD, transitionVpdValue]
165
+ ]);
166
+ this.adapter.log.debug(`API-Antwort für dynamisches Übergangs-VPD erfolgreich`);
167
+ break;
168
+
169
+ case 'dynamicBufferVPD':
170
+ const bufferVpdValue = Math.round(parseFloat(value) * 10);
171
+ this.adapter.log.debug(`Sende dynamisches Puffer-VPD an API: deviceId=${deviceId}, portId=${portId}, vpd=${value}, scaledValue=${bufferVpdValue}`);
172
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
173
+ [ADVANCED_SETTINGS_KEY.DYNAMIC_BUFFER_VPD, bufferVpdValue]
174
+ ]);
175
+ this.adapter.log.debug(`API-Antwort für dynamisches Puffer-VPD erfolgreich`);
176
+ break;
177
+
178
+ case 'sunriseTimerEnabled':
179
+ this.adapter.log.debug(`Sende Sonnenaufgang/Sonnenuntergang-Timer-Aktivierung an API: deviceId=${deviceId}, portId=${portId}, enabled=${value}`);
180
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
181
+ [ADVANCED_SETTINGS_KEY.SUNRISE_TIMER_ENABLED, value ? 1 : 0]
182
+ ]);
183
+ this.adapter.log.debug(`API-Antwort für Sonnenaufgang/Sonnenuntergang-Timer-Aktivierung erfolgreich`);
184
+ break;
185
+
186
+ case 'sunriseTimerMinutes':
187
+ this.adapter.log.debug(`Sende Sonnenaufgang/Sonnenuntergang-Timer-Minuten an API: deviceId=${deviceId}, portId=${portId}, minutes=${parseInt(value)}`);
188
+ await this.client.updateAdvancedSettings(deviceId, portId, portName, [
189
+ [ADVANCED_SETTINGS_KEY.SUNRISE_TIMER_DURATION, parseInt(value)]
190
+ ]);
191
+ this.adapter.log.debug(`API-Antwort für Sonnenaufgang/Sonnenuntergang-Timer-Minuten erfolgreich`);
192
+ break;
193
+
194
+ default:
195
+ this.adapter.log.warn(`Unbekannte erweiterte Port-Einstellung: ${setting}`);
196
+ }
197
+ } catch (error) {
198
+ this.adapter.log.error(`API-Fehler beim Aktualisieren der Port-Einstellung ${setting}: ${error.message}`);
199
+ if (error.response) {
200
+ this.adapter.log.error(`API-Antwort: ${JSON.stringify(error.response.data || {})}`);
201
+ }
202
+ }
203
+
204
+ // Aktualisierung der Daten auslösen, um die Zustände zu aktualisieren
205
+ await this.stateManager.refreshWithThrottle();
206
+ } catch (error) {
207
+ this.adapter.log.error(`Fehler beim Aktualisieren erweiterter Port-Einstellungen: ${error.message}`);
208
+ }
209
+ }
210
+ }
211
+
212
+ module.exports = PortSettingsHandler;
@@ -0,0 +1,313 @@
1
+ /**
2
+ * StateManager für AC Infinity Adapter
3
+ * Zentrale Klasse zum Verwalten von Zuständen für AC Infinity-Geräte
4
+ */
5
+
6
+ "use strict";
7
+
8
+ // Importiere Handler-Module
9
+ const DeviceSettingsHandler = require('./handlers/deviceSettingsHandler');
10
+ const PortSettingsHandler = require('./handlers/portSettingsHandler');
11
+ const PortModeHandler = require('./handlers/portModeHandler');
12
+
13
+ // Importiere Creator-Module
14
+ const StateCreator = require('./creators/stateCreator');
15
+ const DeviceCreator = require('./creators/deviceCreator');
16
+ const PortCreator = require('./creators/portCreator');
17
+
18
+ // Importiere Updater-Module
19
+ const DeviceUpdater = require('./updaters/deviceUpdater');
20
+ const PortUpdater = require('./updaters/portUpdater');
21
+
22
+ class StateManager {
23
+ /**
24
+ * Erstellt einen neuen StateManager
25
+ * @param {object} adapter - ioBroker-Adapter-Instanz
26
+ */
27
+ constructor(adapter) {
28
+ this.adapter = adapter;
29
+ this.deviceStates = new Map(); // Verfolgt erstellte Gerätezustände
30
+ this._refreshPending = false;
31
+ this._refreshTimer = null;
32
+ this.client = null; // API-Client-Referenz
33
+
34
+ // Initialisiere Handler
35
+ this.deviceSettingsHandler = new DeviceSettingsHandler(this);
36
+ this.portSettingsHandler = new PortSettingsHandler(this);
37
+ this.portModeHandler = new PortModeHandler(this);
38
+
39
+ // Initialisiere Creator
40
+ this.stateCreator = new StateCreator(this);
41
+ this.deviceCreator = new DeviceCreator(this);
42
+ this.portCreator = new PortCreator(this);
43
+
44
+ // Initialisiere Updater
45
+ this.deviceUpdater = new DeviceUpdater(this);
46
+ this.portUpdater = new PortUpdater(this);
47
+ }
48
+
49
+ /**
50
+ * Setzt den API-Client und gibt ihn an die Handler weiter
51
+ * @param {object} client - AC Infinity API-Client
52
+ */
53
+ setClient(client) {
54
+ this.client = client;
55
+
56
+ // Gib den Client an alle Handler weiter
57
+ this.deviceSettingsHandler.setClient(client);
58
+ this.portSettingsHandler.setClient(client);
59
+ this.portModeHandler.setClient(client);
60
+
61
+ this.adapter.log.debug("API client successfully passed to StateManager and handlers");
62
+ }
63
+
64
+ /**
65
+ * Initialisiert Zustände für alle Geräte
66
+ * @param {Array} devices - Array mit Geräteobjekten
67
+ */
68
+ async initializeDevices(devices) {
69
+ for (const device of devices) {
70
+ const deviceId = device.devId;
71
+ this.adapter.log.info(`Initializing device: ${device.devName} (ID: ${deviceId})`);
72
+
73
+ // Erstelle Geräteobjekt
74
+ await this.deviceCreator.createDeviceObject(deviceId, device.devName);
75
+
76
+ // Erstelle Controller-Info-Kanal
77
+ await this.deviceCreator.createInfoChannel(deviceId);
78
+
79
+ // Erstelle Controller-Sensor-Zustände
80
+ await this.deviceCreator.createSensorChannel(deviceId);
81
+
82
+ // Erstelle Ports
83
+ const ports = device.deviceInfo.ports;
84
+ if (Array.isArray(ports)) {
85
+ for (const port of ports) {
86
+ const portId = port.port;
87
+ await this.portCreator.createPortChannel(deviceId, portId, port.portName);
88
+ }
89
+ } else {
90
+ this.adapter.log.warn(`No ports found for device ${deviceId}`);
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Aktualisiere Gerätedaten mit neuesten Werten
97
+ * @param {object} device - Geräteobjekt
98
+ */
99
+ async updateDeviceData(device) {
100
+ const deviceId = device.devId;
101
+ this.adapter.log.debug(`Updating device data for ${deviceId}`);
102
+
103
+ // Aktualisiere Gerätedaten über den DeviceUpdater
104
+ await this.deviceUpdater.updateDeviceData(deviceId, device);
105
+
106
+ // Aktualisiere Port-Zustände
107
+ if (device.deviceInfo && Array.isArray(device.deviceInfo.ports)) {
108
+ for (const port of device.deviceInfo.ports) {
109
+ const portId = port.port;
110
+ await this.portUpdater.updatePortData(deviceId, portId, port);
111
+ }
112
+ } else {
113
+ this.adapter.log.warn(`No ports found in device data for ${deviceId}`);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Aktualisiere Port-Einstellungen
119
+ * @param {string|number} deviceId - Geräte-ID
120
+ * @param {number} portId - Port-ID
121
+ * @param {object} settings - Einstellungsobjekt
122
+ */
123
+ async updatePortSettings(deviceId, portId, settings) {
124
+ await this.portUpdater.updatePortSettings(deviceId, portId, settings);
125
+ }
126
+
127
+ /**
128
+ * Aktualisiere erweiterte Einstellungen
129
+ * @param {string|number} deviceId - Geräte-ID
130
+ * @param {number} portId - Port-ID (0 für Controller-Einstellungen)
131
+ * @param {object} settings - Einstellungsobjekt
132
+ */
133
+ async updateAdvancedSettings(deviceId, portId, settings) {
134
+ if (portId === 0) {
135
+ // Controller-Einstellungen
136
+ await this.deviceUpdater.updateAdvancedSettings(deviceId, settings);
137
+ } else {
138
+ // Port-Einstellungen
139
+ await this.portUpdater.updateAdvancedPortSettings(deviceId, portId, settings);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Verarbeitet eine vom Benutzer initiierte Zustandsänderung
145
+ * @param {string} id - Zustands-ID
146
+ * @param {object} state - Zustandsobjekt
147
+ */
148
+ async handleStateChange(id, state) {
149
+ if (!state || state.ack) {
150
+ // Ignoriere bestätigte Zustandsänderungen oder Zustände, die nicht existieren
151
+ return;
152
+ }
153
+
154
+ this.adapter.log.debug(`Processing user state change: ${id} = ${state.val}`);
155
+
156
+ try {
157
+ // Überprüfen, ob der Client gesetzt ist
158
+ if (!this.client) {
159
+ throw new Error("API client not set. Cannot process state change.");
160
+ }
161
+
162
+ // Parse ID, um Geräte-, Port- und Parameterinformationen zu erhalten
163
+ const idParts = id.split('.');
164
+
165
+ // Entferne Adaptername und Instanz vom Pfad
166
+ let path;
167
+ if (idParts[0] === this.adapter.name && idParts[1].match(/^\d+$/)) {
168
+ // ID ist vollständig (z.B. "acinfinity.0.devices.1234")
169
+ path = idParts.slice(2);
170
+ } else {
171
+ // ID ist bereits ohne Präfix (z.B. "devices.1234")
172
+ path = idParts;
173
+ }
174
+
175
+ this.adapter.log.debug(`Processing path parts: ${JSON.stringify(path)}`);
176
+
177
+ if (path[0] !== 'devices' || path.length < 4) {
178
+ this.adapter.log.warn(`Received state change with invalid path: ${id}`);
179
+ return;
180
+ }
181
+
182
+ const deviceId = path[1];
183
+
184
+ // Verarbeite Geräteebenen-Einstellungen
185
+ if (path[2] === 'settings') {
186
+ await this.deviceSettingsHandler.handleDeviceSettingsChange(deviceId, path.slice(3), state.val);
187
+ return;
188
+ }
189
+
190
+ // Verarbeite Port-Ebenen-Einstellungen
191
+ if (path[2] === 'ports' && path.length >= 5) {
192
+ const portId = parseInt(path[3]);
193
+ const subPath = path.slice(4);
194
+
195
+ // Leite die Änderung an den richtigen Handler weiter
196
+ if (subPath[0] === 'mode') {
197
+ this.adapter.log.info(`Processing mode change: Device ${deviceId}, Port ${portId}, Path ${subPath.join('.')}, Value ${state.val}`);
198
+ await this.portModeHandler.handlePortModeChange(deviceId, portId, subPath.slice(1), state.val);
199
+ } else if (subPath[0] === 'settings') {
200
+ this.adapter.log.info(`Processing settings change: Device ${deviceId}, Port ${portId}, Path ${subPath.join('.')}, Value ${state.val}`);
201
+ await this.portSettingsHandler.handlePortAdvancedSettingsChange(deviceId, portId, subPath.slice(1), state.val);
202
+ } else {
203
+ this.adapter.log.warn(`Unknown port settings category: ${subPath[0]}`);
204
+ }
205
+ return;
206
+ }
207
+
208
+ this.adapter.log.warn(`Unprocessed state change: ${id}`);
209
+ } catch (error) {
210
+ this.adapter.log.error(`Error processing state change: ${error.message}`);
211
+ if (error.stack) {
212
+ this.adapter.log.debug(`Stack trace: ${error.stack}`);
213
+ }
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Helfermethode zum Erstellen eines Zustands
219
+ * Wird vom StateCreator verwendet
220
+ * @param {string} id - Zustands-ID
221
+ * @param {string} name - Zustandsname
222
+ * @param {string} type - Zustandstyp
223
+ * @param {string} role - Zustandsrolle
224
+ * @param {string|null} unit - Zustandseinheit
225
+ * @param {boolean} write - Zustand beschreibbar
226
+ * @param {Array|null} states - Zustandswerte (für Dropdown)
227
+ * @param {object|null} common - Zusätzliche Common-Eigenschaften
228
+ */
229
+ async createState(id, name, type, role, unit = null, write = false, states = null, common = null) {
230
+ return this.stateCreator.createState(id, name, type, role, unit, write, states, common);
231
+ }
232
+
233
+ /**
234
+ * Aktualisiere einen Zustandswert
235
+ * @param {string} id - Zustands-ID
236
+ * @param {any} value - Zustandswert
237
+ */
238
+ async updateState(id, value) {
239
+ try {
240
+ // Prüfe, ob Wert null oder undefined ist, in diesem Fall nicht aktualisieren
241
+ if (value === null || value === undefined) {
242
+ return;
243
+ }
244
+
245
+ // Für Debug-Zwecke
246
+ this.adapter.log.debug(`Updating state ${id} with value ${value}`);
247
+
248
+ await this.adapter.setStateAsync(id, { val: value, ack: true });
249
+ } catch (error) {
250
+ this.adapter.log.error(`Error updating state ${id}: ${error.message}`);
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Hilfsmethode, um Änderungen im UI temporär zu aktualisieren, bevor die tatsächliche Aktualisierung stattfindet
256
+ * Dies verhindert, dass das UI zurückspringt, solange die API-Anfrage bearbeitet wird
257
+ * @param {string} id - Zustands-ID
258
+ * @param {any} value - Zustandswert
259
+ */
260
+ async updateUIState(id, value) {
261
+ try {
262
+ // Mit false ack markieren, aber in der UI anzeigen
263
+ await this.adapter.setStateAsync(id, { val: value, ack: false });
264
+ } catch (error) {
265
+ this.adapter.log.warn(`Error temporarily updating UI state ${id}: ${error.message}`);
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Verzögert die Ausführung einer Funktion
271
+ * @param {number} ms - Verzögerung in Millisekunden
272
+ * @returns {Promise} - Promise, das nach der Verzögerung aufgelöst wird
273
+ */
274
+ async delay(ms) {
275
+ return new Promise(resolve => setTimeout(resolve, ms));
276
+ }
277
+
278
+ /**
279
+ * Aktualisiert alle Daten mit Ratenbegrenzung
280
+ * Um Überflutung der API zu vermeiden
281
+ */
282
+ async refreshWithThrottle() {
283
+ if (this._refreshPending) {
284
+ this.adapter.log.debug("Update already in progress, skipping");
285
+ return;
286
+ }
287
+
288
+ // Falls noch ein ausstehender Timer existiert, diesen löschen
289
+ if (this._refreshTimer) {
290
+ clearTimeout(this._refreshTimer);
291
+ this._refreshTimer = null;
292
+ }
293
+
294
+ this._refreshPending = true;
295
+ try {
296
+ // Warte einen Moment, um die API nicht zu überlasten
297
+ await this.delay(2000);
298
+ await this.adapter.updateDeviceData();
299
+ } catch (error) {
300
+ this.adapter.log.error(`Error during delayed data update: ${error.message}`);
301
+ } finally {
302
+ // Wichtig: Flag nach Abschluss zurücksetzen, auch bei Fehlern
303
+ // Verwende einen Timer um sicherzustellen, dass genug Zeit zwischen Updates ist
304
+ this._refreshTimer = setTimeout(() => {
305
+ this._refreshPending = false;
306
+ this._refreshTimer = null;
307
+ this.adapter.log.debug("Update lock released");
308
+ }, 3000); // Wartezeit, um übermäßige Aufrufe zu verhindern
309
+ }
310
+ }
311
+ }
312
+
313
+ module.exports = StateManager;