iobroker.poolcontrol 1.3.28 → 1.3.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.
Files changed (40) hide show
  1. package/README.md +22 -12
  2. package/admin/i18n/de/translations.json +4 -1
  3. package/admin/i18n/en/translations.json +8 -2
  4. package/admin/i18n/es/translations.json +4 -1
  5. package/admin/i18n/fr/translations.json +4 -1
  6. package/admin/i18n/it/translations.json +4 -1
  7. package/admin/i18n/nl/translations.json +4 -1
  8. package/admin/i18n/pl/translations.json +4 -1
  9. package/admin/i18n/pt/translations.json +4 -1
  10. package/admin/i18n/ru/translations.json +4 -1
  11. package/admin/i18n/uk/translations.json +4 -1
  12. package/admin/i18n/zh-cn/translations.json +4 -1
  13. package/admin/jsonConfig.json +31 -1
  14. package/io-package.json +27 -27
  15. package/lib/helpers/aiForecastHelper.js +6 -4
  16. package/lib/helpers/aiHelper.js +11 -9
  17. package/lib/helpers/consumptionHelper.js +47 -5
  18. package/lib/helpers/heatHelper.js +12 -9
  19. package/lib/helpers/infoHelper.js +11 -11
  20. package/lib/helpers/poolInsightsHelper.js +727 -0
  21. package/lib/helpers/pumpHelper.js +1 -4
  22. package/lib/helpers/statisticsHelper.js +7 -3
  23. package/lib/helpers/statisticsHelperMonth.js +19 -15
  24. package/lib/helpers/statisticsHelperWeek.js +11 -5
  25. package/lib/i18n/de.json +31 -1
  26. package/lib/i18n/en.json +34 -4
  27. package/lib/i18n/es.json +31 -1
  28. package/lib/i18n/fr.json +31 -1
  29. package/lib/i18n/it.json +31 -1
  30. package/lib/i18n/nl.json +31 -1
  31. package/lib/i18n/pl.json +31 -1
  32. package/lib/i18n/pt.json +31 -1
  33. package/lib/i18n/ru.json +31 -1
  34. package/lib/i18n/uk.json +31 -1
  35. package/lib/i18n/zh-cn.json +31 -1
  36. package/lib/stateDefinitions/poolInsightsStates.js +308 -0
  37. package/lib/stateDefinitions/solarStates.js +12 -3
  38. package/lib/stateDefinitions/statusStates.js +1 -1
  39. package/main.js +20 -0
  40. package/package.json +2 -2
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "1.3.28",
4
+ "version": "1.3.30",
5
5
  "news": {
6
+ "1.3.30": {
7
+ "en": "Updated release tooling to the required minimum version. Cleaned up outdated Admin i18n keys. Replaced native timers in AI weather helpers with ioBroker adapter timers.",
8
+ "de": "Release-Werkzeuge auf die erforderliche Mindestversion aktualisiert. Veraltete Admin-i18n-Schlüssel bereinigt. Native Timer in den KI-Wetter-Helpern durch ioBroker-Adapter-Timer ersetzt.",
9
+ "ru": "Обновлены инструменты выпуска до необходимой минимальной версии. Очищены устаревшие ключи администратора i18n. Заменены встроенные таймеры в помощниках погоды AI на таймеры адаптера ioBroker.",
10
+ "pt": "Ferramentas de lançamento atualizadas para a versão mínima exigida. Limpeza de chaves Admin i18n desatualizadas. Temporizadores nativos substituídos em ajudantes meteorológicos de IA por temporizadores adaptadores ioBroker.",
11
+ "nl": "Releasetooling bijgewerkt naar de vereiste minimumversie. Verouderde Admin i18n-sleutels opgeschoond. Native timers in AI-weerhelpers vervangen door ioBroker-adaptertimers.",
12
+ "fr": "Outils de version mis à jour vers la version minimale requise. Nettoyage des clés Admin i18n obsolètes. Remplacement des minuteries natives dans les assistants météo AI par des minuteries d'adaptateur ioBroker.",
13
+ "it": "Strumenti di rilascio aggiornati alla versione minima richiesta. Ripulite le chiavi Admin i18n obsolete. Sostituiti i timer nativi negli assistenti meteorologici AI con i timer dell'adattatore ioBroker.",
14
+ "es": "Herramientas de lanzamiento actualizadas a la versión mínima requerida. Se limpiaron las claves de Admin i18n obsoletas. Se reemplazaron los temporizadores nativos en los asistentes meteorológicos de IA con temporizadores del adaptador ioBroker.",
15
+ "pl": "Zaktualizowano narzędzia wydania do wymaganej wersji minimalnej. Wyczyszczono nieaktualne klucze administratora i18n. Zastąpiono natywne liczniki czasu w pomocnikach pogodowych AI zegarami adaptera ioBroker.",
16
+ "uk": "Оновлено інструмент випуску до необхідної мінімальної версії. Очищено застарілі ключі адміністратора i18n. Вбудовані таймери в помічниках погоди штучного інтелекту замінено на таймери адаптера ioBroker.",
17
+ "zh-cn": "将发布工具更新为所需的最低版本。清理了过时的 Admin i18n 密钥。将 AI 天气助手中的本机计时器替换为 ioBroker 适配器计时器。"
18
+ },
19
+ "1.3.29": {
20
+ "en": "Added Pool Insights V1 with observations, status evaluation and runtime i18n support. Improved Pool Insights text generation and removed dependency on external summary blocks. Fixed missing initialization of season and solar warning runtime states from adapter configuration. Added admin UI notes explaining initial values versus runtime datapoint control.",
21
+ "de": "Pool Insights V1 mit Beobachtungen, Statusbewertung und Runtime-i18n hinzugefügt. Pool-Insights-Texte verbessert und die Abhängigkeit von externen Summary-Blöcken entfernt. Fehlende Initialisierung der Saison- und Solarwarnungs-States aus der Adapterkonfiguration behoben. Hinweise in der Admin-Oberfläche ergänzt, die den Unterschied zwischen Initialwerten und Runtime-Datenpunkten erläutern.",
22
+ "ru": "Добавлен Pool Insights V1 с наблюдениями, оценкой состояния и поддержкой i18n во время выполнения. Улучшено создание текста Pool Insights и удалена зависимость от внешних сводных блоков. Исправлена ​​отсутствующая инициализация состояний выполнения сезонных и солнечных предупреждений из конфигурации адаптера. Добавлены примечания к интерфейсу администратора, объясняющие начальные значения и контроль точек данных во время выполнения.",
23
+ "pt": "Adicionado Pool Insights V1 com observações, avaliação de status e suporte ao tempo de execução i18n. Geração de texto do Pool Insights aprimorada e dependência removida de blocos de resumo externos. Corrigida a falta de inicialização dos estados de tempo de execução de aviso solar e de estação na configuração do adaptador. Adicionadas notas da UI administrativa explicando os valores iniciais versus controle de ponto de dados em tempo de execução.",
24
+ "nl": "Pool Insights V1 toegevoegd met observaties, statusevaluatie en runtime i18n-ondersteuning. Verbeterde tekstgeneratie in Pool Insights en verwijderde de afhankelijkheid van externe samenvattingsblokken. Probleem opgelost waarbij de initialisatie van seizoens- en zonne-waarschuwingsruntimestatussen uit de adapterconfiguratie ontbreekt. Aantekeningen in de beheerdersinterface toegevoegd waarin initiële waarden versus runtime-datapuntcontrole worden uitgelegd.",
25
+ "fr": "Ajout de Pool Insights V1 avec observations, évaluation de l'état et prise en charge du runtime i18n. Amélioration de la génération de texte Pool Insights et suppression de la dépendance aux blocs de résumé externes. Correction de l'initialisation manquante des états d'exécution de la saison et de l'avertissement solaire dans la configuration de l'adaptateur. Ajout de notes sur l'interface utilisateur d'administration expliquant les valeurs initiales par rapport au contrôle des points de données d'exécution.",
26
+ "it": "Aggiunto Pool Insights V1 con osservazioni, valutazione dello stato e supporto i18n runtime. Migliorata la generazione del testo di Pool Insights e rimossa la dipendenza dai blocchi di riepilogo esterni. Risolto il problema con l'inizializzazione mancante degli stati di runtime dell'avviso stagionale e solare dalla configurazione dell'adattatore. Aggiunte note sull'interfaccia utente di amministrazione che spiegano i valori iniziali rispetto al controllo del punto dati di runtime.",
27
+ "es": "Se agregó Pool Insights V1 con observaciones, evaluación de estado y soporte de tiempo de ejecución i18n. Se mejoró la generación de texto de Pool Insights y se eliminó la dependencia de bloques de resumen externos. Se corrigió la falta de inicialización de los estados de tiempo de ejecución de advertencia solar y de temporada desde la configuración del adaptador. Se agregaron notas de la interfaz de usuario del administrador que explican los valores iniciales versus el control de puntos de datos en tiempo de ejecución.",
28
+ "pl": "Dodano usługę Pool Insights V1 z obserwacjami, oceną stanu i obsługą środowiska wykonawczego i18n. Ulepszone generowanie tekstu Pool Insights i usunięta zależność od zewnętrznych bloków podsumowań. Naprawiono brakującą inicjalizację stanów wykonawczych sezonu i ostrzeżenia słonecznego z konfiguracji adaptera. Dodano uwagi do interfejsu administratora wyjaśniające wartości początkowe w porównaniu z kontrolą punktów danych w czasie wykonywania.",
29
+ "uk": "Додано Pool Insights V1 із спостереженнями, оцінкою стану та підтримкою i18n під час виконання. Покращено створення тексту Pool Insights і видалено залежність від зовнішніх блоків підсумків. Виправлено відсутність ініціалізації сезону та станів попередження про сонячне світло з конфігурації адаптера. Додано примітки інтерфейсу користувача адміністратора, що пояснюють початкові значення та керування точкою даних під час виконання.",
30
+ "zh-cn": "添加了 Pool Insights V1,具有观察、状态评估和运行时 i18n 支持。改进了 Pool Insights 文本生成并消除了对外部摘要块的依赖。修复了适配器配置中缺少季节和太阳警告运行时状态初始化的问题。添加了管理 UI 注释,解释初始值与运行时数据点控制。"
31
+ },
6
32
  "1.3.28": {
7
33
  "en": "Added configurable startup power check timeout for pump monitoring (5-10 seconds). Improved compatibility with delayed power measurements from smart plugs and power meters.",
8
34
  "de": "Konfigurierbares Timeout für die Leistungsprüfung nach Pumpenstart (5-10 Sekunden) hinzugefügt. Kompatibilität mit verzögert aktualisierten Leistungswerten von Smart-Steckdosen und Leistungsmessern verbessert.",
@@ -41,32 +67,6 @@
41
67
  "pl": "Przerobiono kilka ostrzeżeń i uwag z oficjalnych kontroli ioBroker. Różne drobne ulepszenia i wewnętrzne porządki.",
42
68
  "uk": "Перероблено кілька попереджень і приміток до огляду з офіційних перевірок ioBroker. Різні невеликі покращення та внутрішні очищення.",
43
69
  "zh-cn": "重新设计了官方 ioBroker 检查中的几条警告和审查说明。各种小的改进和内部清理。"
44
- },
45
- "1.3.25": {
46
- "en": "Updated documentation and repository maintenance: improved README structure, synchronized function overviews and updated development dependencies",
47
- "de": "Dokumentation und Repository-Wartung aktualisiert: README-Struktur verbessert, Funktionsübersichten synchronisiert und Entwicklungsabhängigkeiten aktualisiert",
48
- "ru": "Обновленная документация и обслуживание репозитория: улучшенная структура README, синхронизированные обзоры функций и обновленные зависимости разработки.",
49
- "pt": "Documentação atualizada e manutenção de repositório: estrutura README aprimorada, visões gerais de funções sincronizadas e dependências de desenvolvimento atualizadas",
50
- "nl": "Bijgewerkte documentatie en repository-onderhoud: verbeterde README-structuur, gesynchroniseerde functieoverzichten en bijgewerkte ontwikkelingsafhankelijkheden",
51
- "fr": "Documentation mise à jour et maintenance du référentiel : structure README améliorée, aperçus des fonctions synchronisés et dépendances de développement mises à jour",
52
- "it": "Documentazione aggiornata e manutenzione del repository: struttura README migliorata, panoramiche delle funzioni sincronizzate e dipendenze di sviluppo aggiornate",
53
- "es": "Documentación actualizada y mantenimiento del repositorio: estructura README mejorada, descripciones generales de funciones sincronizadas y dependencias de desarrollo actualizadas",
54
- "pl": "Zaktualizowana dokumentacja i konserwacja repozytorium: ulepszona struktura README, zsynchronizowane przeglądy funkcji i zaktualizowane zależności programistyczne",
55
- "uk": "Оновлена ​​документація та обслуговування репозиторію: покращена структура README, синхронізовані огляди функцій та оновлені залежності розробки",
56
- "zh-cn": "更新的文档和存储库维护:改进的自述文件结构、同步的功能概述和更新的开发依赖项"
57
- },
58
- "1.3.24": {
59
- "en": "Updated repository and maintainer components: updated release-script dependencies, improved README/changelog structure and reviewed repository checker suggestions",
60
- "de": "Repository- und Maintainer-Komponenten aktualisiert: Release-Script-Abhängigkeiten aktualisiert, README-/Changelog-Struktur verbessert und Repository-Checker-Hinweise überarbeitet",
61
- "ru": "Обновлены компоненты репозитория и сопровождающего: обновлены зависимости сценариев выпуска, улучшена структура README/журнала изменений и рассмотрены предложения по проверке репозитория.",
62
- "pt": "Repositório atualizado e componentes do mantenedor: dependências de script de lançamento atualizadas, estrutura README/changelog aprimorada e sugestões revisadas do verificador de repositório",
63
- "nl": "Bijgewerkte repository- en onderhoudercomponenten: bijgewerkte release-scriptafhankelijkheden, verbeterde README/changelog-structuur en herziene suggesties voor repositorycontrole",
64
- "fr": "Composants du référentiel et du responsable mis à jour : dépendances de script de version mises à jour, structure README/changelog améliorée et suggestions révisées du vérificateur de référentiel",
65
- "it": "Componenti del repository e del manutentore aggiornati: dipendenze aggiornate degli script di rilascio, struttura README/log delle modifiche migliorata e suggerimenti rivisti per il controllo del repository",
66
- "es": "Componentes actualizados del repositorio y del mantenedor: dependencias actualizadas del script de lanzamiento, estructura README/registro de cambios mejorada y sugerencias revisadas del verificador del repositorio",
67
- "pl": "Zaktualizowane komponenty repozytorium i opiekuna: zaktualizowane zależności skryptu wydania, ulepszona struktura README/dziennika zmian i sprawdzone sugestie dotyczące sprawdzania repozytorium",
68
- "uk": "Оновлений репозиторій і компоненти супроводжувача: оновлені залежності сценарію випуску, покращена структура README/журналу змін і переглянуті пропозиції перевірки сховища",
69
- "zh-cn": "更新了存储库和维护者组件:更新了发布脚本依赖项,改进了自述文件/变更日志结构并审查了存储库检查器建议"
70
70
  }
71
71
  },
