iobroker.poolcontrol 0.0.8 → 0.0.10

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/LICENSE CHANGED
@@ -1,22 +1,21 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 DasBo1975 <dasbo1975@outlook.de>
3
+ Copyright (c) 2025 DasBo1975
4
4
 
5
- Hiermit wird jedem, der eine Kopie dieser Software und der zugehörigen
6
- Dokumentationsdateien (die "Software") erhält, die Erlaubnis erteilt,
7
- die Software uneingeschränkt zu nutzen, einschließlich, aber nicht
8
- beschränkt auf das Recht, die Software zu verwenden, zu kopieren,
9
- zu ändern, zu verbinden, zu veröffentlichen, zu verbreiten,
10
- Unterlizenzen zu erteilen und/oder Kopien der Software zu verkaufen,
11
- sowie Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten,
12
- unter der Bedingung, dass der oben genannte Urheberrechtshinweis und dieser
13
- Erlaubnishinweis in allen Kopien oder wesentlichen Teilen der Software
14
- beibehalten werden.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
15
11
 
16
- DIE SOFTWARE WIRD "WIE BESEHEN" OHNE JEDE GARANTIE, WEDER AUSDRÜCKLICH NOCH
17
- STILLSCHWEIGEND, EINSCHLIESSLICH, ABER NICHT BEGRENZT AUF DIE GARANTIEN DER
18
- MARKTGÄNGIGKEIT, EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG.
19
- IN KEINEM FALL HAFTEN DIE AUTOREN ODER COPYRIGHT-INHABER FÜR ANSPRÜCHE, SCHÄDEN
20
- ODER SONSTIGE HAFTUNG, OB IN EINER KLAGE ODER EINER ANDEREN HAFTUNGSGRUNDLAGE,
21
- DIE AUS ODER IM ZUSAMMENHANG MIT DER SOFTWARE ODER DER NUTZUNG DER SOFTWARE
22
- ODER ANDEREN VEREINBARUNGEN ENTSTEHT.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ![Test and Release](https://github.com/DasBo1975/iobroker.poolcontrol/actions/workflows/test-and-release.yml/badge.svg)
4
4
  ![npm](https://img.shields.io/npm/v/iobroker.poolcontrol?color=blue)
5
+ ![Downloads](https://img.shields.io/npm/dm/iobroker.poolcontrol)
6
+ ![Installs](https://iobroker.live/badges/poolcontrol-installed.svg)
7
+ ![Stable](https://iobroker.live/badges/poolcontrol-stable.svg)
8
+ [![License](https://img.shields.io/github/license/DasBo1975/ioBroker.poolcontrol?cacheSeconds=3600)](https://github.com/DasBo1975/ioBroker.poolcontrol/blob/main/LICENSE)
5
9
 
6
10
  Der Adapter **ioBroker.poolcontrol** dient zur Steuerung und Überwachung von Poolanlagen.
7
11
  Er ermöglicht die Automatisierung von Pumpen, Temperatur- und Solarsteuerung sowie Verbrauchsauswertung.
@@ -90,6 +94,30 @@ Funktionen können sich ändern, bitte regelmäßig den Changelog beachten.
90
94
  ## Changelog
91
95
  Auszug, vollständige Liste siehe `io-package.json`:
92
96
 
97
+ ### 0.0.10
98
+
99
+ Statusübersicht
100
+ Ab Version 0.0.10 gibt es einen eigenen Bereich `status.*` mit folgenden Datenpunkten:
101
+
102
+ - **status.summary** → Textübersicht (Pumpe, Modus, Temperaturen, Laufzeit, Umwälzung)
103
+ - **status.overview_json** → Übersicht als JSON (maschinenlesbar)
104
+ - **status.last_summary_update** → Zeitpunkt der letzten Aktualisierung
105
+ - **status.pump_last_start** → Letzter Pumpenstart (Zeitstempel)
106
+ - **status.pump_last_stop** → Letztes Pumpenende (Zeitstempel)
107
+ - **status.pump_was_on_today** → Boolean, ob die Pumpe heute lief
108
+ - **status.pump_today_count** → Anzahl der Starts heute (Reset um Mitternacht)
109
+ - **status.system_ok** → Boolean, ob das System fehlerfrei läuft
110
+ - **status.system_warning** → Boolean, wenn eine Warnung aktiv ist
111
+ - **status.system_warning_text** → Beschreibung der aktiven Warnung
112
+ - **status.season_active** → Anzeige, ob die Poolsaison aktiv ist
113
+
114
+ Diese Datenpunkte sind besonders für **VIS/vis2, Alexa- oder Telegram-Ausgaben** gedacht, da sie eine schnelle Übersicht über den aktuellen Poolstatus bieten.
115
+
116
+
117
+ ### 0.0.9
118
+ - Laufzeit-, Umwälz-, Verbrauch-/Kosten- und Temperatur-Min/Max-States sind jetzt persistent
119
+ (Werte bleiben nach Adapter-Neustart oder Stromausfall erhalten)
120
+
93
121
  ### 0.0.8
94
122
  - Hilfetab in der Instanzkonfiguration hinzugefügt (mit Link zur GitHub-Dokumentation)
95
123
 
@@ -128,6 +156,7 @@ Der Nutzer ist für die **sichere Installation und den Betrieb seiner Hardware**
128
156
 
129
157
  ---
130
158
 
131
- ## LICENSE
132
- [MIT](./LICENSE) License
133
- Copyright (c) 2025 DasBo1975
159
+ ## License
160
+ Copyright (c) 2025 DasBo1975 <dasbo1975@outlook.de>
161
+
162
+ MIT License
@@ -137,7 +137,12 @@
137
137
  "pump_mode_hint": {
138
138
  "type": "staticText",
139
139
  "text": "Pumpenmodus (Automatik/Manuell/Aus/Zeit) kann über den Datenpunkt 'pump.mode' gesteuert werden.",
140
- "newLine": true
140
+ "newLine": true,
141
+ "xs": 12,
142
+ "sm": 12,
143
+ "md": 12,
144
+ "lg": 12,
145
+ "xl": 12
141
146
  },
142
147
  "divider10": {
143
148
  "type": "divider",
@@ -157,7 +162,12 @@
157
162
  "manual_safety_enabled_hint": {
158
163
  "type": "staticText",
159
164
  "text": "Wenn aktiviert, werden die Sicherheitsfunktionen wie Frostschutz und Überhitzungsschutz (Solar) weiterhin ausgeführt.",
160
- "newLine": true
165
+ "newLine": true,
166
+ "xs": 12,
167
+ "sm": 12,
168
+ "md": 12,
169
+ "lg": 12,
170
+ "xl": 12
161
171
  }
162
172
  }
163
173
  },
@@ -390,7 +400,12 @@
390
400
  "solar_collector_warn_hint": {
391
401
  "type": "staticText",
392
402
  "text": "Hinweis: Die Warnung wird automatisch zurückgesetzt, sobald die Temperatur 10 % unter die eingestellte Schwelle fällt.",
393
- "newLine": true
403
+ "newLine": true,
404
+ "xs": 12,
405
+ "sm": 12,
406
+ "md": 12,
407
+ "lg": 12,
408
+ "xl": 12
394
409
  }
395
410
  }
396
411
  },
@@ -893,7 +908,12 @@
893
908
  "consumption_hint": {
894
909
  "type": "staticText",
895
910
  "text": "Hinweis: Für die Verbrauchsberechnung wird ein externer kWh-Zähler benötigt (z. B. Messsteckdose).",
896
- "newLine": true
911
+ "newLine": true,
912
+ "xs": 12,
913
+ "sm": 12,
914
+ "md": 12,
915
+ "lg": 12,
916
+ "xl": 12
897
917
  }
898
918
  }
899
919
  },
@@ -909,11 +929,21 @@
909
929
  "type": "staticLink",
910
930
  "label": "Öffne die ausführliche Dokumentation auf GitHub",
911
931
  "href": "https://github.com/DasBo1975/iobroker.poolcontrol/blob/main/admin/help.md",
912
- "newLine": true
932
+ "newLine": true,
933
+ "xs": 12,
934
+ "sm": 12,
935
+ "md": 12,
936
+ "lg": 12,
937
+ "xl": 12
913
938
  },
914
939
  "helpText": {
915
940
  "type": "staticText",
916
- "text": "Hier finden Sie die vollständige Dokumentation und Hinweise zu allen Einstellungen. Weitere Hinweise zu künftigen Versionen folgen."
941
+ "text": "Hier finden Sie die vollständige Dokumentation und Hinweise zu allen Einstellungen. Weitere Hinweise zu künftigen Versionen folgen.",
942
+ "xs": 12,
943
+ "sm": 12,
944
+ "md": 12,
945
+ "lg": 12,
946
+ "xl": 12
917
947
  }
918
948
  }
