iobroker.poolcontrol 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -135,6 +135,16 @@ Neue Funktionen werden regelmäßig ergänzt – bitte den Changelog beachten.
135
135
  ## Changelog
136
136
  ### **WORK IN PROGRESS**
137
137
 
138
+
139
+ ## v0.7.0 (2025-11-29)
140
+ - Einführung eines neuen Drucksensor-Systems unter `pump.pressure.*`
141
+ - Unterstützung externer Drucksensor-ObjektID (bar-Wert aus ioBroker)
142
+ - Trenderkennung (steigend/fallend/stabil) und gleitender Druckdurchschnitt
143
+ - Selbstlernende Min-/Max-Druckwerte mit manuellem Reset-State
144
+ - Neuer Diagnose-Text (`status_text_diagnostic`) mit erweiterten Analyseinformationen
145
+ - Erweiterte Pumpenüberwachung ohne automatische Steuerlogik (rein informativ)
146
+
147
+
138
148
  ## v0.6.2 (2025-11-07)
139
149
  - Überarbeitung der Instanzübersicht mit neuen Header-Strukturen für klarere Bedienung
140
150
  - Neues Startseitenbild „Egon im Blaumann“ in der Admin-Oberfläche integriert
@@ -199,6 +199,48 @@
199
199
  "md": 12,
200
200
  "lg": 12,
201
201
  "xl": 12
202
+ },
203
+ "pressure_header": {
204
+ "type": "header",
205
+ "text": "Drucksensor (Filterdruck)",
206
+ "size": 4,
207
+ "newLine": true,
208
+ "xs": 12,
209
+ "sm": 12,
210
+ "md": 12,
211
+ "lg": 12,
212
+ "xl": 12
213
+ },
214
+ "use_pressure_sensor": {
215
+ "type": "checkbox",
216
+ "label": "Drucksensor verwenden",
217
+ "default": false,
218
+ "xs": 12,
219
+ "sm": 3,
220
+ "md": 3,
221
+ "lg": 3,
222
+ "xl": 3,
223
+ "newLine": true
224
+ },
225
+ "pressure_sensor_id": {
226
+ "type": "objectId",
227
+ "label": "Objekt-ID Drucksensor (bar)",
228
+ "default": "",
229
+ "xs": 12,
230
+ "sm": 3,
231
+ "md": 3,
232
+ "lg": 3,
233
+ "xl": 3
234
+ },
235
+ "pressure_hint": {
236
+ "type": "staticText",
237
+ "text": "Hinweis: Unterstützt sowohl externe Sensoren als auch die PoolControl-Druckbox.",
238
+ "newLine": true,
239
+ "xs": 12,
240
+ "sm": 12,
241
+ "md": 12,
242
+ "lg": 12,
243
+ "xl": 12
202
244
  },
