iobroker.poolcontrol 1.3.31 → 1.3.33

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
@@ -36,6 +36,7 @@ It provides automation for pumps, heating, solar and photovoltaic control as wel
36
36
 
37
37
  - **Solar Control**
38
38
  - Collector on/off thresholds with hysteresis
39
+ - Live collector-surface delta for dashboards and scripts
39
40
  - Collector warning threshold
40
41
  - Optional speech output for warnings
41
42
  - Automatic reset logic
@@ -43,10 +44,12 @@ It provides automation for pumps, heating, solar and photovoltaic control as wel
43
44
  - **Solar Extended**
44
45
  - Separate control for external solar actuators
45
46
  - Delta on/off thresholds
47
+ - Live collector-pool reference delta for dashboards and scripts
46
48
  - Maximum pool temperature limits
47
49
  - Diagnostic and reason states
48
50
  - Priority and block logic
49
51
  - Status section under `solar.extended.*`
52
+ - Runtime changes to `solar.extended.pool_temperature_source` are applied automatically; because Solar Extended uses a cyclic check interval, calculation, control logic, and `solar.extended.collector_pool_reference_delta` may take up to approximately 60 seconds to update.
50
53
 
51
54
  - **Photovoltaic Control**
52
55
  - Pump control based on PV surplus and household consumption
@@ -271,6 +274,20 @@ New features are added regularly – please refer to the changelog.
271
274
  ---
272
275
 
273
276
  ## Changelog
277
+ ### 1.3.33 (2026-06-18)
278
+
279
+ - Added live delta states for standard solar and Solar Extended control:
280
+ - `solar.collector_surface_delta`
281
+ - `solar.extended.collector_pool_reference_delta`
282
+ - Documented that runtime changes to `solar.extended.pool_temperature_source` are applied automatically, but may take up to approximately 60 seconds due to the Solar Extended cyclic check interval.
283
+
284
+ ### 1.3.32 (2026-06-08)
285
+
286
+ - Added circulation plausibility diagnostics for daily circulation calculations.
287
+ - Added detection of implausible pump power values, flow rates and daily circulation volume jumps.
288
+ - Added detailed diagnostic states under `circulation.plausibility` for troubleshooting and analysis.
289
+ - Improved diagnostics for circulation calculations without changing existing pump, PV or solar control logic.
290
+
274
291
  ### 1.3.31 (2026-06-07)
275
292
 
276
293
  - Fixed automatic circulation top-up logic when temperature sensors are missing. Automatic top-up is now only blocked by collector/pool temperature comparison when solar control is active and both temperatures are valid.
@@ -289,22 +306,6 @@ New features are added regularly – please refer to the changelog.
289
306
  - Fixed missing initialization of season and solar warning runtime states from adapter configuration.
290
307
  - Added admin UI information about initial configuration values and runtime datapoint control.
291
308
 
292
- ### 1.3.28 (2026-06-03)
293
-
294
- - Added configurable startup power check timeout for pump monitoring (`pump.startup_power_check_timeout_sec`).
295
- - Default behavior remains unchanged (5 seconds).
296
- - Improved compatibility with delayed power measurements from smart plugs and power meters.
297
-
298
- ### 1.3.27 (2026-05-30)
299
-
300
- - Added new Chemistry Tools section
301
- - Added pH Plus Calculator
302
- - Added pH Minus Calculator
303
- - Added Salt Calculator
304
- - Added validation, result texts and error handling for all calculators
305
- - Added automatic pool volume prefill support
306
- - Expanded documentation and function overviews
307
-
308
309
  ## Archived Release History
309
310
 