919
949
  }
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "0.0.8",
4
+ "version": "0.0.10",
5
5
  "news": {
6
+ "0.0.10": {
7
+ "en": "Added extended status overview with pump statistics, system flags and JSON summary",
8
+ "de": "Erweiterte Statusübersicht mit Pumpenstatistiken, Systemanzeigen und JSON-Zusammenfassung hinzugefügt",
9
+ "ru": "Добавлен расширенный обзор состояния с насосной статистикой, системными флагами и JSON-резюме",
10
+ "pt": "Adicionada visão geral de status estendida com estatísticas da bomba, sinalizadores do sistema e resumo em JSON",
11
+ "nl": "Uitgebreide statusoverzicht toegevoegd met pompstatistieken, systeemindicatoren en JSON-samenvatting",
12
+ "fr": "Aperçu du statut étendu ajouté avec statistiques de la pompe, indicateurs système et résumé JSON",
13
+ "it": "Aggiunta panoramica dello stato estesa con statistiche della pompa, indicatori di sistema e riepilogo JSON",
14
+ "es": "Añadida vista general de estado extendida con estadísticas de la bomba, indicadores del sistema y resumen en JSON",
15
+ "pl": "Dodano rozszerzony przegląd statusu ze statystykami pompy, flagami systemowymi i podsumowaniem JSON",
16
+ "uk": "Додано розширений огляд статусу зі статистикою насоса, системними прапорцями та зведенням JSON",
17
+ "zh-cn": "新增扩展状态概览,包括泵统计、系统标志和 JSON 摘要"
18
+ },
19
+ "0.0.9": {
20
+ "en": "Made runtime, circulation, consumption/costs and temperature min/max states persistent across restarts",
21
+ "de": "Laufzeit-, Umwälz-, Verbrauch-/Kosten- und Temperatur-Min/Max-States bleiben jetzt über Neustarts erhalten",
22
+ "ru": "Состояния времени работы, циркуляции, потребления/стоимости и мин/макс температуры теперь сохраняются при перезапуске",
23
+ "pt": "Estados de tempo de execução, circulação, consumo/custos e temperatura min/máx agora persistem após reinicializações",
24
+ "nl": "Runtime-, circulatie-, verbruiks-/kosten- en temperatuur min/max-states blijven nu behouden bij herstart",
25
+ "fr": "Les états de durée, de circulation, de consommation/coûts et de température min/max persistent désormais après redémarrage",
26
+ "it": "Gli stati di runtime, circolazione, consumo/costi e temperatura min/max ora persistono ai riavvii",
27
+ "es": "Los estados de tiempo de ejecución, circulación, consumo/costos y temperatura min/máx ahora persisten tras reinicios",
28
+ "pl": "Stany czasu pracy, cyrkulacji, zużycia/kosztów i temp. min/max są teraz zachowane po restartach",
29
+ "uk": "Стан часу роботи, циркуляції, споживання/вартості та мін/макс температури тепер зберігаються після перезапусків",
30
+ "zh-cn": "运行时间、循环、消耗/成本和温度最小/最大状态现在在重启后保持"
31
+ },
6
32
  "0.0.8": {
7
33
  "en": "Added Help tab in instance configuration with link to GitHub documentation",
8
34
  "de": "Hilfetab in der Instanzkonfiguration hinzugefügt mit Link zur GitHub-Dokumentation",
@@ -16,97 +42,6 @@
16
42
  "uk": "Додано вкладку довідки в конфігурацію екземпляра з посиланням на документацію GitHub",
17
43
  "zh-cn": "在实例配置中添加了帮助选项卡,并链接到 документацию GitHub"
18
44
  }
19
- "0.0.7": {
20
- "en": "Added help file (help.md) and first README version",
21
- "de": "Hilfedatei (help.md) und erste README-Version hinzugefügt",
22
- "ru": "Добавлен файл справки (help.md) и первая версия README",
23
- "pt": "Adicionado arquivo de ajuda (help.md) e primeira versão do README",
24
- "nl": "Helpbestand (help.md) en eerste README-versie toegevoegd",
25
- "fr": "Ajout du fichier d'aide (help.md) et première version du README",
26
- "it": "Aggiunto file di aiuto (help.md) e prima versione di README",
27
- "es": "Se agregó archivo de ayuda (help.md) y primera versión de README",
28
- "pl": "Dodano plik pomocy (help.md) i pierwszą wersję README",
29
- "uk": "Додано файл довідки (help.md) та першу версію README",
30
- "zh-cn": "添加了帮助文件 (help.md) 和第一个 README 版本"
31
- },
32
- "0.0.6": {
33
- "en": "Added consumption & cost calculation with external kWh meter",
34
- "de": "Verbrauchs- und Kostenberechnung mit externem kWh-Zähler hinzugefügt",
35
- "ru": "Добавлен расчет потребления и затрат с внешним счетчиком кВт·ч",
36
- "pt": "Adicionado cálculo de consumo e custo com medidor externo de kWh",
37
- "nl": "Verbruik- en kostenberekening toegevoegd met externe kWh-meter",
38
- "fr": "Ajout du calcul de consommation et de coût avec compteur kWh externe",
39
- "it": "Aggiunto calcolo di consumo e costi con contatore kWh esterno",
40
- "es": "Se agregó cálculo de consumo y costos con medidor externo de kWh",
41
- "pl": "Dodano obliczanie zużycia i kosztów z zewnętrznym licznikiem kWh",
42
- "uk": "Додано розрахунок споживання та витрат із зовнішнім лічильником кВт·год",
43
- "zh-cn": "新增使用外部千瓦时电表的消耗和成本计算"
44
- },
45
- "0.0.5": {
46
- "en": "Added speech output via Alexa and Telegram",
47
- "de": "Sprachausgaben über Alexa und Telegram hinzugefügt",
48
- "ru": "Добавлен голосовой вывод через Alexa и Telegram",
49
- "pt": "Adicionada saída de voz via Alexa e Telegram",
50
- "nl": "Spraakuitvoer toegevoegd via Alexa en Telegram",
51
- "fr": "Ajout de la sortie vocale via Alexa et Telegram",
52
- "it": "Aggiunta uscita vocale tramite Alexa e Telegram",
53
- "es": "Se agregó salida de voz a través de Alexa y Telegram",
54
- "pl": "Dodano wyjście głosowe przez Alexa i Telegram",
55
- "uk": "Додано голосовий вивід через Alexa та Telegram",
56
- "zh-cn": "新增通过 Alexa 和 Telegram 的语音输出"
57
- },
58
- "0.0.4": {
59
- "en": "Added runtime & circulation logic including new datapoint 'circulation.daily_required'",
60
- "de": "Laufzeit- und Umwälzlogik hinzugefügt, einschließlich neuem Datenpunkt 'circulation.daily_required'",
61
- "ru": "Добавлена логика времени работы и циркуляции, включая новую точку данных 'circulation.daily_required'",
62
- "pt": "Adicionada lógica de tempo de execução e circulação, incluindo novo datapoint 'circulation.daily_required'",
63
- "nl": "Runtime- en circulatielogica toegevoegd, inclusief nieuw datapoint 'circulation.daily_required'",
64
- "fr": "Ajout de la logique de temps d'exécution et de circulation, y compris le nouveau point de données 'circulation.daily_required'",
65
- "it": "Aggiunta logica di runtime e circolazione, incluso nuovo datapoint 'circulation.daily_required'",
66
- "es": "Se agregó lógica de tiempo de ejecución y circulación, incluido nuevo datapoint 'circulation.daily_required'",
67
- "pl": "Dodano logikę czasu pracy i cyrkulacji, w tym nowy punkt danych 'circulation.daily_required'",
68
- "uk": "Додано логіку часу роботи та циркуляції, включаючи нову точку даних 'circulation.daily_required'",
69
- "zh-cn": "新增运行时间和循环逻辑,包括新数据点 'circulation.daily_required'"
70
- },
71
- "0.0.3": {
72
- "en": "Added time control with up to 3 configurable time windows",
73
- "de": "Zeitsteuerung mit bis zu 3 konfigurierbaren Zeitfenstern hinzugefügt",
74
- "ru": "Добавлено управление временем с до 3 настраиваемыми временными окнами",
75
- "pt": "Adicionado controle de tempo com até 3 janelas de tempo configuráveis",
76
- "nl": "Tijdregeling toegevoegd met maximaal 3 configureerbare tijdvensters",
77
- "fr": "Ajout du contrôle du temps avec jusqu'à 3 fenêtres de temps configurables",
78
- "it": "Aggiunto controllo del tempo con fino a 3 finestre temporali configurabili",
79
- "es": "Se agregó control de tiempo con hasta 3 ventanas de tiempo configurables",
80
- "pl": "Dodano kontrolę czasu z maksymalnie 3 konfigurowalnymi oknami czasowymi",
81
- "uk": "Додано керування часом з до 3 налаштовуваними часовими вікнами",
82
- "zh-cn": "新增时间控制,最多可配置 3 个时间窗口"
83
- },
84
- "0.0.2": {
85
- "en": "Extended pump logic with error detection and safety functions",
86
- "de": "Pumpenlogik erweitert mit Fehlererkennung und Sicherheitsfunktionen",
87
- "ru": "Расширена логика насоса с обнаружением ошибок и функциями безопасности",
88
- "pt": "Lógica da bomba estendida com detecção de erros e funções de segurança",
89
- "nl": "Pomplogica uitgebreid met foutdetectie en veiligheidsfuncties",
90
- "fr": "Logique de pompe étendue avec détection d'erreurs et fonctions de sécurité",
91
- "it": "Logica della pompa estesa con rilevamento errori e funzioni di sicurezza",
92
- "es": "Lógica de la bomba ampliada con detección de errores y funciones de seguridad",
93
- "pl": "Rozszerzona logika pompy z wykrywaniem błędów i funkcjami bezpieczeństwa",
94
- "uk": "Розширена логіка насоса з виявленням помилок та функціями безпеки",
95
- "zh-cn": "扩展泵逻辑,具有错误检测和安全功能"
96
- },
97
- "0.0.1": {
98
- "en": "initial release",
99
- "de": "Erstveröffentlichung",
100
- "ru": "Начальная версия",
101
- "pt": "lançamento inicial",
102
- "nl": "Eerste uitgave",
103
- "fr": "Première version",
104
- "it": "Versione iniziale",
105
- "es": "Versión inicial",
106
- "pl": "Pierwsze wydanie",
107
- "uk": "Початкова версія",
108
- "zh-cn": "首次出版"
109
- }
110
45
  },