72
72
  "titleLang": {
@@ -41,7 +41,9 @@ const aiForecastHelper = {
41
41
  // ----------------------------------------------------------
42
42
  // NEU: Delay, damit ioBroker alle States laden kann
43
43
  // ----------------------------------------------------------
44
- await new Promise(res => setTimeout(res, 1500));
44
+ await new Promise(resolve => {
45
+ this.adapter.setTimeout(resolve, 1500);
46
+ });
45
47
 
46
48
  // ----------------------------------------------------------
47
49
  // NEU: Sofortige Ausführung beim Adapterstart (wenn aktiviert)
@@ -64,7 +66,7 @@ const aiForecastHelper = {
64
66
  */
65
67
  cleanup() {
66
68
  if (this.timer) {
67
- clearInterval(this.timer);
69
+ this.adapter.clearInterval(this.timer);
68
70
  this.timer = null;
69
71
  }
70
72
  this.adapter && this.adapter.log.debug('[aiForecastHelper] cleanup finished');
@@ -113,7 +115,7 @@ const aiForecastHelper = {
113
115
  async _refreshTimer() {
114
116
  // alten Timer stoppen
115
117
  if (this.timer) {
116
- clearInterval(this.timer);
118
+ this.adapter.clearInterval(this.timer);
117
119
  this.timer = null;
118
120
  }
119
121
 
@@ -132,7 +134,7 @@ const aiForecastHelper = {
132
134
  );
133
135
 
134
136
  // minütlicher Check
135
- this.timer = setInterval(async () => {
137
+ this.timer = this.adapter.setInterval(async () => {
136
138
  const now = new Date();
137
139
  if (now.getHours() === time.hour && now.getMinutes() === time.minute) {
138
140
  try {
@@ -123,7 +123,9 @@ const aiHelper = {
123
123
  // ----------------------------------------------------------
124
124
  // NEU: Delay, damit ioBroker alle States laden kann
125
125
  // ----------------------------------------------------------
126
- await new Promise(res => setTimeout(res, 1500));
126
+ await new Promise(resolve => {
127
+ this.adapter.setTimeout(resolve, 1500);
128
+ });
127
129
 
128
130
  // NEU: Wenn Uhrzeit heute noch in der Zukunft liegt → sofort ausführen
129
131
  try {
@@ -183,7 +185,7 @@ const aiHelper = {
183
185
  */
184
186
  _clearTimers() {
185
187
  for (const t of this.timers) {
186
- clearInterval(t);
188
+ this.adapter.clearInterval(t);
187
189
  }
188
190
  this.timers = [];
189
191
  },
@@ -257,7 +259,7 @@ const aiHelper = {
257
259
  //--------------------------------------------------------
258
260
  this.adapter.log.debug('[aiHelper] setting hourly weather update timer');
259
261
 
260
- const hourlyTimer = setInterval(
262
+ const hourlyTimer = this.adapter.setInterval(
261
263
  async () => {
262
264
  try {
263
265
  const geo = await this._loadGeoLocation();
@@ -303,7 +305,7 @@ const aiHelper = {
303
305
  */
304
306
  _createDailyTimer(timeObj, callback) {
305
307
  const { hour, minute } = timeObj;
306
- const timer = setInterval(async () => {
308
+ const timer = this.adapter.setInterval(async () => {
307
309
  const now = new Date();
308
310
 
309
311
  // --- FIX: Nachholen nur in den ersten 3 Minuten nach Adapterstart ---
@@ -517,7 +519,7 @@ const aiHelper = {
517
519
  *
518
520
  * @param {number} lat
519
521
  * @param {number} lon
520
- * @returns {Promise<any|null>}
522
+ * @returns {Promise<object|null>}
521
523
  */
522
524
  async _fetchWeather(lat, lon) {
523
525
  const url =
@@ -572,7 +574,7 @@ const aiHelper = {
572
574
  /**
573
575
  * Erzeugt einen gut lesbaren Wetterhinweis-Text.
574
576
  *
575
- * @param {any} weather
577
+ * @param {object|null} weather
576
578
  * @returns {string}
577
579
  */
578
580
  _buildWeatherAdviceText(weather) {
@@ -601,7 +603,7 @@ const aiHelper = {
601
603
  /**
602
604
  * Erzeugt die Tageszusammenfassung.
603
605
  *
604
- * @param {{weather:any,seasonActive:boolean,pumpOn:boolean,pumpMode:string,surfaceTemp:number|null}} ctx
606
+ * @param {{weather: object|null, seasonActive: boolean, pumpOn: boolean, pumpMode: string, surfaceTemp: number|null}} ctx
605
607
  * @returns {string}
606
608
  */
607
609
  _buildDailySummaryText(ctx) {
@@ -661,7 +663,7 @@ const aiHelper = {
661
663
  /**
662
664
  * Erzeugt tägliche Pool-Tipps abhängig von Wetter & Saison.
663
665
  *
664
- * @param {any} weather
666
+ * @param {object|null} weather
665
667
  * @param {boolean} seasonActive
666
668
  * @returns {string}
667
669
  */
@@ -795,7 +797,7 @@ const aiHelper = {
795
797
  /**
796
798
  * Erzeugt Wochenend-Zusammenfassung (Samstag/Sonntag).
797
799
  *
798
- * @param {any} weather
800
+ * @param {object|null} weather
799
801
  * @param {boolean} seasonActive
800
802
  * @param {number} weekday JS-Tag (0=So..6=Sa)
801
803
  * @returns {string}
@@ -15,6 +15,9 @@ const consumptionHelper = {
15
15
  price: 0,
16
16
  baselines: {},
17
17
  resetTimer: null,
18
+ weeklyResetTimer: null,
19
+ monthlyResetTimer: null,
20
+ yearlyResetTimer: null,
18
21
 
19
22
  lastKnownPrice: 0,
20
23
  baseTotalKwh: 0,
@@ -252,7 +255,12 @@ const consumptionHelper = {
252
255
  nextMidnight.setHours(24, 0, 0, 0);
253
256
  const msUntilMidnight = nextMidnight - now;
254
257
 
255
- this.resetTimer = setTimeout(async () => {
258
+ if (this.resetTimer) {
259
+ this.adapter.clearTimeout(this.resetTimer);
260
+ this.resetTimer = null;
261
+ }
262
+
263
+ this.resetTimer = this.adapter.setTimeout(async () => {
256
264
  try {
257
265
  this.adapter.log.info('[consumptionHelper] daily counter reset (midnight)');
258
266
  await this.adapter.setStateAsync('consumption.day_kwh', { val: 0, ack: true });
@@ -261,6 +269,7 @@ const consumptionHelper = {
261
269
  } catch (err) {
262
270
  this.adapter.log.warn(`[consumptionHelper] error during midnight reset: ${err.message}`);
263
271
  }
272
+ this.resetTimer = null;
264
273
  this._scheduleDailyReset(); // Timer erneut setzen
265
274
  }, msUntilMidnight);
266
275
  },
@@ -280,7 +289,12 @@ const consumptionHelper = {
280
289
 
281
290
  const delay = next - now;
282
291
 
283
- setTimeout(async () => {
292
+ if (this.weeklyResetTimer) {
293
+ this.adapter.clearTimeout(this.weeklyResetTimer);
294
+ this.weeklyResetTimer = null;
295
+ }
296
+
297
+ this.weeklyResetTimer = this.adapter.setTimeout(async () => {
284
298
  try {
285
299
  const nowCheck = new Date();
286
300
 
@@ -296,6 +310,7 @@ const consumptionHelper = {
296
310
  }
297
311
 
298
312
  // Morgen wieder planen
313
+ this.weeklyResetTimer = null;
299
314
  this._scheduleWeeklyReset();
300
315
  }, delay);
301
316
  },
@@ -315,7 +330,12 @@ const consumptionHelper = {
315
330
 
316
331
  const delay = next - now;
317
332
 
318
- setTimeout(async () => {
333
+ if (this.monthlyResetTimer) {
334
+ this.adapter.clearTimeout(this.monthlyResetTimer);
335
+ this.monthlyResetTimer = null;
336
+ }
337
+
338
+ this.monthlyResetTimer = this.adapter.setTimeout(async () => {
319
339
  try {
320
340
  const nowCheck = new Date();
321
341
 
@@ -331,6 +351,7 @@ const consumptionHelper = {
331
351
  }
332
352
 
333
353
  // Morgen wieder planen
354
+ this.monthlyResetTimer = null;
334
355
  this._scheduleMonthlyReset();
335
356
  }, delay);
336
357
  },
@@ -350,7 +371,12 @@ const consumptionHelper = {
350
371
 
351
372
  const delay = next - now;
352
373
 
353
- setTimeout(async () => {
374
+ if (this.yearlyResetTimer) {
375
+ this.adapter.clearTimeout(this.yearlyResetTimer);
376
+ this.yearlyResetTimer = null;
377
+ }
378
+
379
+ this.yearlyResetTimer = this.adapter.setTimeout(async () => {
354
380
  try {
355
381
  const nowCheck = new Date();
356
382
 
@@ -366,15 +392,31 @@ const consumptionHelper = {
366
392
  }
367
393
 
368
394
  // Morgen wieder prüfen
395
+ this.yearlyResetTimer = null;
369
396
  this._scheduleYearlyReset();
370
397
  }, delay);
371
398
  },
372
399
 
373
400
  cleanup() {
374
401
  if (this.resetTimer) {
375
- clearTimeout(this.resetTimer);
402
+ this.adapter.clearTimeout(this.resetTimer);
376
403
  this.resetTimer = null;
377
404
  }
405
+
406
+ if (this.weeklyResetTimer) {
407
+ this.adapter.clearTimeout(this.weeklyResetTimer);
408
+ this.weeklyResetTimer = null;
409
+ }
410
+
411
+ if (this.monthlyResetTimer) {
412
+ this.adapter.clearTimeout(this.monthlyResetTimer);
413
+ this.monthlyResetTimer = null;
414
+ }
415
+
416
+ if (this.yearlyResetTimer) {
417
+ this.adapter.clearTimeout(this.yearlyResetTimer);
418
+ this.yearlyResetTimer = null;
419
+ }
378
420
  },
379
421
  };
380
422
 
@@ -246,7 +246,7 @@ const heatHelper = {
246
246
 
247
247
  const holdMs = Math.round(prerunMin * 60 * 1000);
248
248
 
249
- this._prerunTimer = setTimeout(async () => {
249
+ this._prerunTimer = this.adapter.setTimeout(async () => {
250
250
  this._prerunTimer = null;
251
251
 
252
252
  await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
@@ -261,9 +261,8 @@ const heatHelper = {
261
261
 
262
262
  this._desiredHeat = true;
263
263
 
264
- // Nachlauf ggf. abbrechen
265
264
  if (this._afterrunTimer) {
266
- clearTimeout(this._afterrunTimer);
265
+ this.adapter.clearTimeout(this._afterrunTimer);
267
266
  this._afterrunTimer = null;
268
267
  }
269
268
 
@@ -323,7 +322,7 @@ const heatHelper = {
323
322
  async _applyBlockedState(mode, reason, afterrunMin) {
324
323
  // NEU: laufenden Prerun abbrechen
325
324
  if (this._prerunTimer) {
326
- clearTimeout(this._prerunTimer);
325
+ this.adapter.clearTimeout(this._prerunTimer);
327
326
  this._prerunTimer = null;
328
327
  await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
329
328
  }
@@ -347,7 +346,7 @@ const heatHelper = {
347
346
  async _applyOffState(mode, reason, afterrunMin) {
348
347
  // NEU: laufenden Prerun abbrechen
349
348
  if (this._prerunTimer) {
350
- clearTimeout(this._prerunTimer);
349
+ this.adapter.clearTimeout(this._prerunTimer);
351
350
  this._prerunTimer = null;
352
351
  await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
353
352
  }
@@ -401,7 +400,7 @@ const heatHelper = {
401
400
 
402
401
  // Timer neu starten
403
402
  if (this._afterrunTimer) {
404
- clearTimeout(this._afterrunTimer);
403
+ this.adapter.clearTimeout(this._afterrunTimer);
405
404
  this._afterrunTimer = null;
406
405
  }
407
406
 
@@ -410,12 +409,15 @@ const heatHelper = {
410
409
  const holdMs = Math.round(afterrunMin * 60 * 1000);
411
410
  this.adapter.log.debug(`[heatHelper] Pump after-run started: ${afterrunMin} min (${reason})`);
412
411
 
413
- this._afterrunTimer = setTimeout(async () => {
412
+ this._afterrunTimer = this.adapter.setTimeout(async () => {
413
+ this._afterrunTimer = null;
414
+
414
415
  // Wenn inzwischen wieder Heizbedarf aktiv ist -> Nachlauf abbrechen
415
416
  if (this._desiredHeat === true) {
416
417
  this.adapter.log.debug('[heatHelper] After-run cancelled - heating is active again.');
417
418
  return;
418
419
  }
420
+
419
421
  await this._stopPumpNow('afterrun_done');
420
422
  }, holdMs);
421
423
  },
@@ -497,11 +499,12 @@ const heatHelper = {
497
499
 
498
500
  cleanup() {
499
501
  if (this._afterrunTimer) {
500
- clearTimeout(this._afterrunTimer);
502
+ this.adapter.clearTimeout(this._afterrunTimer);
501
503
  this._afterrunTimer = null;
502
504
  }
505
+
503
506
  if (this._prerunTimer) {
504
- clearTimeout(this._prerunTimer);
507
+ this.adapter.clearTimeout(this._prerunTimer);
505
508
  this._prerunTimer = null;
506
509
  }
507
510
 
@@ -121,6 +121,11 @@ const infoHelper = {
121
121
  * Startet den täglichen Update-Intervall (Update 00:01 Uhr)
122
122
  */
123
123
  _startDailyTimer() {
124
+ if (this.dailyTimer) {
125
+ this.adapter.clearTimeout(this.dailyTimer);
126
+ this.dailyTimer = null;
127
+ }
128
+
124
129
  // nächsten Trigger für morgen 00:01 berechnen
125
130
  const now = new Date();
126
131
  const next = new Date(now);
@@ -130,17 +135,13 @@ const infoHelper = {
130
135
 
131
136
  const delay = next.getTime() - now.getTime();
132
137
 
133
- // einmaliger Timer bis 00:01
134
- this.dailyTimer = setTimeout(() => {
138
+ this.dailyTimer = this.adapter.setTimeout(() => {
139
+ this.dailyTimer = null;
140
+
135
141
  this._updateDeveloperGreeting();
136
142
 
137
- // danach täglich um 24h
138
- this.dailyTimer = setInterval(
139
- () => {
140
- this._updateDeveloperGreeting();
141
- },
142
- 24 * 60 * 60 * 1000,
143
- );
143
+ // Danach neu planen, damit kein dauerhaftes setInterval nötig ist.
144
+ this._startDailyTimer();
144
145
  }, delay);
145
146
  },
146
147
 
@@ -149,8 +150,7 @@ const infoHelper = {
149
150
  */
150
151
  cleanup() {
151
152
  if (this.dailyTimer) {
152
- clearTimeout(this.dailyTimer);
153
- clearInterval(this.dailyTimer);
153
+ this.adapter.clearTimeout(this.dailyTimer);
154
154
  this.dailyTimer = null;
155
155
  }
156
156
  },