310
311
  For older releases and archived version history see:
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "1.3.31",
4
+ "version": "1.3.33",
5
5
  "news": {
6
+ "1.3.33": {
7
+ "en": "Added live delta states for standard solar and Solar Extended control. Documented Solar Extended pool reference runtime update behavior.",
8
+ "de": "Live-Delta-Datenpunkte für Standard-Solar und Solar Extended ergänzt. Laufzeitverhalten der Solar-Extended-Poolreferenz dokumentiert.",
9
+ "ru": "Добавлены дельта-состояния в реальном времени для стандартного и расширенного управления солнечной энергией. Документированное поведение обновления во время выполнения ссылки на расширенный пул Solar.",
10
+ "pt": "Adicionados estados delta ao vivo para controle solar padrão e solar estendido. Comportamento de atualização de tempo de execução de referência do pool Solar Extended documentado.",
11
+ "nl": "Live deltatoestanden toegevoegd voor standaard zonne-energie en Solar Extended-regeling. Gedocumenteerd runtime-updategedrag van de Solar Extended-poolreferentie.",
12
+ "fr": "Ajout d'états delta en direct pour le contrôle solaire standard et solaire étendu. Comportement documenté de la mise à jour du runtime de référence du pool Solar Extended.",
13
+ "it": "Aggiunti stati delta live per il controllo solare standard e Solar Extended. Comportamento documentato dell'aggiornamento runtime di riferimento del pool Solar Extended.",
14
+ "es": "Se agregaron estados delta en vivo para control solar estándar y solar extendido. Comportamiento de actualización del tiempo de ejecución de referencia del grupo Solar Extended documentado.",
15
+ "pl": "Dodano stany delta na żywo dla standardowego sterowania solarnego i Solar Extended. Udokumentowane zachowanie aktualizacji środowiska uruchomieniowego referencyjnej puli Solar Extended.",
16
+ "uk": "Додано живі дельта-стани для стандартного сонячного та розширеного керування Solar. Задокументована поведінка оновлення середовища виконання довідкового пулу Solar Extended.",
17
+ "zh-cn": "为标准太阳能和太阳能扩展控制添加了实时增量状态。记录了 Solar Extended 池参考运行时更新行为。"
18
+ },
19
+ "1.3.32": {
20
+ "en": "Added circulation plausibility diagnostics. New checks detect implausible pump power, flow rates, and daily circulation jumps. Added detailed diagnostic states under circulation.plausibility to simplify troubleshooting and analysis of circulation calculations.",
21
+ "de": "Plausibilitätsdiagnose für die Umwälzberechnung hinzugefügt. Neue Prüfungen erkennen unplausible Pumpenleistungen, Durchflusswerte und Sprünge der Tagesumwälzung. Detaillierte Diagnose-States unter circulation.plausibility erleichtern die Fehlersuche und Analyse der Umwälzberechnung.",
22
+ "ru": "Добавлена ​​диагностика достоверности циркуляции. Новые проверки выявляют неправдоподобную мощность насоса, скорость потока и скачки суточной циркуляции. Добавлены подробные диагностические состояния в разделе «циркуляция.достоверность» для упрощения поиска и устранения неисправностей и анализа расчетов циркуляции.",
23
+ "pt": "Adicionados diagnósticos de plausibilidade de circulação. Novas verificações detectam potências de bomba, taxas de fluxo e saltos diários de circulação implausíveis. Adicionados estados de diagnóstico detalhados em circulação.plausibilidade para simplificar a solução de problemas e a análise de cálculos de circulação.",
24
+ "nl": "Diagnostiek van circulatieplausibiliteit toegevoegd. Nieuwe controles detecteren onwaarschijnlijk pompvermogen, debieten en dagelijkse circulatiesprongen. Gedetailleerde diagnostische statussen toegevoegd onder circulatie.plausibiliteit om probleemoplossing en analyse van circulatieberekeningen te vereenvoudigen.",
25
+ "fr": "Ajout de diagnostics de plausibilité de la circulation. De nouveaux contrôles détectent une puissance de pompe, des débits et des sauts de circulation quotidiens invraisemblables. Ajout d'états de diagnostic détaillés sous circulation.plausibilité pour simplifier le dépannage et l'analyse des calculs de circulation.",
26
+ "it": "Aggiunta diagnostica di plausibilità della circolazione. Nuovi controlli rilevano potenza della pompa, portate e salti di circolazione giornalieri non plausibili. Aggiunti stati diagnostici dettagliati in circolazione.plausibilità per semplificare la risoluzione dei problemi e l'analisi dei calcoli della circolazione.",
27
+ "es": "Se agregaron diagnósticos de plausibilidad de circulación. Las nuevas comprobaciones detectan potencias de bombeo, caudales y saltos diarios de circulación inverosímiles. Se agregaron estados de diagnóstico detallados bajo circulación. Plausibilidad para simplificar la resolución de problemas y el análisis de los cálculos de circulación.",
28
+ "pl": "Dodano diagnostykę wiarygodności obiegu. Nowe kontrole wykrywają nieprawdopodobną moc pompy, natężenie przepływu i codzienne skoki cyrkulacji. Dodano szczegółowe stany diagnostyczne w obszarze cyrkulacja.wiarygodność, aby uprościć rozwiązywanie problemów i analizę obliczeń cyrkulacji.",
29
+ "uk": "Додана діагностика вірогідності циркуляції. Нові перевірки виявляють неправдоподібну потужність насоса, швидкість потоку та щоденні стрибки циркуляції. Додано детальні діагностичні стани під циркуляцією. Правдоподібність для спрощення пошуку несправностей і аналізу розрахунків циркуляції.",
30
+ "zh-cn": "添加了循环合理性诊断。新的检查可以检测到难以置信的泵功率、流量和每日循环跳跃。在循环下添加了详细的诊断状态。合理性以简化循环计算的故障排除和分析。"
31
+ },
6
32
  "1.3.31": {
7
33
  "en": "Fixed automatic circulation top-up logic when temperature sensors are missing. Automatic top-up is now only blocked by collector/pool temperature comparison when solar control is active and both temperatures are valid.",
8
34
  "de": "Fehler in der automatischen Nachpump-Logik bei fehlenden Temperatursensoren behoben. Das automatische Nachpumpen wird jetzt nur noch durch den Kollektor-/Pooltemperaturvergleich blockiert, wenn die Solarsteuerung aktiv ist und beide Temperaturwerte gültig vorliegen.",
@@ -41,32 +67,6 @@
41
67
  "pl": "Dodano usługę Pool Insights V1 z obserwacjami, oceną stanu i obsługą środowiska wykonawczego i18n. Ulepszone generowanie tekstu Pool Insights i usunięta zależność od zewnętrznych bloków podsumowań. Naprawiono brakującą inicjalizację stanów wykonawczych sezonu i ostrzeżenia słonecznego z konfiguracji adaptera. Dodano uwagi do interfejsu administratora wyjaśniające wartości początkowe w porównaniu z kontrolą punktów danych w czasie wykonywania.",
42
68
  "uk": "Додано Pool Insights V1 із спостереженнями, оцінкою стану та підтримкою i18n під час виконання. Покращено створення тексту Pool Insights і видалено залежність від зовнішніх блоків підсумків. Виправлено відсутність ініціалізації сезону та станів попередження про сонячне світло з конфігурації адаптера. Додано примітки інтерфейсу користувача адміністратора, що пояснюють початкові значення та керування точкою даних під час виконання.",
43
69
  "zh-cn": "添加了 Pool Insights V1,具有观察、状态评估和运行时 i18n 支持。改进了 Pool Insights 文本生成并消除了对外部摘要块的依赖。修复了适配器配置中缺少季节和太阳警告运行时状态初始化的问题。添加了管理 UI 注释,解释初始值与运行时数据点控制。"
44
- },
45
- "1.3.28": {
46
- "en": "Added configurable startup power check timeout for pump monitoring (5-10 seconds). Improved compatibility with delayed power measurements from smart plugs and power meters.",
47
- "de": "Konfigurierbares Timeout für die Leistungsprüfung nach Pumpenstart (5-10 Sekunden) hinzugefügt. Kompatibilität mit verzögert aktualisierten Leistungswerten von Smart-Steckdosen und Leistungsmessern verbessert.",
48
- "ru": "Добавлен настраиваемый тайм-аут проверки мощности при запуске для мониторинга насоса (5–10 секунд). Улучшена совместимость с измерениями мощности с задержкой от интеллектуальных розеток и измерителей мощности.",
49
- "pt": "Adicionado tempo limite de verificação de energia de inicialização configurável para monitoramento da bomba (5 a 10 segundos). Compatibilidade aprimorada com medições de energia atrasadas de plugues inteligentes e medidores de energia.",
50
- "nl": "Configureerbare time-out voor stroomcontrole bij opstarten toegevoegd voor pompbewaking (5-10 seconden). Verbeterde compatibiliteit met vertraagde stroommetingen van slimme stekkers en stroommeters.",
51
- "fr": "Ajout d'un délai d'expiration configurable pour la vérification de l'alimentation au démarrage pour la surveillance de la pompe (5 à 10 secondes). Compatibilité améliorée avec les mesures de puissance retardées des prises intelligentes et des compteurs de puissance.",
52
- "it": "Aggiunto timeout configurabile del controllo dell'alimentazione all'avvio per il monitoraggio della pompa (5-10 secondi). Compatibilità migliorata con misurazioni di potenza ritardate da prese intelligenti e misuratori di potenza.",
53
- "es": "Se agregó un tiempo de espera de verificación de energía de inicio configurable para el monitoreo de la bomba (5-10 segundos). Compatibilidad mejorada con mediciones de potencia retrasadas de enchufes inteligentes y medidores de potencia.",
54
- "pl": "Dodano konfigurowalny limit czasu sprawdzania mocy rozruchowej dla monitorowania pompy (5-10 sekund). Poprawiona kompatybilność z opóźnionymi pomiarami mocy z inteligentnych wtyczek i mierników mocy.",
55
- "uk": "Додано настроюваний тайм-аут перевірки живлення при запуску для моніторингу насоса (5-10 секунд). Покращена сумісність із затримкою вимірювання потужності від розумних розеток і лічильників.",
56
- "zh-cn": "添加了用于泵监控的可配置启动电源检查超时(5-10 秒)。改进了与智能插头和功率计的延迟功率测量的兼容性。"
57
- },
58
- "1.3.27": {
59
- "en": "Added new Chemistry Tools with pH Plus Calculator, pH Minus Calculator and Salt Calculator. Added validation, result texts, error handling and automatic pool volume prefill. Expanded documentation and function overviews.",
60
- "de": "Neuen Bereich Chemistry Tools mit pH-Plus-Rechner, pH-Minus-Rechner und Salz-Rechner hinzugefügt. Validierungen, Ergebnistexte, Fehlerbehandlung und automatische Vorbelegung des Poolvolumens ergänzt. Dokumentation und Funktionsübersichten erweitert.",
61
- "ru": "Добавлены новые химические инструменты с калькулятором pH плюс, калькулятором pH минус и калькулятором соли. Добавлена ​​проверка, тексты результатов, обработка ошибок и автоматическое предварительное заполнение объема пула. Расширенная документация и обзоры функций.",
62
- "pt": "Adicionadas novas ferramentas de química com calculadora pH Plus, calculadora pH menos e calculadora de sal. Adicionados validação, textos de resultados, tratamento de erros e preenchimento automático do volume do pool. Documentação expandida e visões gerais de funções.",
63
- "nl": "Nieuwe chemiehulpmiddelen toegevoegd met pH Plus-calculator, pH-minuscalculator en Zoutcalculator. Validatie, resultaatteksten, foutafhandeling en automatisch vooraf invullen van poolvolumes toegevoegd. Uitgebreide documentatie en functieoverzichten.",
64
- "fr": "Ajout de nouveaux outils de chimie avec calculateur de pH Plus, calculateur de pH Moins et calculateur de sel. Ajout de la validation, des textes de résultats, de la gestion des erreurs et du pré-remplissage automatique du volume du pool. Documentation étendue et aperçus des fonctions.",
65
- "it": "Aggiunti nuovi strumenti di chimica con calcolatore di pH più, calcolatore di pH meno e calcolatore di sale. Aggiunta convalida, testi dei risultati, gestione degli errori e precompilazione automatica del volume del pool. Documentazione estesa e panoramiche delle funzioni.",
66
- "es": "Se agregaron nuevas herramientas de química con calculadora de pH Plus, calculadora de pH Minus y calculadora de sal. Se agregó validación, textos de resultados, manejo de errores y precarga automática del volumen del grupo. Documentación ampliada y descripciones generales de funciones.",
67
- "pl": "Dodano nowe narzędzia chemiczne z kalkulatorem pH Plus, kalkulatorem pH Minus i kalkulatorem soli. Dodano weryfikację, teksty wyników, obsługę błędów i automatyczne wstępne wypełnianie objętości puli. Rozszerzona dokumentacja i przeglądy funkcji.",
68
- "uk": "Додано нові хімічні інструменти з калькулятором pH Plus, калькулятором pH мінус і калькулятором солі. Додано перевірку, тексти результатів, обробку помилок і автоматичне попереднє заповнення обсягу пулу. Розширена документація та огляд функцій.",
69
- "zh-cn": "添加了新的化学工具,包括 pH 加计算器、pH 减计算器和盐计算器。添加了验证、结果文本、错误处理和自动池容量预填充。扩展的文档和功能概述。"
70
70
  }
71
71
  },