111
46
  "titleLang": {
112
47
  "en": "PoolControl",
@@ -168,9 +103,9 @@
168
103
  "js-controller": ">=6.0.11"
169
104
  }
170
105
  ],
171
- "globalDependencies": [
106
+ "globalDependencies": [
172
107
  {
173
- "admin": ">=7.0.23"
108
+ "admin": ">=7.6.17"
174
109
  }
175
110
  ]
176
111
  },
@@ -179,11 +114,6 @@
179
114
  "option2": "42"
180
115
  },
181
116
  "objects": [],
182
- "instanceObjects": [],
183
- "support": {
184
- "donate": {
185
- "paypal": "https://www.paypal.com/donate?business=dirk.bertin%40t-online.de"
186
- }
117
+ "instanceObjects": []
187
118
  }
188
- }
189
119
 
@@ -51,6 +51,20 @@ const pumpHelper = {
51
51
  if (this.deviceId) {
52
52
  this.adapter.subscribeForeignStates(this.deviceId);
53
53
  this.adapter.log.info(`[pumpHelper] Überwache Steckdose: ${this.deviceId}`);
54
+
55
+ // NEU: Initialwert übernehmen
56
+ this.adapter
57
+ .getForeignStateAsync(this.deviceId)
58
+ .then(s => {
59
+ if (s) {
60
+ const val = !!s.val;
61
+ this.adapter.setStateAsync('pump.pump_switch', { val, ack: true });
62
+ this.adapter.log.info(`[pumpHelper] Initialer Pumpenstatus von Steckdose übernommen: ${val}`);
63
+ }
64
+ })
65
+ .catch(err =>
66
+ this.adapter.log.warn(`[pumpHelper] Konnte initialen Pumpenstatus nicht laden: ${err.message}`),
67
+ );
54
68
  } else {
55
69
  this.adapter.log.info('[pumpHelper] Keine Objekt-ID für Pumpen-Steckdose konfiguriert');
56
70
  }
@@ -23,13 +23,43 @@ const runtimeHelper = {
23
23
  // Pumpenschalter überwachen
24
24
  this.adapter.subscribeStates('pump.pump_switch');
25
25
 
26
- // Tagesreset einplanen
27
- this._scheduleDailyReset();
26
+ // >>> NEU: Alte Werte aus States laden
27
+ this._restoreFromStates()
28
+ .then(() => {
29
+ // Tagesreset einplanen
30
+ this._scheduleDailyReset();
31
+
32
+ // Erst nach Restore einmal berechnen
33
+ this._updateStates();
34
+
35
+ this.adapter.log.info('[runtimeHelper] initialisiert (mit Restore)');
36
+ })
37
+ .catch(err => {
38
+ this.adapter.log.warn(`[runtimeHelper] Restore fehlgeschlagen: ${err.message}`);
39
+ this._scheduleDailyReset();
40
+ this._updateStates();
41
+ this.adapter.log.info('[runtimeHelper] initialisiert (ohne Restore)');
42
+ });
43
+ },
44
+
45
+ async _restoreFromStates() {
46
+ const total = Number((await this.adapter.getStateAsync('runtime.total'))?.val);
47
+ const today = Number((await this.adapter.getStateAsync('runtime.today'))?.val);
28
48
 
29
- // Gleich beim Start einmal berechnen
30
- this._updateStates();
49
+ if (Number.isFinite(total)) {
50
+ this.runtimeTotal = total;
51
+ }
52
+ if (Number.isFinite(today)) {
53
+ this.runtimeToday = today;
54
+ }
31
55
 
32
- this.adapter.log.info('[runtimeHelper] initialisiert');
56
+ // Falls Pumpe gerade läuft → Status wiederherstellen
57
+ const active = !!(await this.adapter.getStateAsync('pump.pump_switch'))?.val;
58
+ if (active) {
59
+ this.isRunning = true;
60
+ this.lastOn = Date.now();
61
+ this._startLiveTimer();
62
+ }
33
63
  },
34
64
 
35
65
  async handleStateChange(id, state) {
@@ -0,0 +1,226 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * statusHelper
5
+ * - Erstellt Text- und JSON-Zusammenfassungen
6
+ * - Schreibt Pumpenstart/Stop-Zeiten, Zähler, Indikatoren
7
+ * - Hält systemweite OK/Warning-Flags aktuell
8
+ * - Führt Tagesreset um Mitternacht durch
9
+ */
10
+
11
+ const statusHelper = {
12
+ adapter: null,
13
+ midnightTimer: null,
14
+ pumpOn: null, // interner Merker für Pumpenstatus
15
+
16
+ init(adapter) {
17
+ this.adapter = adapter;
18
+
19
+ // Relevante States überwachen
20
+ this.adapter.subscribeStates('pump.status');
21
+ this.adapter.subscribeStates('pump.mode');
22
+ this.adapter.subscribeStates('pump.pump_switch'); // wichtig für Start/Stop
23
+ this.adapter.subscribeStates('temperature.surface.current');
24
+ this.adapter.subscribeStates('temperature.collector.current');
25
+ this.adapter.subscribeStates('temperature.outside.current');
26
+ this.adapter.subscribeStates('runtime.today');
27
+ this.adapter.subscribeStates('circulation.daily_total');
28
+ this.adapter.subscribeStates('circulation.daily_required');
29
+
30
+ // System-Warnungen überwachen
31
+ this.adapter.subscribeStates('solar.collector_warning');
32
+ this.adapter.subscribeStates('pump.error');
33
+
34
+ // Aktuellen Pumpenstatus laden
35
+ this.adapter
36
+ .getStateAsync('pump.pump_switch')
37
+ .then(s => {
38
+ this.pumpOn = !!s?.val;
39
+ })
40
+ .catch(() => {
41
+ this.pumpOn = false;
42
+ });
43
+
44
+ // Beim Start initiale Updates
45
+ this.updateSummary().catch(err =>
46
+ this.adapter.log.warn(`[statusHelper] Initial-Update fehlgeschlagen: ${err.message}`),
47
+ );
48
+ this.updateSystemStatus().catch(err =>
49
+ this.adapter.log.warn(`[statusHelper] Initial-Systemstatus fehlgeschlagen: ${err.message}`),
50
+ );
51
+
52
+ // Mitternacht-Reset einplanen
53
+ this.scheduleMidnightReset();
54
+
55
+ this.adapter.log.info('[statusHelper] initialisiert');
56
+ },
57
+
58
+ async handleStateChange(id, state) {
59
+ if (!state || state.ack !== true) {
60
+ return;
61
+ }
62
+
63
+ // Pumpenstart/-stop
64
+ if (id.endsWith('pump.pump_switch')) {
65
+ const nowOn = !!state.val;
66
+
67
+ // steigende Flanke
68
+ if (nowOn && this.pumpOn !== true) {
69
+ await this.adapter.setStateAsync('status.pump_last_start', {
70
+ val: new Date().toISOString(),
71
+ ack: true,
72
+ });
73
+ const currentCount = (await this.adapter.getStateAsync('status.pump_today_count'))?.val || 0;
74
+ await this.adapter.setStateAsync('status.pump_today_count', { val: currentCount + 1, ack: true });
75
+ await this.adapter.setStateAsync('status.pump_was_on_today', { val: true, ack: true });
76
+ this.pumpOn = true;
77
+ }
78
+
79
+ // fallende Flanke
80
+ if (!nowOn && this.pumpOn !== false) {
81
+ await this.adapter.setStateAsync('status.pump_last_stop', {
82
+ val: new Date().toISOString(),
83
+ ack: true,
84
+ });
85
+ this.pumpOn = false;
86
+ }
87
+ }
88
+
89
+ // System-Warnungen
90
+ if (id.endsWith('solar.collector_warning') || id.endsWith('pump.error')) {
91
+ await this.updateSystemStatus();
92
+ }
93
+
94
+ // Allgemeines Update
95
+ await this.updateSummary();
96
+ },
97
+
98
+ async updateSummary() {
99
+ try {
100
+ // Werte laden
101
+ const pumpStatus = (await this.adapter.getStateAsync('pump.status'))?.val || 'unbekannt';
102
+ const pumpMode = (await this.adapter.getStateAsync('pump.mode'))?.val || 'unknown';
103
+
104
+ const poolTemp = (await this.adapter.getStateAsync('temperature.surface.current'))?.val;
105
+ const collectorTemp = (await this.adapter.getStateAsync('temperature.collector.current'))?.val;
106
+ const outsideTemp = (await this.adapter.getStateAsync('temperature.outside.current'))?.val;
107
+
108
+ const runtimeToday = (await this.adapter.getStateAsync('runtime.today'))?.val || 0;
109
+ const dailyTotal = (await this.adapter.getStateAsync('circulation.daily_total'))?.val || 0;
110
+ const dailyRequired = (await this.adapter.getStateAsync('circulation.daily_required'))?.val || 0;
111
+
112
+ // Laufzeit formatieren
113
+ const h = Math.floor(runtimeToday / 3600);
114
+ const m = Math.floor((runtimeToday % 3600) / 60);
115
+ const runtimeFormatted = `${h}h ${m}m`;
116
+
117
+ // Umwälzungsquote
118
+ let circulationPct = 0;
119
+ if (dailyRequired > 0) {
120
+ circulationPct = Math.round((dailyTotal / dailyRequired) * 100);
121
+ }
122
+
123
+ // Text bauen
124
+ let text = `Pumpe: ${pumpStatus}`;
125
+ if (pumpMode && pumpMode !== 'unknown') {
126
+ text += ` (Modus: ${pumpMode})`;
127
+ }
128
+ if (poolTemp != null) {
129
+ text += `. Pool: ${poolTemp.toFixed(1)} °C`;
130
+ }
131
+ if (collectorTemp != null) {
132
+ text += `, Kollektor: ${collectorTemp.toFixed(1)} °C`;
133
+ }
134
+ if (outsideTemp != null) {
135
+ text += `, Außentemperatur: ${outsideTemp.toFixed(1)} °C`;
136
+ }
137
+ text += `. Tageslaufzeit: ${runtimeFormatted} (${circulationPct}% der Soll-Umwälzung).`;
138
+
139
+ // In States schreiben
140
+ await this.adapter.setStateAsync('status.summary', { val: text, ack: true });
141
+ await this.adapter.setStateAsync('status.last_summary_update', {
142
+ val: new Date().toISOString(),
143
+ ack: true,
144
+ });
145
+
146
+ // JSON-Übersicht bauen
147
+ const json = {
148
+ pump: pumpStatus,
149
+ mode: pumpMode,
150
+ pool: poolTemp,
151
+ collector: collectorTemp,
152
+ outside: outsideTemp,
153
+ runtime_today: runtimeToday,
154
+ runtime_formatted: runtimeFormatted,
155
+ circulation_pct: circulationPct,
156
+ };
157
+ await this.adapter.setStateAsync('status.overview_json', {
158
+ val: JSON.stringify(json),
159
+ ack: true,
160
+ });
161
+ } catch (err) {
162
+ this.adapter.log.warn(`[statusHelper] Fehler beim Update: ${err.message}`);
163
+ }
164
+ },
165
+
166
+ async updateSystemStatus() {
167
+ try {
168
+ const pumpError = (await this.adapter.getStateAsync('pump.error'))?.val;
169
+ const collectorWarning = (await this.adapter.getStateAsync('solar.collector_warning'))?.val;
170
+
171
+ let warningActive = false;
172
+ let warningText = '';
173
+
174
+ if (pumpError) {
175
+ warningActive = true;
176
+ warningText += 'Pumpenfehler ';
177
+ }
178
+ if (collectorWarning) {
179
+ warningActive = true;
180
+ warningText += 'Kollektorwarnung ';
181
+ }
182
+
183
+ await this.adapter.setStateAsync('status.system_warning', { val: warningActive, ack: true });
184
+ await this.adapter.setStateAsync('status.system_warning_text', { val: warningText.trim(), ack: true });
185
+ await this.adapter.setStateAsync('status.system_ok', { val: !warningActive, ack: true });
186
+ } catch (err) {
187
+ this.adapter.log.warn(`[statusHelper] Fehler beim Systemstatus: ${err.message}`);
188
+ }
189
+ },
190
+
191
+ scheduleMidnightReset() {
192
+ if (this.midnightTimer) {
193
+ clearTimeout(this.midnightTimer);
194
+ }
195
+
196
+ const now = new Date();
197
+ const nextMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 5, 0);
198
+ const msToMidnight = nextMidnight.getTime() - now.getTime();
199
+
200
+ this.midnightTimer = setTimeout(async () => {
201
+ await this.doMidnightReset();
202
+ this.scheduleMidnightReset(); // neu einplanen
203
+ }, msToMidnight);
204
+
205
+ this.adapter.log.debug(`[statusHelper] Tagesreset geplant in ${Math.round(msToMidnight / 1000)}s`);
206
+ },
207
+
208
+ async doMidnightReset() {
209
+ try {
210
+ await this.adapter.setStateAsync('status.pump_today_count', { val: 0, ack: true });
211
+ await this.adapter.setStateAsync('status.pump_was_on_today', { val: false, ack: true });
212
+ this.adapter.log.info('[statusHelper] Tagesreset durchgeführt');
213
+ } catch (err) {
214
+ this.adapter.log.warn(`[statusHelper] Fehler beim Tagesreset: ${err.message}`);
215
+ }
216
+ },
217
+
218
+ cleanup() {
219
+ if (this.midnightTimer) {
220
+ clearTimeout(this.midnightTimer);
221
+ this.midnightTimer = null;
222
+ }
223
+ },
224
+ };
225
+
226
+ module.exports = statusHelper;
@@ -30,6 +30,11 @@ const temperatureHelper = {
30
30
  adapter.subscribeForeignStates(id);
31
31
  }
32
32
 
33
+ // >>> NEU: Alte Min/Max-Werte wiederherstellen
34
+ this._restoreMinMaxFromStates().catch(err =>
35
+ this.adapter.log.warn(`[temperatureHelper] Restore Min/Max fehlgeschlagen: ${err.message}`),
36
+ );
37
+
33
38
  // Reset um Mitternacht
34
39
  this._scheduleDailyReset();
35
40
 
@@ -216,6 +221,20 @@ const temperatureHelper = {
216
221
  }
217
222
  },
