iobroker.poolcontrol 0.0.9 → 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 +0 -26
- package/README.md +22 -1
- package/admin/jsonConfig.json +6 -1
- package/io-package.json +18 -21
- package/lib/helpers/statusHelper.js +226 -0
- package/lib/stateDefinitions/statusStates.js +185 -0
- package/main.js +14 -0
- package/package.json +2 -7
package/LICENSE
CHANGED
|
@@ -19,29 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
MIT-Lizenz
|
|
26
|
-
|
|
27
|
-
Copyright (c) 2025 DasBo1975
|
|
28
|
-
|
|
29
|
-
Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der
|
|
30
|
-
zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt,
|
|
31
|
-
sie uneingeschränkt zu nutzen, einschließlich und ohne Ausnahme des Rechts,
|
|
32
|
-
sie zu verwenden, zu kopieren, zu ändern, zusammenzuführen, zu veröffentlichen,
|
|
33
|
-
zu verbreiten, zu unterlizenzieren und/oder zu verkaufen, und Personen, denen
|
|
34
|
-
diese Software überlassen wird, diese Rechte zu verschaffen, unter den
|
|
35
|
-
folgenden Bedingungen:
|
|
36
|
-
|
|
37
|
-
Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen
|
|
38
|
-
Kopien oder Teilkopien der Software beizulegen.
|
|
39
|
-
|
|
40
|
-
DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GARANTIE
|
|
41
|
-
BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE DER MARKTREIFE, DER EIGNUNG FÜR
|
|
42
|
-
EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER.
|
|
43
|
-
IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER FÜR ANSPRÜCHE,
|
|
44
|
-
SCHÄDEN ODER SONSTIGE VERPFLICHTUNGEN HAFTBAR ZU MACHEN, OB AUS EINEM
|
|
45
|
-
VERTRAG, EINER UNERLAUBTEN HANDLUNG ODER ANDERWEITIG ENTSTANDEN, DIE SICH AUS
|
|
46
|
-
ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER VERWENDUNG ODER SONSTIGEN
|
|
47
|
-
HANDLUNGEN IN DER SOFTWARE ERGEBEN.
|
package/README.md
CHANGED
|
@@ -94,6 +94,26 @@ Funktionen können sich ändern, bitte regelmäßig den Changelog beachten.
|
|
|
94
94
|
## Changelog
|
|
95
95
|
Auszug, vollständige Liste siehe `io-package.json`:
|
|
96
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
|
+
|
|
97
117
|
### 0.0.9
|
|
98
118
|
- Laufzeit-, Umwälz-, Verbrauch-/Kosten- und Temperatur-Min/Max-States sind jetzt persistent
|
|
99
119
|
(Werte bleiben nach Adapter-Neustart oder Stromausfall erhalten)
|
|
@@ -137,5 +157,6 @@ Der Nutzer ist für die **sichere Installation und den Betrieb seiner Hardware**
|
|
|
137
157
|
---
|
|
138
158
|
|
|
139
159
|
## License
|
|
140
|
-
|
|
160
|
+
Copyright (c) 2025 DasBo1975 <dasbo1975@outlook.de>
|
|
141
161
|
|
|
162
|
+
MIT License
|
package/admin/jsonConfig.json
CHANGED
|
@@ -938,7 +938,12 @@
|
|
|
938
938
|
},
|
|
939
939
|
"helpText": {
|
|
940
940
|
"type": "staticText",
|
|
941
|
-
"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
|
|
942
947
|
}
|
|
943
948
|
}
|
|
944
949
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "poolcontrol",
|
|
4
|
-
"version": "0.0.
|
|
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
|
+
},
|
|
6
19
|
"0.0.9": {
|
|
7
20
|
"en": "Made runtime, circulation, consumption/costs and temperature min/max states persistent across restarts",
|
|
8
21
|
"de": "Laufzeit-, Umwälz-, Verbrauch-/Kosten- und Temperatur-Min/Max-States bleiben jetzt über Neustarts erhalten",
|
|
@@ -28,19 +41,6 @@
|
|
|
28
41
|
"pl": "Dodano kartę pomocy w konfiguracji instancji z linkiem do dokumentacji GitHub",
|
|
29
42
|
"uk": "Додано вкладку довідки в конфігурацію екземпляра з посиланням на документацію GitHub",
|
|
30
43
|
"zh-cn": "在实例配置中添加了帮助选项卡,并链接到 документацию GitHub"
|
|
31
|
-
},
|
|
32
|
-
"0.0.7": {
|
|
33
|
-
"en": "Added help file (help.md) and first README version",
|
|
34
|
-
"de": "Hilfedatei (help.md) und erste README-Version hinzugefügt",
|
|
35
|
-
"ru": "Добавлен файл справки (help.md) и первая версия README",
|
|
36
|
-
"pt": "Adicionado arquivo de ajuda (help.md) e primeira versão do README",
|
|
37
|
-
"nl": "Helpbestand (help.md) en eerste README-versie toegevoegd",
|
|
38
|
-
"fr": "Ajout du fichier d'aide (help.md) et première version du README",
|
|
39
|
-
"it": "Aggiunto file di aiuto (help.md) e prima versione di README",
|
|
40
|
-
"es": "Se agregó archivo de ayuda (help.md) y primera versión de README",
|
|
41
|
-
"pl": "Dodano plik pomocy (help.md) i pierwszą wersję README",
|
|
42
|
-
"uk": "Додано файл довідки (help.md) та першу версію README",
|
|
43
|
-
"zh-cn": "添加了帮助文件 (help.md) 和第一个 README 版本"
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"titleLang": {
|
|
@@ -103,14 +103,11 @@
|
|
|
103
103
|
"js-controller": ">=6.0.11"
|
|
104
104
|
}
|
|
105
105
|
],
|
|
106
|
-
|
|
106
|
+
"globalDependencies": [
|
|
107
|
+
{
|
|
107
108
|
"admin": ">=7.6.17"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"donate": {
|
|
111
|
-
"paypal": "https://www.paypal.com/donate?business=dirk.bertin%40t-online.de"
|
|
112
|
-
}
|
|
113
|
-
}
|
|
109
|
+
}
|
|
110
|
+
]
|
|
114
111
|
},
|
|
115
112
|
"native": {
|
|
116
113
|
"option1": true,
|
|
@@ -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;
|
|
@@ -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
|
+
};
|
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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.poolcontrol",
|
|
3
|
-
"version": "0.0.
|
|
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
6
|
"homepage": "https://github.com/DasBo1975/ioBroker.poolcontrol",
|
|
@@ -27,14 +27,9 @@
|
|
|
27
27
|
"@iobroker/adapter-dev": "^1.5.0",
|
|
28
28
|
"@iobroker/eslint-config": "^2.2.0",
|
|
29
29
|
"@iobroker/testing": "^5.1.1",
|
|
30
|
-
"chai": "^4.5.0",
|
|
31
|
-
"chai-as-promised": "^7.1.2",
|
|
32
30
|
"eslint": "^9.36.0",
|
|
33
|
-
"mocha": "^11.7.2",
|
|
34
31
|
"prettier": "^3.6.2",
|
|
35
|
-
"proxyquire": "^2.1.3"
|
|
36
|
-
"sinon": "^21.0.0",
|
|
37
|
-
"sinon-chai": "^3.7.0"
|
|
32
|
+
"proxyquire": "^2.1.3"
|
|
38
33
|
},
|
|
39
34
|
"main": "main.js",
|
|
40
35
|
"files": [
|