72
72
  "titleLang": {
@@ -22,6 +22,8 @@ const runtimeHelper = {
22
22
  resetTimer: null,
23
23
  liveTimer: null, // Timer für Live-Updates
24
24
  syncTimer: null, // FIX: Timer zur Selbstheilung bei verpasstem Pumpenstart/-stopp
25
+ lastPlausibilityDailyTotal: null,
26
+ lastPlausibilityCheckTs: null,
25
27
 
26
28
  /**
27
29
  * Initialisiert den Runtime-Helper.
@@ -236,9 +238,21 @@ const runtimeHelper = {
236
238
 
237
239
  // Umwälzmenge berechnen
238
240
  // Reeller Durchflusswert aus pump.live.flow_current_lh
239
- const liveFlowLh = (await this.adapter.getStateAsync('pump.live.flow_current_lh'))?.val || 0;
241
+ const liveFlowLh = Number((await this.adapter.getStateAsync('pump.live.flow_current_lh'))?.val || 0);
242
+
243
+ // Bestehende Werte für Total/Remaining laden
244
+ const oldTotal = Number((await this.adapter.getStateAsync('circulation.daily_total'))?.val || 0);
245
+ const oldRemaining = Number((await this.adapter.getStateAsync('circulation.daily_remaining'))?.val || 0);
240
246
 
241
247
  if (liveFlowLh <= 0) {
248
+ await this._updateCirculationPlausibility({
249
+ dailyTotal: oldTotal,
250
+ oldTotal,
251
+ liveFlowLh,
252
+ dailyRequired,
253
+ effectiveToday,
254
+ currentSessionSeconds,
255
+ });
242
256
  this.adapter.log.debug('[runtimeHelper] No live flow value available, calculation skipped');
243
257
  return;
244
258
  }
@@ -247,9 +261,14 @@ const runtimeHelper = {
247
261
  const dailyTotal = Math.round((effectiveToday / 3600) * liveFlowLh);
248
262
  const dailyRemaining = Math.max(dailyRequired - dailyTotal, 0);
249
263
 
250
- // Bestehende Werte für Total/Remaining laden
251
- const oldTotal = (await this.adapter.getStateAsync('circulation.daily_total'))?.val || 0;
252
- const oldRemaining = (await this.adapter.getStateAsync('circulation.daily_remaining'))?.val || 0;
264
+ await this._updateCirculationPlausibility({
265
+ dailyTotal,
266
+ oldTotal,
267
+ liveFlowLh,
268
+ dailyRequired,
269
+ effectiveToday,
270
+ currentSessionSeconds,
271
+ });
253
272
 
254
273
  // Nur schreiben, wenn tatsächlich sinnvolle Livewerte vorliegen
255
274
  if (liveFlowLh > 0 && dailyTotal > 0) {
@@ -268,6 +287,152 @@ const runtimeHelper = {
268
287
  }
269
288
  },
270
289
 
290
+ async _updateCirculationPlausibility({
291
+ dailyTotal,
292
+ oldTotal,
293
+ liveFlowLh,
294
+ dailyRequired,
295
+ effectiveToday,
296
+ currentSessionSeconds,
297
+ }) {
298
+ try {
299
+ const nowMs = Date.now();
300
+ const nowIso = new Date(nowMs).toISOString();
301
+ const readNumber = async id => {
302
+ const value = Number((await this.adapter.getStateAsync(id))?.val);
303
+ return Number.isFinite(value) ? value : 0;
304
+ };
305
+ const write = (id, val) => this.adapter.setStateAsync(`circulation.plausibility.${id}`, { val, ack: true });
306
+
307
+ const enabledState = await this.adapter.getStateAsync('circulation.plausibility.000_enabled');
308
+ const plausibilityEnabled = enabledState?.val === false ? false : true;
309
+
310
+ const currentPower = await readNumber('pump.current_power');
311
+ const pumpMaxWatt = await readNumber('pump.pump_max_watt');
312
+ const pumpPowerLph = await readNumber('pump.pump_power_lph');
313
+ const flowValue = Number.isFinite(Number(liveFlowLh)) ? Number(liveFlowLh) : 0;
314
+ const flowAvailable = flowValue > 0;
315
+ const currentTotal = Number.isFinite(Number(dailyTotal)) ? Number(dailyTotal) : 0;
316
+ const previousTotal =
317
+ this.lastPlausibilityDailyTotal === null ? Number(oldTotal) || 0 : this.lastPlausibilityDailyTotal;
318
+
319
+ if (!plausibilityEnabled) {
320
+ await write('00_status', 'disabled');
321
+ await write('01_level', 'info');
322
+ await write('02_message_key', 'circulation_plausibility_disabled');
323
+ await write('03_last_update', nowIso);
324
+ await write('10_power_warning', false);
325
+ await write('20_flow_warning', false);
326
+ await write('30_jump_warning', false);
327
+ await write('40_last_daily_total', previousTotal);
328
+ await write('41_current_daily_total', currentTotal);
329
+ await write('42_delta_liters', 0);
330
+ await write('43_elapsed_seconds', 0);
331
+ await write('44_max_plausible_delta_liters', 0);
332
+
333
+ this.lastPlausibilityDailyTotal = currentTotal;
334
+ this.lastPlausibilityCheckTs = nowMs;
335
+ return;
336
+ }
337
+
338
+ const powerLimit = pumpMaxWatt > 0 ? pumpMaxWatt * 1.2 : 0;
339
+ const flowLimit = pumpPowerLph > 0 ? pumpPowerLph * 1.2 : 0;
340
+ let powerWarning = currentPower > 0 && powerLimit > 0 && currentPower > powerLimit;
341
+ let flowWarning = flowAvailable && flowLimit > 0 && flowValue > flowLimit;
342
+
343
+ let elapsedSeconds = 0;
344
+ let deltaLiters = 0;
345
+ let maxPlausibleDelta = 0;
346
+ let jumpWarning = false;
347
+ const hasPreviousCheck = this.lastPlausibilityCheckTs !== null && this.lastPlausibilityDailyTotal !== null;
348
+
349
+ if (hasPreviousCheck) {
350
+ elapsedSeconds = Math.max(0, Math.round((nowMs - this.lastPlausibilityCheckTs) / 1000));
351
+ deltaLiters = Math.max(0, currentTotal - this.lastPlausibilityDailyTotal);
352
+
353
+ if (elapsedSeconds > 0 && elapsedSeconds <= 3600 && pumpPowerLph > 0) {
354
+ maxPlausibleDelta = (pumpPowerLph * 1.5 * elapsedSeconds) / 3600;
355
+ jumpWarning = deltaLiters > maxPlausibleDelta;
356
+ }
357
+ }
358
+
359
+ if (!flowAvailable) {
360
+ flowWarning = false;
361
+ jumpWarning = false;
362
+ }
363
+
364
+ const warningCount = [powerWarning, flowWarning, jumpWarning].filter(Boolean).length;
365
+ let status = 'ok';
366
+ let level = 'ok';
367
+ let messageKey = 'circulation_plausibility_ok';
368
+
369
+ if (warningCount > 0) {
370
+ status = 'warning';
371
+ level = 'warning';
372
+ if (warningCount > 1) {
373
+ messageKey = 'circulation_plausibility_multiple_warnings';
374
+ } else if (powerWarning) {
375
+ messageKey = 'circulation_plausibility_power_warning';
376
+ } else if (flowWarning) {
377
+ messageKey = 'circulation_plausibility_flow_warning';
378
+ } else {
379
+ messageKey = 'circulation_plausibility_daily_total_jump_warning';
380
+ }
381
+ } else if (!flowAvailable) {
382
+ status = 'unchecked';
383
+ level = 'info';
384
+ messageKey = 'circulation_plausibility_no_flow';
385
+ }
386
+
387
+ await write('00_status', status);
388
+ await write('01_level', level);
389
+ await write('02_message_key', messageKey);
390
+ await write('03_last_update', nowIso);
391
+ await write('10_power_warning', powerWarning);
392
+ await write('11_power_value_w', currentPower > 0 ? currentPower : 0);
393
+ await write('12_power_limit_w', powerLimit > 0 ? powerLimit : 0);
394
+ await write('20_flow_warning', flowWarning);
395
+ await write('21_flow_value_lh', flowAvailable ? flowValue : 0);
396
+ await write('22_flow_limit_lh', flowLimit > 0 ? flowLimit : 0);
397
+ await write('24_flow_available', flowAvailable);
398
+ await write('30_jump_warning', jumpWarning);
399
+ await write('31_jump_value_liters', deltaLiters);
400
+ await write('32_jump_limit_liters', maxPlausibleDelta);
401
+ await write('40_last_daily_total', previousTotal);
402
+ await write('41_current_daily_total', currentTotal);
403
+ await write('42_delta_liters', deltaLiters);
404
+ await write('43_elapsed_seconds', elapsedSeconds);
405
+ await write('44_max_plausible_delta_liters', maxPlausibleDelta);
406
+
407
+ if (powerWarning) {
408
+ await write('13_power_warning_at', nowIso);
409
+ }
410
+ if (flowWarning) {
411
+ await write('23_flow_warning_at', nowIso);
412
+ }
413
+ if (jumpWarning) {
414
+ await write('33_jump_warning_at', nowIso);
415
+ }
416
+
417
+ this.lastPlausibilityDailyTotal = currentTotal;
418
+ this.lastPlausibilityCheckTs = nowMs;
419
+
420
+ if (warningCount > 0) {
421
+ this.adapter.log.warn(
422
+ `[runtimeHelper] Circulation plausibility warning: power=${powerWarning}, flow=${flowWarning}, jump=${jumpWarning}, dailyTotal=${currentTotal}, delta=${deltaLiters}, maxDelta=${maxPlausibleDelta}`,
423
+ );
424
+ } else {
425
+ this.adapter.log.debug(
426
+ `[runtimeHelper] Circulation plausibility updated (status=${status}, dailyTotal=${currentTotal}, flow=${flowValue}, required=${dailyRequired}, effectiveToday=${effectiveToday}, currentSession=${currentSessionSeconds})`,
427
+ );
428
+ }
429
+ } catch (err) {
430
+ this.adapter.log.warn(
431
+ `[runtimeHelper] Error while updating circulation plausibility states: ${err.message}`,
432
+ );
433
+ }
434
+ },
435
+
271
436
  _formatTime(seconds) {
272
437
  seconds = Math.max(0, Math.floor(seconds));
273
438
  const h = Math.floor(seconds / 3600);
@@ -351,6 +516,17 @@ const runtimeHelper = {
351
516
  this.runtimeToday = 0;
352
517
  this.startCountToday = 0;
353
518
  this.lastOn = this.isRunning ? Date.now() : null;
519
+ this.lastPlausibilityDailyTotal = 0;
520
+ this.lastPlausibilityCheckTs = Date.now();
521
+
522
+ await this.adapter.setStateAsync('circulation.plausibility.40_last_daily_total', { val: 0, ack: true });
523
+ await this.adapter.setStateAsync('circulation.plausibility.41_current_daily_total', { val: 0, ack: true });
524
+ await this.adapter.setStateAsync('circulation.plausibility.42_delta_liters', { val: 0, ack: true });
525
+ await this.adapter.setStateAsync('circulation.plausibility.43_elapsed_seconds', { val: 0, ack: true });
526
+ await this.adapter.setStateAsync('circulation.plausibility.44_max_plausible_delta_liters', {
527
+ val: 0,
528
+ ack: true,
529
+ });
354
530
 
355
531
  // Laufzeiten zurücksetzen
356
532
  await this._updateStates();
@@ -69,6 +69,35 @@ const solarExtendedHelper = {
69
69
  const isTimePriority = activeHelper === 'timeHelper';
70
70
  const actorConfigOk = controlObjectId !== '' && (controlType === 'boolean' || controlType === 'socket');
71
71
 
72
+ const poolReferenceStateId =
73
+ poolTemperatureSource === 'ground'
74
+ ? 'temperature.ground.current'
75
+ : poolTemperatureSource === 'surface'
76
+ ? 'temperature.surface.current'
77
+ : '';
78
+ const collectorDeltaState = await this.adapter.getStateAsync('temperature.collector.current');
79
+ const poolReferenceDeltaState = poolReferenceStateId
80
+ ? await this.adapter.getStateAsync(poolReferenceStateId)
81
+ : null;
82
+ const collectorDeltaValue = collectorDeltaState?.val;
83
+ const poolReferenceDeltaValue = poolReferenceDeltaState?.val;
84
+ const collectorDeltaNumber = Number(collectorDeltaValue);
85
+ const poolReferenceDeltaNumber = Number(poolReferenceDeltaValue);
86
+ const extendedDeltaValid =
87
+ collectorDeltaValue !== null &&
88
+ collectorDeltaValue !== undefined &&
89
+ collectorDeltaValue !== '' &&
90
+ poolReferenceDeltaValue !== null &&
91
+ poolReferenceDeltaValue !== undefined &&
92
+ poolReferenceDeltaValue !== '' &&
93
+ Number.isFinite(collectorDeltaNumber) &&
94
+ Number.isFinite(poolReferenceDeltaNumber);
95
+
96
+ await this.adapter.setStateChangedAsync('solar.extended.collector_pool_reference_delta', {
97
+ val: extendedDeltaValid ? Number((collectorDeltaNumber - poolReferenceDeltaNumber).toFixed(2)) : null,
98
+ ack: true,
99
+ });
100
+
72
101
  let configOk = false;
73
102
  let requestActive = false;
74
103
  let active = false;
@@ -71,8 +71,26 @@ const solarHelper = {
71
71
  const hysteresis = (await this.adapter.getStateAsync('solar.hysteresis_active'))?.val;
72
72
 
73
73
  // Temperaturen laden
74
- const collector = Number((await this.adapter.getStateAsync('temperature.collector.current'))?.val);
75
- const pool = Number((await this.adapter.getStateAsync('temperature.surface.current'))?.val); // Oberfläche = Pooltemp
74
+ const collectorState = await this.adapter.getStateAsync('temperature.collector.current');
75
+ const poolState = await this.adapter.getStateAsync('temperature.surface.current');
76
+ const collectorValue = collectorState?.val;
77
+ const poolValue = poolState?.val;
78
+ const collector = Number(collectorValue);
79
+ const pool = Number(poolValue); // Oberfläche = Pooltemp
80
+ const solarDeltaValid =
81
+ collectorValue !== null &&
82
+ collectorValue !== undefined &&
83
+ collectorValue !== '' &&
84
+ poolValue !== null &&
85
+ poolValue !== undefined &&
86
+ poolValue !== '' &&
87
+ Number.isFinite(collector) &&
88
+ Number.isFinite(pool);
89
+
90
+ await this.adapter.setStateChangedAsync('solar.collector_surface_delta', {
91
+ val: solarDeltaValid ? Number((collector - pool).toFixed(2)) : null,
92
+ ack: true,
93
+ });
76
94
 
77
95
  // NEU: Absicherung gegen ungültige Werte
78
96
  if (isNaN(collector) || isNaN(pool)) {
package/lib/i18n/de.json CHANGED
@@ -372,5 +372,14 @@
372
372
  "pool_insights_observation_pv_runtime_today": "PV-Unterstützung lief heute {minutes} Minuten.",
373
373
  "pool_insights_observation_ph_evaluation_available": "Eine pH-Bewertung ist verfügbar.",
374
374
  "pool_insights_observation_tds_evaluation_available": "Eine TDS-Bewertung ist verfügbar.",
375
- "pool_insights_observation_orp_evaluation_available": "Eine ORP-Bewertung ist verfügbar."
375
+ "pool_insights_observation_orp_evaluation_available": "Eine ORP-Bewertung ist verfügbar.",
376
+
377
+ "circulation_plausibility_initializing": "Die Plausibilitätsprüfung der Umwälzberechnung wird initialisiert.",
378
+ "circulation_plausibility_ok": "Die Plausibilitätsprüfung der Umwälzberechnung ist in Ordnung.",
379
+ "circulation_plausibility_no_flow": "Für die Umwälzberechnung ist kein gültiger Live-Durchflusswert verfügbar.",
380
+ "circulation_plausibility_power_warning": "Die Pumpenleistung ist im Verhältnis zur konfigurierten Maximalleistung unplausibel hoch.",
381
+ "circulation_plausibility_flow_warning": "Der berechnete Durchfluss ist im Verhältnis zur konfigurierten Nennförderleistung unplausibel hoch.",
382
+ "circulation_plausibility_daily_total_jump_warning": "Das Tagesumwälzvolumen ist schneller gestiegen als physikalisch plausibel.",
383
+ "circulation_plausibility_multiple_warnings": "Mehrere Plausibilitätswarnungen zur Umwälzberechnung sind aktiv.",
384
+ "circulation_plausibility_disabled": "Die Plausibilitätsprüfung der Umwälzberechnung ist deaktiviert."
376
385
  }
package/lib/i18n/en.json CHANGED
@@ -399,5 +399,14 @@
399
399
  "pool_insights_observation_pv_runtime_today": "PV support ran for {minutes} minutes today.",
400
400
  "pool_insights_observation_ph_evaluation_available": "A pH evaluation is available.",
401
401
  "pool_insights_observation_tds_evaluation_available": "A TDS evaluation is available.",
402
- "pool_insights_observation_orp_evaluation_available": "An ORP evaluation is available."
402
+ "pool_insights_observation_orp_evaluation_available": "An ORP evaluation is available.",
403
+
404
+ "circulation_plausibility_initializing": "Circulation plausibility check is initializing.",
405
+ "circulation_plausibility_ok": "Circulation plausibility check is OK.",
406
+ "circulation_plausibility_no_flow": "No valid live flow value is available for the circulation calculation.",
407
+ "circulation_plausibility_power_warning": "Pump power is implausibly high compared to the configured maximum power.",
408
+ "circulation_plausibility_flow_warning": "Calculated flow rate is implausibly high compared to the configured nominal flow.",
409
+ "circulation_plausibility_daily_total_jump_warning": "Daily circulation volume increased faster than physically plausible.",
410
+ "circulation_plausibility_multiple_warnings": "Multiple circulation plausibility warnings are active.",
411
+ "circulation_plausibility_disabled": "Circulation plausibility check is disabled."
403
412
  }
package/lib/i18n/es.json CHANGED
@@ -395,5 +395,15 @@
395
395
  "pool_insights_observation_pv_runtime_today": "La asistencia PV funcionó hoy durante {minutes} minutos.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Hay una evaluación de pH disponible.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Hay una evaluación de TDS disponible.",
398
- "pool_insights_observation_orp_evaluation_available": "Hay una evaluación de ORP disponible."
398
+ "pool_insights_observation_orp_evaluation_available": "Hay una evaluación de ORP disponible.",
399
+
400
+ "circulation_plausibility_initializing": "La comprobación de plausibilidad de la circulación se está inicializando.",
401
+ "circulation_plausibility_ok": "La comprobación de plausibilidad de la circulación es correcta.",
402
+ "circulation_plausibility_no_flow": "No hay un valor válido de caudal disponible para el cálculo de la circulación.",
403
+ "circulation_plausibility_power_warning": "La potencia de la bomba es excesiva en relación con la potencia máxima configurada.",
404
+ "circulation_plausibility_flow_warning": "El caudal calculado es excesivo en relación con el caudal nominal configurado.",
405
+ "circulation_plausibility_daily_total_jump_warning": "El volumen diario de circulación ha aumentado más rápido de lo físicamente plausible.",
406
+ "circulation_plausibility_multiple_warnings": "Hay varias advertencias de plausibilidad de circulación activas.",
407
+ "circulation_plausibility_disabled": "La comprobación de plausibilidad de la circulación está desactivada."
399
408
  }
409
+
package/lib/i18n/fr.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "L’assistance PV a fonctionné pendant {minutes} minutes aujourd’hui.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Une évaluation du pH est disponible.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Une évaluation TDS est disponible.",
398
- "pool_insights_observation_orp_evaluation_available": "Une évaluation ORP est disponible."
398
+ "pool_insights_observation_orp_evaluation_available": "Une évaluation ORP est disponible.",
399
+
400
+ "circulation_plausibility_initializing": "La vérification de plausibilité de la circulation est en cours d'initialisation.",
401
+ "circulation_plausibility_ok": "La vérification de plausibilité de la circulation est correcte.",
402
+ "circulation_plausibility_no_flow": "Aucune valeur de débit valide n'est disponible pour le calcul de circulation.",
403
+ "circulation_plausibility_power_warning": "La puissance de la pompe est anormalement élevée par rapport à la puissance maximale configurée.",
404
+ "circulation_plausibility_flow_warning": "Le débit calculé est anormalement élevé par rapport au débit nominal configuré.",
405
+ "circulation_plausibility_daily_total_jump_warning": "Le volume quotidien de circulation a augmenté plus rapidement que physiquement plausible.",
406
+ "circulation_plausibility_multiple_warnings": "Plusieurs avertissements de plausibilité de circulation sont actifs.",
407
+ "circulation_plausibility_disabled": "La vérification de plausibilité de la circulation est désactivée."
399
408
  }
package/lib/i18n/it.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "Il supporto PV ha funzionato oggi per {minutes} minuti.",
396
396
  "pool_insights_observation_ph_evaluation_available": "È disponibile una valutazione pH.",
397
397
  "pool_insights_observation_tds_evaluation_available": "È disponibile una valutazione TDS.",
398
- "pool_insights_observation_orp_evaluation_available": "È disponibile una valutazione ORP."
398
+ "pool_insights_observation_orp_evaluation_available": "È disponibile una valutazione ORP.",
399
+
400
+ "circulation_plausibility_initializing": "Il controllo di plausibilità della circolazione è in fase di inizializzazione.",
401
+ "circulation_plausibility_ok": "Il controllo di plausibilità della circolazione è corretto.",
402
+ "circulation_plausibility_no_flow": "Non è disponibile un valore di flusso valido per il calcolo della circolazione.",
403
+ "circulation_plausibility_power_warning": "La potenza della pompa è eccessivamente alta rispetto alla potenza massima configurata.",
404
+ "circulation_plausibility_flow_warning": "La portata calcolata è eccessivamente alta rispetto alla portata nominale configurata.",
405
+ "circulation_plausibility_daily_total_jump_warning": "Il volume giornaliero di circolazione è aumentato più velocemente di quanto fisicamente plausibile.",
406
+ "circulation_plausibility_multiple_warnings": "Sono attivi più avvisi di plausibilità della circolazione.",
407
+ "circulation_plausibility_disabled": "Il controllo di plausibilità della circolazione è disattivato."
399
408
  }
package/lib/i18n/nl.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "PV-ondersteuning liep vandaag {minutes} minuten.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Er is een pH-beoordeling beschikbaar.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Er is een TDS-beoordeling beschikbaar.",
398
- "pool_insights_observation_orp_evaluation_available": "Er is een ORP-beoordeling beschikbaar."
398
+ "pool_insights_observation_orp_evaluation_available": "Er is een ORP-beoordeling beschikbaar.",
399
+
400
+ "circulation_plausibility_initializing": "De plausibiliteitscontrole van de circulatie wordt geïnitialiseerd.",
401
+ "circulation_plausibility_ok": "De plausibiliteitscontrole van de circulatie is in orde.",
402
+ "circulation_plausibility_no_flow": "Er is geen geldige debietwaarde beschikbaar voor de circulatieberekening.",
403
+ "circulation_plausibility_power_warning": "Het pompvermogen is onwaarschijnlijk hoog ten opzichte van het ingestelde maximale vermogen.",
404
+ "circulation_plausibility_flow_warning": "Het berekende debiet is onwaarschijnlijk hoog ten opzichte van het ingestelde nominale debiet.",
405
+ "circulation_plausibility_daily_total_jump_warning": "Het dagelijkse circulatievolume is sneller gestegen dan fysiek plausibel.",
406
+ "circulation_plausibility_multiple_warnings": "Er zijn meerdere waarschuwingen voor circulatie-plausibiliteit actief.",
407
+ "circulation_plausibility_disabled": "De plausibiliteitscontrole van de circulatie is uitgeschakeld."
399
408
  }
package/lib/i18n/pl.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "Wsparcie PV działało dziś przez {minutes} minut.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Dostępna jest ocena pH.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Dostępna jest ocena TDS.",
398
- "pool_insights_observation_orp_evaluation_available": "Dostępna jest ocena ORP."
398
+ "pool_insights_observation_orp_evaluation_available": "Dostępna jest ocena ORP.",
399
+
400
+ "circulation_plausibility_initializing": "Trwa inicjalizacja kontroli wiarygodności obiegu.",
401
+ "circulation_plausibility_ok": "Kontrola wiarygodności obiegu jest prawidłowa.",
402
+ "circulation_plausibility_no_flow": "Brak prawidłowej wartości przepływu dla obliczeń obiegu.",
403
+ "circulation_plausibility_power_warning": "Moc pompy jest nienaturalnie wysoka względem skonfigurowanej mocy maksymalnej.",
404
+ "circulation_plausibility_flow_warning": "Obliczony przepływ jest nienaturalnie wysoki względem skonfigurowanego przepływu nominalnego.",
405
+ "circulation_plausibility_daily_total_jump_warning": "Dzienna objętość obiegu wzrosła szybciej niż jest to fizycznie możliwe.",
406
+ "circulation_plausibility_multiple_warnings": "Aktywnych jest kilka ostrzeżeń dotyczących wiarygodności obiegu.",
407
+ "circulation_plausibility_disabled": "Kontrola wiarygodności obiegu jest wyłączona."
399
408
  }
package/lib/i18n/pt.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "O apoio PV funcionou hoje durante {minutes} minutos.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Está disponível uma avaliação de pH.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Está disponível uma avaliação TDS.",
398
- "pool_insights_observation_orp_evaluation_available": "Está disponível uma avaliação ORP."
398
+ "pool_insights_observation_orp_evaluation_available": "Está disponível uma avaliação ORP.",
399
+
400
+ "circulation_plausibility_initializing": "A verificação de plausibilidade da circulação está a ser inicializada.",
401
+ "circulation_plausibility_ok": "A verificação de plausibilidade da circulação está correta.",
402
+ "circulation_plausibility_no_flow": "Não existe um valor de caudal válido para o cálculo da circulação.",
403
+ "circulation_plausibility_power_warning": "A potência da bomba é excessivamente elevada em relação à potência máxima configurada.",
404
+ "circulation_plausibility_flow_warning": "O caudal calculado é excessivamente elevado em relação ao caudal nominal configurado.",
405
+ "circulation_plausibility_daily_total_jump_warning": "O volume diário de circulação aumentou mais rapidamente do que seria fisicamente plausível.",
406
+ "circulation_plausibility_multiple_warnings": "Existem vários avisos de plausibilidade da circulação ativos.",
407
+ "circulation_plausibility_disabled": "A verificação de plausibilidade da circulação está desativada."
399
408
  }
package/lib/i18n/ru.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "Поддержка PV сегодня работала {minutes} минут.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Доступна оценка pH.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Доступна оценка TDS.",
398
- "pool_insights_observation_orp_evaluation_available": "Доступна оценка ORP."
398
+ "pool_insights_observation_orp_evaluation_available": "Доступна оценка ORP.",
399
+
400
+ "circulation_plausibility_initializing": "Инициализируется проверка достоверности циркуляции.",
401
+ "circulation_plausibility_ok": "Проверка достоверности циркуляции выполнена успешно.",
402
+ "circulation_plausibility_no_flow": "Нет допустимого значения потока для расчёта циркуляции.",
403
+ "circulation_plausibility_power_warning": "Мощность насоса слишком велика по сравнению с настроенной максимальной мощностью.",
404
+ "circulation_plausibility_flow_warning": "Расчётный поток слишком велик по сравнению с настроенным номинальным потоком.",
405
+ "circulation_plausibility_daily_total_jump_warning": "Суточный объём циркуляции увеличился быстрее, чем это физически возможно.",
406
+ "circulation_plausibility_multiple_warnings": "Активны несколько предупреждений проверки достоверности циркуляции.",
407
+ "circulation_plausibility_disabled": "Проверка достоверности циркуляции отключена."
399
408
  }
package/lib/i18n/uk.json CHANGED
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "Підтримка PV сьогодні працювала {minutes} хвилин.",
396
396
  "pool_insights_observation_ph_evaluation_available": "Доступна оцінка pH.",
397
397
  "pool_insights_observation_tds_evaluation_available": "Доступна оцінка TDS.",
398
- "pool_insights_observation_orp_evaluation_available": "Доступна оцінка ORP."
398
+ "pool_insights_observation_orp_evaluation_available": "Доступна оцінка ORP.",
399
+
400
+ "circulation_plausibility_initializing": "Ініціалізується перевірка правдоподібності циркуляції.",
401
+ "circulation_plausibility_ok": "Перевірка правдоподібності циркуляції успішна.",
402
+ "circulation_plausibility_no_flow": "Відсутнє коректне значення потоку для розрахунку циркуляції.",
403
+ "circulation_plausibility_power_warning": "Потужність насоса надто висока відносно налаштованої максимальної потужності.",
404
+ "circulation_plausibility_flow_warning": "Розрахований потік надто високий відносно налаштованого номінального потоку.",
405
+ "circulation_plausibility_daily_total_jump_warning": "Добовий обсяг циркуляції збільшився швидше, ніж це фізично можливо.",
406
+ "circulation_plausibility_multiple_warnings": "Активні кілька попереджень перевірки правдоподібності циркуляції.",
407
+ "circulation_plausibility_disabled": "Перевірку правдоподібності циркуляції вимкнено."
399
408
  }
@@ -395,5 +395,14 @@
395
395
  "pool_insights_observation_pv_runtime_today": "今天 PV 支持运行了 {minutes} 分钟。",
396
396
  "pool_insights_observation_ph_evaluation_available": "已有 pH 评估。",
397
397
  "pool_insights_observation_tds_evaluation_available": "已有 TDS 评估。",
398
- "pool_insights_observation_orp_evaluation_available": "已有 ORP 评估。"
398
+ "pool_insights_observation_orp_evaluation_available": "已有 ORP 评估。",
399
+
400
+ "circulation_plausibility_initializing": "循环合理性检查正在初始化。",
401
+ "circulation_plausibility_ok": "循环合理性检查正常。",
402
+ "circulation_plausibility_no_flow": "没有可用于循环计算的有效流量值。",
403
+ "circulation_plausibility_power_warning": "泵功率相对于配置的最大功率异常偏高。",
404
+ "circulation_plausibility_flow_warning": "计算出的流量相对于配置的额定流量异常偏高。",
405
+ "circulation_plausibility_daily_total_jump_warning": "每日循环量增长速度超过物理合理范围。",
406
+ "circulation_plausibility_multiple_warnings": "存在多个循环合理性警告。",
407
+ "circulation_plausibility_disabled": "循环合理性检查已禁用。"
399
408
  }
@@ -14,6 +14,7 @@
14
14
  * - circulation.daily_total
15
15
  * - circulation.daily_required
16
16
  * - circulation.daily_remaining
17
+ * - circulation.plausibility.*
17
18
  *
18
19
  * States sind persistent - behalten Werte über Neustart
19
20
  *
@@ -341,6 +342,313 @@ async function createRuntimeStates(adapter) {
341
342
  },
342
343
  native: {},
343
344
  });
345
+
346
+ // -------------------------------------------------------------------------
347
+ // --- Plausibility check for circulation calculation ---
348
+ await adapter.setObjectNotExistsAsync('circulation.plausibility', {
349
+ type: 'channel',
350
+ common: {
351
+ name: {
352
+ en: 'Plausibility check for circulation calculation',
353
+ de: 'Plausibilitätsprüfung der Umwälzberechnung',
354
+ },
355
+ },
356
+ native: {},
357
+ });
358
+
359
+ const plausibilityStates = [
360
+ {
361
+ id: '000_enabled',
362
+ type: 'boolean',
363
+ role: 'switch',
364
+ write: true,
365
+ def: true,
366
+ name: { en: 'Enable plausibility check', de: 'Plausibilitätsprüfung aktivieren' },
367
+ desc: {
368
+ en: 'Enables or disables the circulation plausibility check.',
369
+ de: 'Aktiviert oder deaktiviert die Plausibilitätsprüfung der Umwälzberechnung.',
370
+ },
371
+ },
372
+ {
373
+ id: '00_status',
374
+ type: 'string',
375
+ role: 'text',
376
+ def: 'unchecked',
377
+ name: { en: 'Plausibility check status', de: 'Status der Plausibilitätsprüfung' },
378
+ desc: {
379
+ en: 'Current status of the circulation plausibility check',
380
+ de: 'Aktueller Status der Plausibilitätsprüfung für die Umwälzberechnung',
381
+ },
382
+ },
383
+ {
384
+ id: '01_level',
385
+ type: 'string',
386
+ role: 'text',
387
+ def: 'info',
388
+ states: { ok: 'ok', info: 'info', warning: 'warning' },
389
+ name: { en: 'Plausibility check level', de: 'Bewertungsstufe der Plausibilitätsprüfung' },
390
+ desc: {
391
+ en: 'Severity level of the circulation plausibility check',
392
+ de: 'Bewertungsstufe der Plausibilitätsprüfung für die Umwälzberechnung',
393
+ },
394
+ },
395
+ {
396
+ id: '02_message_key',
397
+ type: 'string',
398
+ role: 'text',
399
+ def: 'circulation_plausibility_initializing',
400
+ name: { en: 'Plausibility message key', de: 'Meldungsschlüssel der Plausibilitätsprüfung' },
401
+ desc: {
402
+ en: 'Technical message key for the current plausibility result',
403
+ de: 'Technischer Meldungsschlüssel für das aktuelle Plausibilitätsergebnis',
404
+ },
405
+ },
406
+ {
407
+ id: '03_last_update',
408
+ type: 'string',
409
+ role: 'date',
410
+ def: '',
411
+ name: { en: 'Last plausibility check', de: 'Letzte Plausibilitätsprüfung' },
412
+ desc: {
413
+ en: 'Timestamp of the last circulation plausibility check',
414
+ de: 'Zeitpunkt der letzten Plausibilitätsprüfung der Umwälzberechnung',
415
+ },
416
+ },
417
+ {
418
+ id: '10_power_warning',
419
+ type: 'boolean',
420
+ role: 'indicator',
421
+ def: false,
422
+ name: { en: 'Power warning', de: 'Warnung bei Pumpenleistung' },
423
+ desc: {
424
+ en: 'Indicates that the current pump power is implausibly high compared to the configured maximum power',
425
+ de: 'Zeigt an, dass die aktuelle Pumpenleistung im Verhältnis zur konfigurierten Maximalleistung unplausibel hoch ist',
426
+ },
427
+ },
428
+ {
429
+ id: '11_power_value_w',
430
+ type: 'number',
431
+ role: 'value.power',
432
+ unit: 'W',
433
+ def: 0,
434
+ name: { en: 'Measured pump power', de: 'Gemessene Pumpenleistung' },
435
+ desc: {
436
+ en: 'Pump power value used during the last plausibility warning or check',
437
+ de: 'Pumpenleistungswert, der bei der letzten Plausibilitätswarnung oder Prüfung verwendet wurde',
438
+ },
439
+ },
440
+ {
441
+ id: '12_power_limit_w',
442
+ type: 'number',
443
+ role: 'value.power',
444
+ unit: 'W',
445
+ def: 0,
446
+ name: { en: 'Pump power warning limit', de: 'Warngrenze der Pumpenleistung' },
447
+ desc: {
448
+ en: 'Calculated warning limit for the pump power',
449
+ de: 'Berechnete Warngrenze für die Pumpenleistung',
450
+ },
451
+ },
452
+ {
453
+ id: '13_power_warning_at',
454
+ type: 'string',
455
+ role: 'date',
456
+ def: '',
457
+ name: { en: 'Power warning timestamp', de: 'Zeitpunkt der Pumpenleistungswarnung' },
458
+ desc: {
459
+ en: 'Timestamp of the last pump power plausibility warning',
460
+ de: 'Zeitpunkt der letzten Plausibilitätswarnung zur Pumpenleistung',
461
+ },
462
+ },
463
+ {
464
+ id: '20_flow_warning',
465
+ type: 'boolean',
466
+ role: 'indicator',
467
+ def: false,
468
+ name: { en: 'Flow warning', de: 'Warnung bei Durchfluss' },
469
+ desc: {
470
+ en: 'Indicates that the calculated flow rate is implausibly high compared to the configured nominal flow',
471
+ de: 'Zeigt an, dass der berechnete Durchfluss im Verhältnis zur konfigurierten Nennförderleistung unplausibel hoch ist',
472
+ },
473
+ },
474
+ {
475
+ id: '21_flow_value_lh',
476
+ type: 'number',
477
+ role: 'value',
478
+ unit: 'l/h',
479
+ def: 0,
480
+ name: { en: 'Calculated flow rate', de: 'Berechneter Durchfluss' },
481
+ desc: {
482
+ en: 'Flow rate value used during the last plausibility warning or check',
483
+ de: 'Durchflusswert, der bei der letzten Plausibilitätswarnung oder Prüfung verwendet wurde',
484
+ },
485
+ },
486
+ {
487
+ id: '22_flow_limit_lh',
488
+ type: 'number',
489
+ role: 'value',
490
+ unit: 'l/h',
491
+ def: 0,
492
+ name: { en: 'Flow warning limit', de: 'Warngrenze des Durchflusses' },
493
+ desc: {
494
+ en: 'Calculated warning limit for the flow rate',
495
+ de: 'Berechnete Warngrenze für den Durchfluss',
496
+ },
497
+ },
498
+ {
499
+ id: '23_flow_warning_at',
500
+ type: 'string',
501
+ role: 'date',
502
+ def: '',
503
+ name: { en: 'Flow warning timestamp', de: 'Zeitpunkt der Durchflusswarnung' },
504
+ desc: {
505
+ en: 'Timestamp of the last flow plausibility warning',
506
+ de: 'Zeitpunkt der letzten Plausibilitätswarnung zum Durchfluss',
507
+ },
508
+ },
509
+ {
510
+ id: '24_flow_available',
511
+ type: 'boolean',
512
+ role: 'indicator',
513
+ def: false,
514
+ name: { en: 'Flow value available', de: 'Durchflusswert verfügbar' },
515
+ desc: {
516
+ en: 'Indicates whether a valid live flow value was available for the circulation calculation',
517
+ de: 'Zeigt an, ob ein gültiger Live-Durchflusswert für die Umwälzberechnung verfügbar war',
518
+ },
519
+ },
520
+ {
521
+ id: '30_jump_warning',
522
+ type: 'boolean',
523
+ role: 'indicator',
524
+ def: false,
525
+ name: { en: 'Daily circulation jump warning', de: 'Warnung bei Sprung der Tagesumwälzung' },
526
+ desc: {
527
+ en: 'Indicates that the daily circulation volume increased faster than physically plausible',
528
+ de: 'Zeigt an, dass das Tagesumwälzvolumen schneller gestiegen ist als physikalisch plausibel',
529
+ },
530
+ },
531
+ {
532
+ id: '31_jump_value_liters',
533
+ type: 'number',
534
+ role: 'value.volume',
535
+ unit: 'l',
536
+ def: 0,
537
+ name: { en: 'Daily circulation volume jump', de: 'Sprung des Tagesumwälzvolumens' },
538
+ desc: {
539
+ en: 'Detected increase of the daily circulation volume since the previous plausibility check',
540
+ de: 'Erkannter Anstieg des Tagesumwälzvolumens seit der vorherigen Plausibilitätsprüfung',
541
+ },
542
+ },
543
+ {
544
+ id: '32_jump_limit_liters',
545
+ type: 'number',
546
+ role: 'value.volume',
547
+ unit: 'l',
548
+ def: 0,
549
+ name: { en: 'Maximum plausible volume increase', de: 'Maximal plausibler Volumenzuwachs' },
550
+ desc: {
551
+ en: 'Maximum plausible circulation volume increase for the elapsed time',
552
+ de: 'Maximal plausibler Umwälzvolumen-Zuwachs für die vergangene Zeit',
553
+ },
554
+ },
555
+ {
556
+ id: '33_jump_warning_at',
557
+ type: 'string',
558
+ role: 'date',
559
+ def: '',
560
+ name: { en: 'Daily circulation jump warning timestamp', de: 'Zeitpunkt der Sprungwarnung' },
561
+ desc: {
562
+ en: 'Timestamp of the last implausible daily circulation jump warning',
563
+ de: 'Zeitpunkt der letzten Warnung wegen eines unplausiblen Sprungs der Tagesumwälzung',
564
+ },
565
+ },
566
+ {
567
+ id: '40_last_daily_total',
568
+ type: 'number',
569
+ role: 'value.volume',
570
+ unit: 'l',
571
+ def: 0,
572
+ name: { en: 'Previous daily circulation volume', de: 'Vorheriges Tagesumwälzvolumen' },
573
+ desc: {
574
+ en: 'Daily circulation volume used as previous value for the plausibility check',
575
+ de: 'Tagesumwälzvolumen, das als vorheriger Wert für die Plausibilitätsprüfung verwendet wurde',
576
+ },
577
+ },
578
+ {
579
+ id: '41_current_daily_total',
580
+ type: 'number',
581
+ role: 'value.volume',
582
+ unit: 'l',
583
+ def: 0,
584
+ name: { en: 'Current daily circulation volume', de: 'Aktuelles Tagesumwälzvolumen' },
585
+ desc: {
586
+ en: 'Current daily circulation volume used for the plausibility check',
587
+ de: 'Aktuelles Tagesumwälzvolumen, das für die Plausibilitätsprüfung verwendet wurde',
588
+ },
589
+ },
590
+ {
591
+ id: '42_delta_liters',
592
+ type: 'number',
593
+ role: 'value.volume',
594
+ unit: 'l',
595
+ def: 0,
596
+ name: { en: 'Daily circulation volume change', de: 'Änderung des Tagesumwälzvolumens' },
597
+ desc: {
598
+ en: 'Difference between current and previous daily circulation volume',
599
+ de: 'Differenz zwischen aktuellem und vorherigem Tagesumwälzvolumen',
600
+ },
601
+ },
602
+ {
603
+ id: '43_elapsed_seconds',
604
+ type: 'number',
605
+ role: 'value',
606
+ unit: 's',
607
+ def: 0,
608
+ name: { en: 'Elapsed time since previous check', de: 'Zeit seit vorheriger Prüfung' },
609
+ desc: {
610
+ en: 'Elapsed time since the previous circulation plausibility check',
611
+ de: 'Vergangene Zeit seit der vorherigen Plausibilitätsprüfung der Umwälzberechnung',
612
+ },
613
+ },
614
+ {
615
+ id: '44_max_plausible_delta_liters',
616
+ type: 'number',
617
+ role: 'value.volume',
618
+ unit: 'l',
619
+ def: 0,
620
+ name: { en: 'Maximum plausible change', de: 'Maximal plausible Änderung' },
621
+ desc: {
622
+ en: 'Maximum plausible daily circulation volume change for the elapsed time',
623
+ de: 'Maximal plausible Änderung des Tagesumwälzvolumens für die vergangene Zeit',
624
+ },
625
+ },
626
+ ];
627
+
628
+ for (const state of plausibilityStates) {
629
+ const id = `circulation.plausibility.${state.id}`;
630
+ await adapter.setObjectNotExistsAsync(id, {
631
+ type: 'state',
632
+ common: {
633
+ name: state.name,
634
+ desc: state.desc,
635
+ type: state.type,
636
+ role: state.role,
637
+ read: true,
638
+ write: state.write === true,
639
+ persist: true,
640
+ def: state.def,
641
+ ...(state.unit ? { unit: state.unit } : {}),
642
+ ...(state.states ? { states: state.states } : {}),
643
+ },
644
+ native: {},
645
+ });
646
+
647
+ const existing = await adapter.getStateAsync(id);
648
+ if (!existing || existing.val === null || existing.val === undefined) {
649
+ await adapter.setStateAsync(id, { val: state.def, ack: true });
650
+ }
651
+ }
344
652
  }
345
653
 
346
654
  module.exports = {
@@ -305,6 +305,28 @@ async function createSolarExtendedStates(adapter) {
305
305
  });
306
306
  }
307
307
 
308
+ await adapter.setObjectNotExistsAsync(`${channelId}.collector_pool_reference_delta`, {
309
+ type: 'state',
310
+ common: {
311
+ name: {
312
+ en: 'Collector-pool reference delta',
313
+ de: 'Delta Kollektor - Poolreferenz',
314
+ },
315
+ desc: {
316
+ en: 'Current temperature difference between collector and the selected pool reference temperature for extended solar control',
317
+ de: 'Aktuelle Temperaturdifferenz zwischen Kollektor und der gewählten Pool-Referenztemperatur der erweiterten Solarsteuerung',
318
+ },
319
+ type: 'number',
320
+ role: 'value.temperature',
321
+ unit: '°C',
322
+ read: true,
323
+ write: false,
324
+ def: null,
325
+ persist: false,
326
+ },
327
+ native: {},
328
+ });
329
+
308
330
  await adapter.setObjectNotExistsAsync(`${channelId}.active`, {
309
331
  type: 'state',
310
332
  common: {
@@ -6,6 +6,7 @@
6
6
  * - solar.hysteresis_active
7
7
  * - solar.temp_on (Einschaltgrenze)
8
8
  * - solar.temp_off (Ausschaltgrenze)
9
+ * - solar.collector_surface_delta
9
10
  * - solar.collector_warning (Warnung aktiv)
10
11
  * - solar.warn_active (Warnlogik aktivieren/deaktivieren)
11
12
  * - solar.warn_temp (Warnschwelle °C)
@@ -196,6 +197,28 @@ async function createSolarStates(adapter) {
196
197
  ack: true,
197
198
  });
198
199
 
200
+ await adapter.setObjectNotExistsAsync('solar.collector_surface_delta', {
201
+ type: 'state',
202
+ common: {
203
+ name: {
204
+ en: 'Collector-surface delta',
205
+ de: 'Delta Kollektor - Oberfläche',
206
+ },
207
+ desc: {
208
+ en: 'Current temperature difference between collector and pool surface temperature',
209
+ de: 'Aktuelle Temperaturdifferenz zwischen Kollektor und Pooloberfläche',
210
+ },
211
+ type: 'number',
212
+ role: 'value.temperature',
213
+ unit: '°C',
214
+ read: true,
215
+ write: false,
216
+ def: null,
217
+ persist: false,
218
+ },
219
+ native: {},
220
+ });
221
+
199
222
  // Warnung Kollektortemperatur aktiv
200
223
  await adapter.setObjectNotExistsAsync('solar.collector_warning', {
201
224
  type: 'state',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "1.3.31",
3
+ "version": "1.3.33",
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",