218
223
 
224
+ // >>> NEU: Restore von min/max beim Start
225
+ async _restoreMinMaxFromStates() {
226
+ for (const key of Object.keys(this.sensors)) {
227
+ const min = Number((await this.adapter.getStateAsync(`temperature.${key}.min_today`))?.val);
228
+ const max = Number((await this.adapter.getStateAsync(`temperature.${key}.max_today`))?.val);
229
+ if (Number.isFinite(min) || Number.isFinite(max)) {
230
+ this.minMax[key] = {
231
+ min: Number.isFinite(min) ? min : undefined,
232
+ max: Number.isFinite(max) ? max : undefined,
233
+ };
234
+ }
235
+ }
236
+ },
237
+
219
238
  cleanup() {
220
239
  if (this.resetTimer) {
221
240
  clearTimeout(this.resetTimer);
@@ -9,6 +9,8 @@
9
9
  * - costs.total_eur
10
10
  * - costs.day_eur, week_eur, month_eur, year_eur
11
11
  *
12
+ * States sind persistent - Werte bleiben erhalten nach Neustart
13
+ *
12
14
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
13
15
  */
14
16
  async function createConsumptionStates(adapter) {
@@ -39,10 +41,15 @@ async function createConsumptionStates(adapter) {
39
41
  unit: cfg.unit,
40
42
  read: true,
41
43
  write: false,
44
+ persist: true,
42
45
  },
43
46
  native: {},
44
47
  });
45
- await adapter.setStateAsync(`consumption.${id}`, { val: 0, ack: true });
48
+ // NUR falls noch kein Wert existiert (erste Installation)
49
+ const cur = await adapter.getStateAsync(`consumption.${id}`);
50
+ if (cur == null) {
51
+ await adapter.setStateAsync(`consumption.${id}`, { val: 0, ack: true });
52
+ }
46
53
  }