203
245
  "pump_safety_header": {
204
246
  "type": "header",
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "0.6.5",
4
+ "version": "0.7.1",
5
5
  "news": {
6
+ "0.7.1": {
7
+ "en": "Fix for pressure sensor initialization: The adapter now correctly recognizes the configured sensor ID in pumpHelper4. Additionally improved handling of missing / invalid values.",
8
+ "de": "Fehlerbehebung bei der Drucksensor-Initialisierung: Der Adapter erkennt nun die konfigurierte Sensor-ID in pumpHelper4 korrekt. Außerdem wurde die Verarbeitung fehlender oder ungültiger Werte verbessert.",
9
+ "ru": "Исправление инициализации датчика давления: адаптер теперь корректно распознаёт настроенный идентификатор датчика в pumpHelper4. Улучшена обработка отсутствующих и недопустимых значений.",
10
+ "pt": "Correção na inicialização do sensor de pressão: o adaptador agora reconhece corretamente o ID configurado do sensor em pumpHelper4. Manipulação aprimorada de valores ausentes ou inválidos.",
11
+ "nl": "Foutoplossing voor de druksensor-initialisatie: de adapter herkent nu correct de geconfigureerde sensor-ID in pumpHelper4. Verbeterde verwerking van ontbrekende of ongeldige waarden.",
12
+ "fr": "Correction de l'initialisation du capteur de pression : l'adaptateur reconnaît désormais correctement l'ID du capteur configuré dans pumpHelper4. Amélioration du traitement des valeurs manquantes ou invalides.",
13
+ "it": "Correzione dell'inizializzazione del sensore di pressione: l'adattatore ora riconosce correttamente l'ID configurato del sensore in pumpHelper4. Migliorata anche la gestione dei valori mancanti o non validi.",
14
+ "es": "Corrección en la inicialización del sensor de presión: el adaptador ahora reconoce correctamente la ID del sensor configurado en pumpHelper4. Manejo mejorado de valores faltantes o inválidos.",
15
+ "pl": "Poprawka inicjalizacji czujnika ciśnienia: adapter poprawnie rozpoznaje teraz skonfigurowany identyfikator czujnika w pumpHelper4. Ulepszono również obsługę brakujących lub nieprawidłowych wartości.",
16
+ "uk": "Виправлення ініціалізації датчика тиску: адаптер тепер правильно розпізнає налаштований ID датчика в pumpHelper4. Покращено обробку відсутніх або некоректних значень.",
17
+ "zh-cn": "修复压力传感器初始化:适配器现在可以正确识别 pumpHelper4 中配置的传感器 ID,并改进了对缺失或无效数值的处理。"
18
+ },
19
+ "0.7.0": {
20
+ "en": "Added full pressure sensor integration (pump.pressure.*), including trend detection, self-learning min/max values, diagnostic output and configurable normal pressure range. No automatic control logic – purely informative.",
21
+ "de": "Vollständige Drucksensor-Integration (pump.pressure.*) hinzugefügt, inklusive Trenderkennung, selbstlernenden Min-/Max-Werten, Diagnoseausgabe und einstellbarem Normaldruckbereich. Keine automatische Logik – rein informativ.",
22
+ "ru": "Добавлена полная интеграция датчика давления (pump.pressure.*), включая определение тренда, самообучающиеся минимальные/максимальные значения, диагностический вывод и настраиваемый диапазон нормального давления. Без автоматической логики – только информация.",
23
+ "pt": "Adicionada integração completa do sensor de pressão (pump.pressure.*), incluindo detecção de tendência, valores mínimos/máximos autoaprendidos, saída de diagnóstico e faixa de pressão normal configurável. Sem lógica automática – apenas informativo.",
24
+ "nl": "Volledige druksensorintegratie (pump.pressure.*) toegevoegd, inclusief trenddetectie, zelflerende min/max-waarden, diagnostische uitvoer en instelbaar normaaldrukbereik. Geen automatische logica – puur informatief.",
25
+ "fr": "Intégration complète du capteur de pression (pump.pressure.*) ajoutée, comprenant la détection de tendance, des valeurs min/max auto-apprises, une sortie de diagnostic et une plage de pression normale configurable. Aucune logique automatique – uniquement informatif.",
26
+ "it": "Aggiunta integrazione completa del sensore di pressione (pump.pressure.*), con rilevamento delle tendenze, valori min/max autoapprendenti, output diagnostico e intervallo di pressione normale configurabile. Nessuna logica automatica – solo informativo.",
27
+ "es": "Se añadió la integración completa del sensor de presión (pump.pressure.*), incluyendo detección de tendencia, valores mínimos/máximos autoaprendidos, salida de diagnóstico y rango de presión normal configurable. Sin lógica automática – solo informativo.",
28
+ "pl": "Dodano pełną integrację czujnika ciśnienia (pump.pressure.*), w tym wykrywanie trendów, samo uczące się wartości min/max, dane diagnostyczne oraz konfigurowalny zakres ciśnienia normalnego. Bez automatycznej logiki – wyłącznie informacyjne.",
29
+ "uk": "Додано повну інтеграцію датчика тиску (pump.pressure.*), включаючи визначення трендів, самонавчальні мін/макс значення, діагностичний вихід та налаштовуваний діапазон нормального тиску. Без автоматичної логіки – лише інформаційно.",
30
+ "zh-cn": "新增完整压力传感器集成 (pump.pressure.*),包括趋势检测、自学习最小/最大值、诊断输出以及可配置的正常压力范围。无自动控制逻辑,仅提供信息。"
31
+ },
6
32
  "0.6.5": {
7
33
  "en": "Fix for weekly, monthly and yearly reset in consumptionHelper",
8
34
  "de": "Fix für Wochen-, Monats- und Jahres-Reset im ConsumptionHelper",
@@ -65,32 +91,6 @@
65
91
  "es": "Corregido el restablecimiento mensual erróneo cuando no existía una fecha last_reset. Corregida la marca de tiempo real last_update en las estadísticas mensuales.",
66
92
  "pl": "Naprawiono błędny miesięczny reset, gdy nie istniała data last_reset. Poprawiono rzeczywisty znacznik czasu last_update w miesięcznych statystykach.",
67
93
  "zh-cn": "修复了在不存在 last_reset 日期时错误的月度重置。修正了月度统计中的真实 last_update 时间戳。"
68
- },
69
- "0.6.0": {
70
- "en": "Added complete photovoltaic control with automatic pump management (mode 'Automatik (PV)'). The adapter can now react to PV surplus based on configurable house consumption and generation values. Includes migration for existing installations. Improved system consistency and internal logging.",
71
- "de": "Vollständige Photovoltaik-Steuerung mit automatischer Pumpenlogik (Modus 'Automatik (PV)') hinzugefügt. Der Adapter reagiert nun auf PV-Überschuss anhand konfigurierbarer Hausverbrauchs- und Erzeugungswerte. Migration für bestehende Installationen integriert. Systemkonsistenz und interne Protokollierung verbessert.",
72
- "ru": "Добавлено полное управление фотоэлектрической системой с автоматическим управлением насосом (режим 'Automatik (PV)'). Адаптер теперь реагирует на избыток PV на основе настраиваемых значений потребления и генерации. Включена миграция для существующих установок. Улучшена системная согласованность и внутреннее ведение журнала.",
73
- "pt": "Adicionado controle fotovoltaico completo com gerenciamento automático da bomba (modo 'Automatik (PV)'). O adaptador agora reage ao excedente de PV com base nos valores configuráveis de consumo e geração da casa. Inclui migração para instalações existentes. Consistência do sistema e registro interno aprimorados.",
74
- "nl": "Volledige fotovoltaïsche besturing toegevoegd met automatische pompbesturing (modus 'Automatik (PV)'). De adapter reageert nu op PV-overschot op basis van configureerbare huisverbruik- en opwekkingswaarden. Migratie voor bestaande installaties inbegrepen. Verbeterde systeemconsistentie en interne logboekregistratie.",
75
- "fr": "Ajout du contrôle photovoltaïque complet avec gestion automatique de la pompe (mode 'Automatik (PV)'). L'adaptateur réagit désormais au surplus photovoltaïque en fonction des valeurs configurables de consommation et de production domestiques. Migration incluse pour les installations existantes. Cohérence du système et journalisation interne améliorées.",
76
- "it": "Aggiunto controllo fotovoltaico completo con gestione automatica della pompa (modalità 'Automatik (PV)'). L'adattatore ora reagisce al surplus fotovoltaico in base ai valori configurabili di consumo e generazione domestici. Migrazione inclusa per le installazioni esistenti. Migliorata la coerenza del sistema e la registrazione interna.",
77
- "es": "Se añadió control fotovoltaico completo con gestión automática de la bomba (modo 'Automatik (PV)'). El adaptador ahora reacciona al excedente fotovoltaico según los valores configurables de consumo y generación de la casa. Incluye migración para instalaciones existentes. Mejorada la coherencia del sistema y el registro interno.",
78
- "pl": "Dodano pełną kontrolę fotowoltaiczną z automatycznym zarządzaniem pompą (tryb 'Automatik (PV)'). Adapter reaguje teraz na nadwyżkę PV w oparciu o konfigurowalne wartości zużycia i produkcji energii. Zawiera migrację dla istniejących instalacji. Poprawiono spójność systemu i wewnętrzne logowanie.",
79
- "uk": "Додано повний фотогальванічний контроль з автоматичним керуванням насосом (режим 'Automatik (PV)'). Адаптер тепер реагує на надлишок PV на основі налаштовуваних значень споживання та генерації. Включено міграцію для існуючих установок. Покращено системну узгодженість і внутрішнє журналювання.",
80
- "zh-cn": "新增完整的光伏控制与自动泵管理(模式“Automatik (PV)”)。适配器现在可根据可配置的家庭耗电与发电数值响应光伏盈余。包含对现有安装的迁移。改进了系统一致性和内部日志记录。"
81
- },
82
- "0.5.5": {
83
- "en": "Fixed remaining timer recursion issue in weekly and monthly statistics to fully prevent infinite reset loops. Cleaned up jsonConfig structure and improved timer handling.",
84
- "de": "Verbleibende Timer-Rekursion in Wochen- und Monatsstatistik behoben, um Endlosschleifen beim Reset endgültig zu verhindern. jsonConfig-Struktur bereinigt und Timer-Handling verbessert.",
85
- "ru": "Исправлена оставшаяся рекурсия таймера в еженедельной и ежемесячной статистике для полного предотвращения бесконечных циклов сброса. Упрощена структура jsonConfig и улучшено управление таймерами.",
86
- "pt": "Corrigida a recursão restante do temporizador nas estatísticas semanais e mensais para evitar completamente loops de redefinição infinitos. Estrutura jsonConfig limpa e manuseio de temporizador aprimorado.",
87
- "nl": "Overgebleven timerrecursie in week- en maandstatistieken opgelost om oneindige resetlussen volledig te voorkomen. jsonConfig-structuur opgeschoond en timerafhandeling verbeterd.",
88
- "fr": "Correction de la récursion restante du minuteur dans les statistiques hebdomadaires et mensuelles afin d'éviter définitivement les boucles de réinitialisation infinies. Structure jsonConfig nettoyée et gestion du minuteur améliorée.",
89
- "it": "Corretta la ricorsione residua del timer nelle statistiche settimanali e mensili per prevenire completamente i loop di reset infiniti. Pulita la struttura jsonConfig e migliorata la gestione dei timer.",
90
- "es": "Corregida la recursión restante del temporizador en las estadísticas semanales y mensuales para evitar completamente los bucles de reinicio infinitos. Estructura jsonConfig limpiada y manejo del temporizador mejorado.",
91
- "pl": "Naprawiono pozostałą rekursję timera w statystykach tygodniowych i miesięcznych, aby całkowicie zapobiec nieskończonym pętlom resetowania. Uporządkowano strukturę jsonConfig i ulepszono obsługę timera.",
92
- "uk": "Виправлено залишкову рекурсію таймера у тижневій та місячній статистиці, щоб повністю запобігти нескінченним циклам скидання. Очищено структуру jsonConfig і покращено обробку таймерів.",
93
- "zh-cn": "修复了每周和每月统计中的剩余计时器递归问题,以完全防止无限重置循环。清理了 jsonConfig 结构并改进了计时器处理。"
94
94
  }
95
95
  },
96
96
  "titleLang": {
@@ -0,0 +1,362 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * pumpHelper4.js
5
+ * ----------------------------------------------------------
6
+ * Drucksensor-Logik für Pumpenbereich
7
+ *
8
+ * Verarbeitet:
9
+ * - pump.pressure.current_bar
10
+ * - pump.pressure.previous_bar
11
+ * - pump.pressure.status_text
12
+ * - pump.pressure.last_update
13
+ *
14
+ * Liest:
15
+ * - Objekt-ID des Drucksensors aus jsonConfig
16
+ *
17
+ * Version: 1.0.1
18
+ */
19
+
20
+ const pumpHelper4 = {
21
+ adapter: null,
22
+ pressureObjectId: null,
23
+
24
+ /**
25
+ * Initialisiert den Helper
26
+ *
27
+ * @param {ioBroker.Adapter} adapter – aktive Adapterinstanz
28
+ */
29
+ async init(adapter) {
30
+ this.adapter = adapter;
31
+
32
+ this.pressureObjectId = adapter.config.pressure_sensor_id || '';
33
+ adapter.log.info(`[pumpHelper4] Initialisierung gestartet (OID: ${this.pressureObjectId || 'nicht gesetzt'})`);
34
+
35
+ if (!this.pressureObjectId) {
36
+ adapter.log.info('[pumpHelper4] Kein Drucksensor in der Instanzkonfiguration angegeben.');
37
+ return;
38
+ }
39
+
40
+ // Drucksensor abonnieren
41
+ adapter.subscribeForeignStates(this.pressureObjectId);
42
+
43
+ adapter.log.info('[pumpHelper4] Erfolgreich initialisiert');
44
+
45
+ // Benutzerdefinierte Normaldruck-Werte einmalig laden
46
+ this.adapter.getStateAsync('pump.pressure.normal_min_bar').then(s => {
47
+ this.lastMin = Number(s?.val) || 0.2;
48
+ });
49
+ this.adapter.getStateAsync('pump.pressure.normal_max_bar').then(s => {
50
+ this.lastMax = Number(s?.val) || 0.8;
51
+ });
52
+ },
53
+
54
+ /**
55
+ * Verarbeitet alle relevanten State-Änderungen
56
+ *
57
+ * @param {string} id - Objekt-ID
58
+ * @param {ioBroker.State} state - Neuer Wert
59
+ */
60
+ async handleStateChange(id, state) {
61
+ if (!state) {
62
+ return;
63
+ }
64
+
65
+ // ------------------------------------------
66
+ // Manueller Reset des Lernsystems
67
+ // ------------------------------------------
68
+ if (id === 'poolcontrol.0.pump.pressure.learning.reset' && state.val === true) {
69
+ const current = await this._getNumber('pump.pressure.current_bar');
70
+
71
+ // Lernwerte zurücksetzen
72
+ await this.adapter.setStateAsync('pump.pressure.learning.learned_min_bar', { val: current, ack: true });
73
+ await this.adapter.setStateAsync('pump.pressure.learning.learned_max_bar', { val: current, ack: true });
74
+ await this.adapter.setStateAsync('pump.pressure.learning.avg_bar', { val: current, ack: true });
75
+ await this.adapter.setStateAsync('pump.pressure.learning.trend_rising', { val: 0, ack: true });
76
+ await this.adapter.setStateAsync('pump.pressure.learning.trend_falling', { val: 0, ack: true });
77
+ await this.adapter.setStateAsync('pump.pressure.learning.trend_stability', { val: 0, ack: true });
78
+
79
+ // Diagnose-Text
80
+ await this.adapter.setStateAsync('pump.pressure.status_text_diagnostic', {
81
+ val: 'Lernsystem zurückgesetzt',
82
+ ack: true,
83
+ });
84
+
85
+ // Reset-Button zurücksetzen
86
+ await this.adapter.setStateAsync('pump.pressure.learning.reset', {
87
+ val: false,
88
+ ack: true,
89
+ });
90
+
91
+ return; // WICHTIG: nichts weiter tun
92
+ }
93
+
94
+ // ------------------------------------------
95
+ // Live-Update der Min/Max-Werte
96
+ // ------------------------------------------
97
+ if (id === 'poolcontrol.0.pump.pressure.normal_min_bar') {
98
+ this.lastMin = Number(state.val) || 0.2;
99
+ this.adapter.log.debug(`[pumpHelper4] Neuer Minimaldruck übernommen: ${this.lastMin} bar`);
100
+ return;
101
+ }
102
+
103
+ if (id === 'poolcontrol.0.pump.pressure.normal_max_bar') {
104
+ this.lastMax = Number(state.val) || 0.8;
105
+ this.adapter.log.debug(`[pumpHelper4] Neuer Maximaldruck übernommen: ${this.lastMax} bar`);
106
+ return;
107
+ }
108
+
109
+ // Nicht der Drucksensor? Dann raus.
110
+ if (id !== this.pressureObjectId) {
111
+ return;
112
+ }
113
+
114
+ try {
115
+ const newBar = Number(state.val);
116
+
117
+ if (isNaN(newBar)) {
118
+ this.adapter.log.warn(`[pumpHelper4] Ungültiger Druckwert empfangen: ${state.val}`);
119
+ return;
120
+ }
121
+
122
+ // ------------------------------------------
123
+ // NEU: Pumpenschalter prüfen
124
+ // ------------------------------------------
125
+ const pumpSwitch = await this.adapter.getStateAsync('pump.pump_switch');
126
+ const pumpIsOn = !!pumpSwitch?.val;
127
+
128
+ // Zeitstempel immer setzen
129
+ const now = new Date().toISOString();
130
+
131
+ // Wenn Pumpe AUS → Status setzen und raus
132
+ if (!pumpIsOn) {
133
+ await this.adapter.setStateAsync('pump.pressure.status_text', {
134
+ val: 'Pumpe aus – kein Filterdruck',
135
+ ack: true,
136
+ });
137
+
138
+ // trotzdem current_bar und last_update aktualisieren
139
+ await this.adapter.setStateAsync('pump.pressure.current_bar', {
140
+ val: newBar,
141
+ ack: true,
142
+ });
143
+
144
+ await this.adapter.setStateAsync('pump.pressure.last_update', {
145
+ val: now,
146
+ ack: true,
147
+ });
148
+
149
+ return;
150
+ }
151
+
152
+ // Alten Wert lesen
153
+ const previous = await this._getNumber('pump.pressure.current_bar');
154
+
155
+ // previous_bar nur updaten, wenn alter Wert > 0
156
+ if (previous > 0) {
157
+ await this.adapter.setStateAsync('pump.pressure.previous_bar', {
158
+ val: previous,
159
+ ack: true,
160
+ });
161
+ }
162
+
163
+ // ------------------------------------------
164
+ // Trend-Erkennung
165
+ // ------------------------------------------
166
+ let rising = 0;
167
+ let falling = 0;
168
+ let stability = 0;
169
+
170
+ const diff = newBar - previous;
171
+
172
+ // Steigend
173
+ if (diff > 0.01) {
174
+ rising = Number(diff.toFixed(3));
175
+ }
176
+
177
+ // Fallend
178
+ if (diff < -0.01) {
179
+ falling = Number(Math.abs(diff).toFixed(3));
180
+ }
181
+
182
+ // Stabil
183
+ if (Math.abs(diff) <= 0.01) {
184
+ stability = 1;
185
+ }
186
+
187
+ // Werte setzen
188
+ await this.adapter.setStateAsync('pump.pressure.learning.trend_rising', {
189
+ val: rising,
190
+ ack: true,
191
+ });
192
+
193
+ await this.adapter.setStateAsync('pump.pressure.learning.trend_falling', {
194
+ val: falling,
195
+ ack: true,
196
+ });
197
+
198
+ await this.adapter.setStateAsync('pump.pressure.learning.trend_stability', {
199
+ val: stability,
200
+ ack: true,
201
+ });
202
+
203
+ // current_bar aktualisieren
204
+ await this.adapter.setStateAsync('pump.pressure.current_bar', {
205
+ val: newBar,
206
+ ack: true,
207
+ });
208
+
209
+ // ------------------------------------------
210
+ // Gleitender Druckdurchschnitt
211
+ // ------------------------------------------
212
+ const oldAvg = await this._getNumber('pump.pressure.learning.avg_bar');
213
+ const newAvg = oldAvg === 0 ? newBar : oldAvg * 0.9 + newBar * 0.1;
214
+
215
+ await this.adapter.setStateAsync('pump.pressure.learning.avg_bar', {
216
+ val: Number(newAvg.toFixed(3)),
217
+ ack: true,
218
+ });
219
+
220
+ // ------------------------------------------
221
+ // Learning MIN/MAX (autoadaptiv)
222
+ // ------------------------------------------
223
+ const learnedMin = await this._getNumber('pump.pressure.learning.learned_min_bar');
224
+ const learnedMax = await this._getNumber('pump.pressure.learning.learned_max_bar');
225
+
226
+ // Wenn noch keine Werte vorhanden
227
+ let newLearnedMin = learnedMin || newBar;
228
+ let newLearnedMax = learnedMax || newBar;
229
+
230
+ // Pumpe stabil → Min/Max leicht erweitern
231
+ if (newBar < newLearnedMin) {
232
+ newLearnedMin = newBar;
233
+ }
234
+
235
+ if (newBar > newLearnedMax) {
236
+ newLearnedMax = newBar;
237
+ }
238
+
239
+ await this.adapter.setStateAsync('pump.pressure.learning.learned_min_bar', {
240
+ val: Number(newLearnedMin.toFixed(3)),
241
+ ack: true,
242
+ });
243
+
244
+ await this.adapter.setStateAsync('pump.pressure.learning.learned_max_bar', {
245
+ val: Number(newLearnedMax.toFixed(3)),
246
+ ack: true,
247
+ });
248
+
249
+ // Zeitstempel schreiben
250
+ // const now = new Date().toISOString();
251
+ await this.adapter.setStateAsync('pump.pressure.last_update', {
252
+ val: now,
253
+ ack: true,
254
+ });
255
+
256
+ // Statustext setzen
257
+ const text = this._getStatusText(newBar);
258
+ await this.adapter.setStateAsync('pump.pressure.status_text', {
259
+ val: text,
260
+ ack: true,
261
+ });
262
+
263
+ // ------------------------------------------
264
+ // Diagnose-Text (Trend + Lernen)
265
+ // ------------------------------------------
266
+ let diagText = '';
267
+
268
+ if (!pumpIsOn) {
269
+ diagText = 'Pumpe aus – keine Diagnose möglich';
270
+ } else {
271
+ const trendParts = [];
272
+
273
+ if (rising > 0) {
274
+ trendParts.push(`steigend (+${rising} bar)`);
275
+ }
276
+ if (falling > 0) {
277
+ trendParts.push(`fallend (-${falling} bar)`);
278
+ }
279
+ if (stability === 1) {
280
+ trendParts.push('stabil');
281
+ }
282
+
283
+ const trendText = trendParts.length > 0 ? trendParts.join(', ') : 'kein Trend erkennbar';
284
+
285
+ const avg = await this._getNumber('pump.pressure.learning.avg_bar');
286
+ const learnedMin = await this._getNumber('pump.pressure.learning.learned_min_bar');
287
+ const learnedMax = await this._getNumber('pump.pressure.learning.learned_max_bar');
288
+
289
+ diagText =
290
+ `Trend: ${trendText} | ` +
291
+ `Durchschnitt: ${avg.toFixed(3)} bar | ` +
292
+ `Lernbereich: ${learnedMin.toFixed(3)}–${learnedMax.toFixed(3)} bar`;
293
+ }
294
+
295
+ // in State schreiben
296
+ await this.adapter.setStateAsync('pump.pressure.status_text_diagnostic', {
297
+ val: diagText,
298
+ ack: true,
299
+ });
300
+
301
+ this.adapter.log.debug(`[pumpHelper4] Druck aktualisiert: ${newBar} bar (vorher: ${previous} bar)`);
302
+ } catch (err) {
303
+ this.adapter.log.warn(`[pumpHelper4] Fehler bei handleStateChange: ${err.message}`);
304
+ }
305
+ },
306
+
307
+ /**
308
+ * Gibt einen einfachen Status basierend auf dem Druck zurück.
309
+ *
310
+ * Berücksichtigt Benutzerwerte:
311
+ * - normal_min_bar
312
+ * - normal_max_bar
313
+ *
314
+ * @param {number} bar - aktueller Druck in bar
315
+ * @returns {string} Statusmeldung
316
+ */
317
+ _getStatusText(bar) {
318
+ if (isNaN(bar)) {
319
+ return 'Ungültiger Druckwert';
320
+ }
321
+
322
+ const min = this.lastMin ?? 0.2;
323
+ const max = this.lastMax ?? 0.8;
324
+
325
+ // Zu niedrig?
326
+ if (bar < min) {
327
+ return `Druck zu niedrig (unter ${min} bar)`;
328
+ }
329
+
330
+ // Normalbereich?
331
+ if (bar >= min && bar <= max) {
332
+ return `Normaldruck (${min}–${max} bar)`;
333
+ }
334
+
335
+ // Zu hoch?
336
+ if (bar > max) {
337
+ return `Druck erhöht (über ${max} bar)`;
338
+ }
339
+
340
+ return 'Unbekannter Zustand';
341
+ },
342
+
343
+ /**
344
+ * Liest einen numerischen State
345
+ *
346
+ * @param {string} id - Die vollständige Objekt-ID des State, dessen numerischer Wert gelesen werden soll
347
+ */
348
+ async _getNumber(id) {
349
+ const state = await this.adapter.getStateAsync(id);
350
+ const val = Number(state?.val);
351
+ return isNaN(val) ? 0 : val;
352
+ },
353
+
354
+ /**
355
+ * Cleanup bei Adapter-Unload
356
+ */
357
+ cleanup() {
358
+ this.adapter?.log.debug('[pumpHelper4] Cleanup ausgeführt.');
359
+ },
360
+ };
361
+
362
+ module.exports = pumpHelper4;
@@ -0,0 +1,312 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * pumpStates4.js
5
+ * ----------------------------------------------------------
6
+ * Legt die States für den Drucksensor im Pumpenbereich an.
7
+ *
8
+ * Ordnerstruktur:
9
+ * pump.pressure.*
10
+ *
11
+ * Diese Datei ergänzt die bisherigen pumpStates.js,
12
+ * pumpStates2.js und pumpStates3.js um Drucksensor-Unterstützung.
13
+ *
14
+ * Alle States sind echte Variablen (persist = true nur falls nötig).
15
+ * ----------------------------------------------------------
16
+ * Version: 1.0.0
17
+ */
18
+
19
+ /**
20
+ * Erstellt alle States für den Drucksensor im Bereich pump.pressure.
21
+ *
22
+ * @param {import('iobroker').Adapter} adapter – Aktive ioBroker Adapterinstanz
23
+ */
24
+ async function createPumpStates4(adapter) {
25
+ adapter.log.debug('[pumpStates4] Initialisierung der Drucksensor-States gestartet.');
26
+
27
+ // ------------------------------------------------------
28
+ // Root-Kanal: pump.pressure
29
+ // ------------------------------------------------------
30
+ await adapter.setObjectNotExistsAsync('pump.pressure', {
31
+ type: 'channel',
32
+ common: {
33
+ name: 'Pumpen-Drucksensor (Filterdruck)',
34
+ },
35
+ native: {},
36
+ });
37
+
38
+ // ------------------------------------------------------
39
+ // Aktueller Druck (bar)
40
+ // ------------------------------------------------------
41
+ await adapter.setObjectNotExistsAsync('pump.pressure.current_bar', {
42
+ type: 'state',
43
+ common: {
44
+ name: 'Aktueller Druck (bar)',
45
+ desc: 'Gemessener aktueller Filterdruck in bar',
46
+ type: 'number',
47
+ role: 'value.pressure',
48
+ unit: 'bar',
49
+ read: true,
50
+ write: false,
51
+ persist: false, // Livewert → NICHT speichern
52
+ },
53
+ native: {},
54
+ });
55
+
56
+ // initial setzen (überinstallationssicher)
57
+ const existing = await adapter.getStateAsync('pump.pressure.current_bar');
58
+ if (existing === null || existing === undefined) {
59
+ await adapter.setStateAsync('pump.pressure.current_bar', { val: 0, ack: true });
60
+ }
61
+
62
+ // ------------------------------------------------------
63
+ // Vorheriger Druckwert (bar)
64
+ // ------------------------------------------------------
65
+ await adapter.setObjectNotExistsAsync('pump.pressure.previous_bar', {
66
+ type: 'state',
67
+ common: {
68
+ name: 'Vorheriger Druck (bar)',
69
+ desc: 'Letzter bekannter Filterdruck vor der aktuellen Messung',
70
+ type: 'number',
71
+ role: 'value.pressure',
72
+ unit: 'bar',
73
+ read: true,
74
+ write: false,
75
+ persist: false,
76
+ },
77
+ native: {},
78
+ });
79
+
80
+ // initial setzen (überinstallationssicher)
81
+ const prev = await adapter.getStateAsync('pump.pressure.previous_bar');
82
+ if (prev === null || prev === undefined) {
83
+ await adapter.setStateAsync('pump.pressure.previous_bar', { val: 0, ack: true });
84
+ }
85
+
86
+ // ------------------------------------------------------
87
+ // Benutzerdefinierte Normaldruck-Bereiche (bar)
88
+ // ------------------------------------------------------
89
+
90
+ // Unterer Normaldruck-Grenzwert (bar)
91
+ await adapter.setObjectNotExistsAsync('pump.pressure.normal_min_bar', {
92
+ type: 'state',
93
+ common: {
94
+ name: 'Normaldruck MIN (bar)',
95
+ desc: 'Unterer Grenzwert des Normaldruck-Bereichs. Werte unterhalb gelten als zu niedrig.',
96
+ type: 'number',
97
+ role: 'level',
98
+ unit: 'bar',
99
+ read: true,
100
+ write: true,
101
+ min: 0,
102
+ max: 2,
103
+ def: 0.2,
104
+ persist: true,
105
+ },
106
+ native: {},
107
+ });
108
+
109
+ const minExisting = await adapter.getStateAsync('pump.pressure.normal_min_bar');
110
+ if (minExisting === null || minExisting === undefined) {
111
+ await adapter.setStateAsync('pump.pressure.normal_min_bar', { val: 0.2, ack: true });
112
+ }
113
+
114
+ // Oberer Normaldruck-Grenzwert (bar)
115
+ await adapter.setObjectNotExistsAsync('pump.pressure.normal_max_bar', {
116
+ type: 'state',
117
+ common: {
118
+ name: 'Normaldruck MAX (bar)',
119
+ desc: 'Oberer Grenzwert des Normaldruck-Bereichs. Werte oberhalb gelten als erhöht.',
120
+ type: 'number',
121
+ role: 'level',
122
+ unit: 'bar',
123
+ read: true,
124
+ write: true,
125
+ min: 0,
126
+ max: 2,
127
+ def: 0.8,
128
+ persist: true,
129
+ },
130
+ native: {},
131
+ });
132
+
133
+ const maxExisting = await adapter.getStateAsync('pump.pressure.normal_max_bar');
134
+ if (maxExisting === null || maxExisting === undefined) {
135
+ await adapter.setStateAsync('pump.pressure.normal_max_bar', { val: 0.8, ack: true });
136
+ }
137
+
138
+ // ------------------------------------------------------
139
+ // Optional vorbereitete States für spätere Erweiterungen
140
+ // ------------------------------------------------------
141
+
142
+ // Zustand / Bewertung
143
+ await adapter.setObjectNotExistsAsync('pump.pressure.status_text', {
144
+ type: 'state',
145
+ common: {
146
+ name: 'Statusmeldung',
147
+ desc: 'Bewertung des Drucks (z. B. Normal / Hoch / Rückspülen nötig)',
148
+ type: 'string',
149
+ role: 'text',
150
+ read: true,
151
+ write: false,
152
+ persist: false,
153
+ },
154
+ native: {},
155
+ });
156
+
157
+ // Erweiterte Diagnoseausgabe
158
+ await adapter.setObjectNotExistsAsync('pump.pressure.status_text_diagnostic', {
159
+ type: 'state',
160
+ common: {
161
+ name: 'Diagnose',
162
+ desc: 'Ausführliche Diagnose basierend auf Trend- und Lernwerten',
163
+ type: 'string',
164
+ role: 'text',
165
+ read: true,
166
+ write: false,
167
+ persist: false,
168
+ },
169
+ native: {},
170
+ });
171
+
172
+ // Letzte Aktualisierung
173
+ await adapter.setObjectNotExistsAsync('pump.pressure.last_update', {
174
+ type: 'state',
175
+ common: {
176
+ name: 'Letzte Aktualisierung',
177
+ desc: 'Zeitstempel der letzten Druckaktualisierung',
178
+ type: 'string',
179
+ role: 'date',
180
+ read: true,
181
+ write: false,
182
+ persist: false,
183
+ },
184
+ native: {},
185
+ });
186
+
187
+ // ------------------------------------------------------
188
+ // Lernwerte-Unterordner anlegen
189
+ // ------------------------------------------------------
190
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning', {
191
+ type: 'channel',
192
+ common: {
193
+ name: 'Lernwerte (Druckverhalten der Pumpe)',
194
+ },
195
+ native: {},
196
+ });
197
+
198
+ // Unterer Lernwert (Wohlfühl-Minimum)
199
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.learned_min_bar', {
200
+ type: 'state',
201
+ common: {
202
+ name: 'Gelerntes Minimum (bar)',
203
+ desc: 'Niedrigster Druck, der im stabilen Betrieb häufig auftritt',
204
+ type: 'number',
205
+ unit: 'bar',
206
+ role: 'value',
207
+ read: true,
208
+ write: true,
209
+ persist: true,
210
+ },
211
+ native: {},
212
+ });
213
+
214
+ // Oberer Lernwert (Wohlfühl-Maximum)
215
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.learned_max_bar', {
216
+ type: 'state',
217
+ common: {
218
+ name: 'Gelerntes Maximum (bar)',
219
+ desc: 'Höchster Druck, der im stabilen Betrieb häufig auftritt',
220
+ type: 'number',
221
+ unit: 'bar',
222
+ role: 'value',
223
+ read: true,
224
+ write: true,
225
+ persist: true,
226
+ },
227
+ native: {},
228
+ });
229
+
230
+ // Gleitender Mittelwert
231
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.avg_bar', {
232
+ type: 'state',
233
+ common: {
234
+ name: 'Gleitender Durchschnittsdruck (bar)',
235
+ desc: 'Berechneter Mittelwert der letzten Messungen',
236
+ type: 'number',
237
+ unit: 'bar',
238
+ role: 'value',
239
+ read: true,
240
+ write: true,
241
+ persist: true,
242
+ },
243
+ native: {},
244
+ });
245
+
246
+ // Trend: Anstieg
247
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.trend_rising', {
248
+ type: 'state',
249
+ common: {
250
+ name: 'Trend Steigend (0–1)',
251
+ desc: 'Gibt an, wie stark der Druck steigt',
252
+ type: 'number',
253
+ role: 'indicator',
254
+ read: true,
255
+ write: true,
256
+ persist: false,
257
+ },
258
+ native: {},
259
+ });
260
+
261
+ // Trend: Abfall
262
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.trend_falling', {
263
+ type: 'state',
264
+ common: {
265
+ name: 'Trend Fallend (0–1)',
266
+ desc: 'Gibt an, wie stark der Druck fällt',
267
+ type: 'number',
268
+ role: 'indicator',
269
+ read: true,
270
+ write: true,
271
+ persist: false,
272
+ },
273
+ native: {},
274
+ });
275
+
276
+ // Trend: Stabilität
277
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.trend_stability', {
278
+ type: 'state',
279
+ common: {
280
+ name: 'Trend Stabilität (0–1)',
281
+ desc: 'Gibt an, wie stabil der Druck insgesamt ist',
282
+ type: 'number',
283
+ role: 'indicator',
284
+ read: true,
285
+ write: true,
286
+ persist: false,
287
+ },
288
+ native: {},
289
+ });
290
+
291
+ // Reset des Lernsystems
292
+ await adapter.setObjectNotExistsAsync('pump.pressure.learning.reset', {
293
+ type: 'state',
294
+ common: {
295
+ name: 'Lernsystem zurücksetzen',
296
+ desc: 'Setzt alle Lernwerte (Min/Max/Avg/Trend) auf den aktuellen Druck zurück',
297
+ type: 'boolean',
298
+ role: 'button',
299
+ read: true,
300
+ write: true,
301
+ def: false,
302
+ persist: false,
303
+ },
304
+ native: {},
305
+ });
306
+
307
+ adapter.log.debug('[pumpStates4] Drucksensor-States erfolgreich erstellt oder geprüft.');
308
+ }
309
+
310
+ module.exports = {
311
+ createPumpStates4,
312
+ };
package/main.js CHANGED
@@ -14,6 +14,7 @@ const statisticsHelperMonth = require('./lib/helpers/statisticsHelperMonth');
14
14
  const pumpHelper = require('./lib/helpers/pumpHelper');