47
54
 
48
55
  // --- Kanal costs ---
@@ -70,10 +77,14 @@ async function createConsumptionStates(adapter) {
70
77
  unit: cfg.unit,
71
78
  read: true,
72
79
  write: false,
80
+ persist: true,
73
81
  },
74
82
  native: {},
75
83
  });
76
- await adapter.setStateAsync(`costs.${id}`, { val: 0, ack: true });
84
+ const cur = await adapter.getStateAsync(`costs.${id}`);
85
+ if (cur == null) {
86
+ await adapter.setStateAsync(`costs.${id}`, { val: 0, ack: true });
87
+ }
77
88
  }
78
89
  }
79
90
 
@@ -9,6 +9,8 @@
9
9
  * - circulation.daily_required
10
10
  * - circulation.daily_remaining
11
11
  *
12
+ * States sind persistent - behalten Werte über Neustart
13
+ *
12
14
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
13
15
  */
14
16
  async function createRuntimeStates(adapter) {
@@ -28,6 +30,7 @@ async function createRuntimeStates(adapter) {
28
30
  unit: 's',
29
31
  read: true,
30
32
  write: false,
33
+ persist: true,
31
34
  },
32
35
  native: {},
33
36
  });
@@ -41,6 +44,7 @@ async function createRuntimeStates(adapter) {
41
44
  unit: 's',
42
45
  read: true,
43
46
  write: false,
47
+ persist: true,
44
48
  },
45
49
  native: {},
46
50
  });
@@ -53,6 +57,7 @@ async function createRuntimeStates(adapter) {
53
57
  role: 'text',
54
58
  read: true,
55
59
  write: false,
60
+ persist: true,
56
61
  },
57
62
  native: {},
58
63
  });
@@ -73,6 +78,7 @@ async function createRuntimeStates(adapter) {
73
78
  unit: 'l',
74
79
  read: true,
75
80
  write: false,
81
+ persist: true,
76
82
  },
77
83
  native: {},
78
84
  });
@@ -86,6 +92,7 @@ async function createRuntimeStates(adapter) {
86
92
  unit: 'l',
87
93
  read: true,
88
94
  write: false,
95
+ persist: true,
89
96
  },
90
97
  native: {},
91
98
  });
@@ -103,6 +110,7 @@ async function createRuntimeStates(adapter) {
103
110
  unit: 'l',
104
111
  read: true,
105
112
  write: false,
113
+ persist: true,
106
114
  },
107
115
  native: {},
108
116
  });
@@ -0,0 +1,185 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Legt alle States für Status-Übersichten an:
5
+ * - status.summary (string, Textzusammenfassung)
6
+ * - status.overview_json (string, JSON-Zusammenfassung)
7
+ * - status.last_summary_update (string, Zeitstempel)
8
+ * - status.pump_last_start (string, Zeitstempel)
9
+ * - status.pump_last_stop (string, Zeitstempel)
10
+ * - status.pump_was_on_today (boolean)
11
+ * - status.pump_today_count (number)
12
+ * - status.system_ok (boolean)
13
+ * - status.system_warning (boolean)
14
+ * - status.system_warning_text (string)
15
+ * - status.season_active (boolean)
16
+ *
17
+ * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
18
+ */
19
+ async function createStatusStates(adapter) {
20
+ // Root-Kanal "status"
21
+ await adapter.setObjectNotExistsAsync('status', {
22
+ type: 'channel',
23
+ common: { name: 'Statusübersicht' },
24
+ native: {},
25
+ });
26
+
27
+ // Zusammenfassung als Text
28
+ await adapter.setObjectNotExistsAsync('status.summary', {
29
+ type: 'state',
30
+ common: {
31
+ name: 'Zusammenfassung als Text',
32
+ type: 'string',
33
+ role: 'text',
34
+ read: true,
35
+ write: false,
36
+ // bewusst kein persist: true, da nur Live-Daten
37
+ },
38
+ native: {},
39
+ });
40
+ await adapter.setStateAsync('status.summary', { val: '', ack: true });
41
+
42
+ // JSON-Zusammenfassung
43
+ await adapter.setObjectNotExistsAsync('status.overview_json', {
44
+ type: 'state',
45
+ common: {
46
+ name: 'Übersicht als JSON',
47
+ type: 'string',
48
+ role: 'json',
49
+ read: true,
50
+ write: false,
51
+ },
52
+ native: {},
53
+ });
54
+ await adapter.setStateAsync('status.overview_json', { val: '{}', ack: true });
55
+
56
+ // Letzte Aktualisierung der Summary
57
+ await adapter.setObjectNotExistsAsync('status.last_summary_update', {
58
+ type: 'state',
59
+ common: {
60
+ name: 'Letzte Aktualisierung der Zusammenfassung',
61
+ type: 'string',
62
+ role: 'date',
63
+ read: true,
64
+ write: false,
65
+ },
66
+ native: {},
67
+ });
68
+ await adapter.setStateAsync('status.last_summary_update', { val: '', ack: true });
69
+
70
+ // Pumpen-Status: letzter Start
71
+ await adapter.setObjectNotExistsAsync('status.pump_last_start', {
72
+ type: 'state',
73
+ common: {
74
+ name: 'Letzter Pumpenstart',
75
+ type: 'string',
76
+ role: 'date',
77
+ read: true,
78
+ write: false,
79
+ },
80
+ native: {},
81
+ });
82
+ await adapter.setStateAsync('status.pump_last_start', { val: '', ack: true });
83
+
84
+ // Pumpen-Status: letzter Stopp
85
+ await adapter.setObjectNotExistsAsync('status.pump_last_stop', {
86
+ type: 'state',
87
+ common: {
88
+ name: 'Letztes Pumpenende',
89
+ type: 'string',
90
+ role: 'date',
91
+ read: true,
92
+ write: false,
93
+ },
94
+ native: {},
95
+ });
96
+ await adapter.setStateAsync('status.pump_last_stop', { val: '', ack: true });
97
+
98
+ // Pumpen-Status: heute eingeschaltet
99
+ await adapter.setObjectNotExistsAsync('status.pump_was_on_today', {
100
+ type: 'state',
101
+ common: {
102
+ name: 'Pumpe war heute eingeschaltet',
103
+ type: 'boolean',
104
+ role: 'indicator',
105
+ read: true,
106
+ write: false,
107
+ },
108
+ native: {},
109
+ });
110
+ await adapter.setStateAsync('status.pump_was_on_today', { val: false, ack: true });
111
+
112
+ // Pumpen-Status: Anzahl Starts heute
113
+ await adapter.setObjectNotExistsAsync('status.pump_today_count', {
114
+ type: 'state',
115
+ common: {
116
+ name: 'Pumpenstarts heute',
117
+ type: 'number',
118
+ role: 'value',
119
+ read: true,
120
+ write: false,
121
+ },
122
+ native: {},
123
+ });
124
+ await adapter.setStateAsync('status.pump_today_count', { val: 0, ack: true });
125
+
126
+ // Systemstatus: OK
127
+ await adapter.setObjectNotExistsAsync('status.system_ok', {
128
+ type: 'state',
129
+ common: {
130
+ name: 'System OK',
131
+ type: 'boolean',
132
+ role: 'indicator',
133
+ read: true,
134
+ write: false,
135
+ },
136
+ native: {},
137
+ });
138
+ await adapter.setStateAsync('status.system_ok', { val: true, ack: true });
139
+
140
+ // Systemstatus: Warnung aktiv
141
+ await adapter.setObjectNotExistsAsync('status.system_warning', {
142
+ type: 'state',
143
+ common: {
144
+ name: 'System-Warnung aktiv',
145
+ type: 'boolean',
146
+ role: 'indicator',
147
+ read: true,
148
+ write: false,
149
+ },
150
+ native: {},
151
+ });
152
+ await adapter.setStateAsync('status.system_warning', { val: false, ack: true });
153
+
154
+ // Systemstatus: Warnungstext
155
+ await adapter.setObjectNotExistsAsync('status.system_warning_text', {
156
+ type: 'state',
157
+ common: {
158
+ name: 'Beschreibung der Systemwarnung',
159
+ type: 'string',
160
+ role: 'text',
161
+ read: true,
162
+ write: false,
163
+ },
164
+ native: {},
165
+ });
166
+ await adapter.setStateAsync('status.system_warning_text', { val: '', ack: true });
167
+
168
+ // Saisonstatus
169
+ await adapter.setObjectNotExistsAsync('status.season_active', {
170
+ type: 'state',
171
+ common: {
172
+ name: 'Poolsaison aktiv',
173
+ type: 'boolean',
174
+ role: 'indicator',
175
+ read: true,
176
+ write: false,
177
+ },
178
+ native: {},
179
+ });
180
+ await adapter.setStateAsync('status.season_active', { val: false, ack: true });
181
+ }
182
+
183
+ module.exports = {
184
+ createStatusStates,
185
+ };
@@ -16,6 +16,8 @@
16
16
  * - temperature.delta.surface_ground