15
15
  const pumpHelper2 = require('./lib/helpers/pumpHelper2');
16
16
  const pumpHelper3 = require('./lib/helpers/pumpHelper3');
17
+ const pumpHelper4 = require('./lib/helpers/pumpHelper4');
17
18
  const speechHelper = require('./lib/helpers/speechHelper');
18
19
  const consumptionHelper = require('./lib/helpers/consumptionHelper');
19
20
  const solarHelper = require('./lib/helpers/solarHelper');
@@ -29,6 +30,7 @@ const { createTemperatureStates } = require('./lib/stateDefinitions/temperatureS
29
30
  const { createPumpStates } = require('./lib/stateDefinitions/pumpStates');
30
31
  const { createPumpStates2 } = require('./lib/stateDefinitions/pumpStates2');
31
32
  const { createPumpStates3 } = require('./lib/stateDefinitions/pumpStates3');
33
+ const { createPumpStates4 } = require('./lib/stateDefinitions/pumpStates4');
32
34
  const { createSolarStates } = require('./lib/stateDefinitions/solarStates');
33
35
  const { createPhotovoltaicStates } = require('./lib/stateDefinitions/photovoltaicStates');
34
36
  const { createGeneralStates } = require('./lib/stateDefinitions/generalStates');
@@ -62,6 +64,7 @@ class Poolcontrol extends utils.Adapter {
62
64
  await createPumpStates(this);
63
65
  await createPumpStates2(this);
64
66
  await createPumpStates3(this);
67
+ await createPumpStates4(this);
65
68
 
66
69
  // --- Temperaturverwaltung ---
67
70
  await createTemperatureStates(this);
@@ -115,6 +118,7 @@ class Poolcontrol extends utils.Adapter {
115
118
  pumpHelper.init(this);
116
119
  pumpHelper2.init(this);
117
120
  pumpHelper3.init(this);
121
+ pumpHelper4.init(this);
118
122
  speechHelper.init(this);
119
123
  consumptionHelper.init(this);
120
124
  solarHelper.init(this);
@@ -150,6 +154,9 @@ class Poolcontrol extends utils.Adapter {
150
154
  if (pumpHelper3.cleanup) {
151
155
  pumpHelper3.cleanup();
152
156
  }
157
+ if (pumpHelper4.cleanup) {
158
+ pumpHelper4.cleanup();
159
+ }
153
160
  if (speechHelper.cleanup) {
154
161
  speechHelper.cleanup();
155
162
  }
@@ -221,6 +228,12 @@ class Poolcontrol extends utils.Adapter {
221
228
  this.log.warn(`[pumpHelper3] Fehler in handleStateChange: ${e.message}`);
222
229
  }
223
230
 
231
+ try {
232
+ pumpHelper4.handleStateChange(id, state);
233
+ } catch (e) {
234
+ this.log.warn(`[pumpHelper4] Fehler in handleStateChange: ${e.message}`);
235
+ }
236
+
224
237
  try {
225
238
  speechHelper.handleStateChange(id, state);
226
239
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "0.6.5",
3
+ "version": "0.7.1",
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",