17
17
  * - temperature.delta.flow_return
18
18
  *
19
+ * States mit Persistenz - bleiben erhalten bei Neustart
20
+ *
19
21
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
20
22
  */
21
23
  async function createTemperatureStates(adapter) {
@@ -97,6 +99,7 @@ async function createTemperatureStates(adapter) {
97
99
  unit: '°C',
98
100
  read: true,
99
101
  write: false,
102
+ persist: true,
100
103
  },
101
104
  native: {},
102
105
  });
@@ -110,6 +113,7 @@ async function createTemperatureStates(adapter) {
110
113
  unit: '°C',
111
114
  read: true,
112
115
  write: false,
116
+ persist: true,
113
117
  },
114
118
  native: {},
115
119
  });
package/main.js CHANGED
@@ -13,6 +13,7 @@ const speechHelper = require('./lib/helpers/speechHelper');
13
13
  const consumptionHelper = require('./lib/helpers/consumptionHelper');
14
14
  const solarHelper = require('./lib/helpers/solarHelper');
15
15
  const frostHelper = require('./lib/helpers/frostHelper');
16
+ const statusHelper = require('./lib/helpers/statusHelper');
16
17
  const { createTemperatureStates } = require('./lib/stateDefinitions/temperatureStates');
17
18
  const { createPumpStates } = require('./lib/stateDefinitions/pumpStates');
18
19
  const { createSolarStates } = require('./lib/stateDefinitions/solarStates');
@@ -21,6 +22,7 @@ const { createTimeStates } = require('./lib/stateDefinitions/timeStates');
21
22
  const { createRuntimeStates } = require('./lib/stateDefinitions/runtimeStates');
22
23
  const { createSpeechStates } = require('./lib/stateDefinitions/speechStates');
23
24
  const { createConsumptionStates } = require('./lib/stateDefinitions/consumptionStates');
25
+ const { createStatusStates } = require('./lib/stateDefinitions/statusStates');
24
26
 
25
27
  class Poolcontrol extends utils.Adapter {
26
28
  constructor(options) {
@@ -60,6 +62,9 @@ class Poolcontrol extends utils.Adapter {
60
62
  // --- Verbrauch & Kosten ---
61
63
  await createConsumptionStates(this);
62
64
 
65
+ // --- Statusübersicht ---
66
+ await createStatusStates(this);
67
+
63
68
  // --- Helper starten ---
64
69
  temperatureHelper.init(this);
65
70
  timeHelper.init(this);
@@ -69,6 +74,7 @@ class Poolcontrol extends utils.Adapter {
69
74
  consumptionHelper.init(this);
70
75
  solarHelper.init(this);
71
76
  frostHelper.init(this);
77
+ statusHelper.init(this);
72
78
  }
73
79
 
74
80
  onUnload(callback) {
@@ -97,6 +103,9 @@ class Poolcontrol extends utils.Adapter {
97
103
  if (frostHelper.cleanup) {
98
104
  frostHelper.cleanup();
99
105
  }
106
+ if (statusHelper.cleanup) {
107
+ statusHelper.cleanup();
108
+ }
100
109
  } catch (e) {
101
110
  this.log.warn(`[onUnload] Fehler beim Cleanup: ${e.message}`);
102
111
  } finally {
@@ -135,6 +144,11 @@ class Poolcontrol extends utils.Adapter {
135
144
  } catch (e) {
136
145
  this.log.warn(`[consumptionHelper] Fehler in handleStateChange: ${e.message}`);
137
146
  }
147
+ try {
148
+ statusHelper.handleStateChange(id, state);
149
+ } catch (e) {
150
+ this.log.warn(`[statusHelper] Fehler in handleStateChange: ${e.message}`);
151
+ }
138
152
  }
139
153
  }
140
154
 
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Steuerung & Automatisierung für den Pool (Pumpe, Heizung, Ventile, Sensoren).",
5
5
  "author": "DasBo1975 <dasbo1975@outlook.de>",
6
- "homepage": "https://github.com/DasBo1975/iobroker.poolcontrol",
6
+ "homepage": "https://github.com/DasBo1975/ioBroker.poolcontrol",
7
7
  "license": "MIT",
8
8
  "keywords": [
9
+ "ioBroker",
9
10
  "pool",
10
11
  "pumpe",
11
12
  "solar",
@@ -14,7 +15,7 @@
14
15
  ],
15
16
  "repository": {
16
17
  "type": "git",
17
- "url": "https://github.com/DasBo1975/iobroker.poolcontrol.git"
18
+ "url": "https://github.com/DasBo1975/ioBroker.poolcontrol.git"
18
19
  },
19
20
  "engines": {
20
21
  "node": ">= 20"
@@ -26,14 +27,9 @@
26
27
  "@iobroker/adapter-dev": "^1.5.0",
27
28
  "@iobroker/eslint-config": "^2.2.0",
28
29
  "@iobroker/testing": "^5.1.1",
29
- "chai": "^4.5.0",
30
- "chai-as-promised": "^7.1.2",
31
30
  "eslint": "^9.36.0",
32
- "mocha": "^11.7.2",
33
31
  "prettier": "^3.6.2",
34
- "proxyquire": "^2.1.3",
35
- "sinon": "^21.0.0",
36
- "sinon-chai": "^3.7.0"
32
+ "proxyquire": "^2.1.3"
37
33
  },
38
34
  "main": "main.js",
39
35
  "files": [
@@ -54,7 +50,7 @@
54
50
  "translate": "translate-adapter"
55
51
  },
56
52
  "bugs": {
57
- "url": "https://github.com/DasBo1975/iobroker.poolcontrol/issues"
53
+ "url": "https://github.com/DasBo1975/ioBroker.poolcontrol/issues"
58
54
  },
59
55
  "readmeFilename": "README.md"
60
56
  }