iobroker.poolcontrol 1.2.18 → 1.2.20

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
@@ -189,6 +189,18 @@ New features are added regularly – please refer to the changelog.
189
189
 
190
190
  ## Changelog
191
191
 
192
+ ### 1.2.20
193
+ Release: 11.04.2026
194
+ - (DasBo) Reduced unnecessary state writes in status and photovoltaic helpers. Summary and PV timestamps are now only updated when the functional result actually changes, making the adapter quieter without affecting existing logic.
195
+
196
+ ### 1.2.19
197
+ Release: 10.04.2026
198
+ - Fixed an interaction issue between `photovoltaicHelper` and `controlHelper` where automatic follow-up pumping could be stopped unexpectedly
199
+ - photovoltaicHelper now respects controlHelper priority and no longer stops the pump while automatic follow-up pumping is active
200
+ - Fixed an issue where `controlHelper` could remain in "nachpumpen" state if the pump was stopped externally
201
+ - `photovoltaic.threshold_w` is now correctly synchronized with the instance configuration
202
+ - Changes to the PV surplus threshold in adapter settings are now reliably reflected in the corresponding read-only datapoint
203
+
192
204
  ### 1.2.18
193
205
  Release: 07.04.2026
194
206
  - Fixed persistence issue for `status.season_active` (no longer overwritten on adapter start)
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "1.2.18",
4
+ "version": "1.2.20",
5
5
  "news": {
6
+ "1.2.20": {
7
+ "en": "Bugfix release. Reduced unnecessary state writes in the status and photovoltaic helpers. Summary timestamps and PV update timestamps are now only written when the related functional result actually changes. This makes the adapter noticeably quieter and avoids needless state updates without changing the existing control logic.",
8
+ "de": "Bugfix-Release. Reduziert unnötige State-Schreibvorgänge im Status- und Photovoltaik-Helper. Summary-Zeitstempel und PV-Aktualisierungszeitstempel werden jetzt nur noch dann geschrieben, wenn sich das zugehörige fachliche Ergebnis tatsächlich ändert. Dadurch arbeitet der Adapter spürbar ruhiger und vermeidet unnötige State-Updates, ohne die bestehende Steuerlogik zu verändern.",
9
+ "ru": "Выпуск с исправлением ошибок. Уменьшено количество ненужных записей в статусе и фотоэлектрических помощниках. Сводные временные метки и временные метки обновления PV теперь записываются только тогда, когда соответствующий функциональный результат действительно изменяется. Это делает адаптер заметно тише и позволяет избежать ненужных обновлений состояния без изменения существующей логики управления.",
10
+ "pt": "Lançamento de correção de bug. Gravações de estado desnecessárias reduzidas nos ajudantes de status e fotovoltaicos. Os carimbos de data e hora de resumo e os carimbos de data e hora de atualização do PV agora são gravados apenas quando o resultado funcional relacionado realmente muda. Isto torna o adaptador visivelmente mais silencioso e evita atualizações de estado desnecessárias sem alterar a lógica de controle existente.",
11
+ "nl": "Bugfix-release. Verminderde onnodige statusschrijven in de status en fotovoltaïsche helpers. Samenvattende tijdstempels en tijdstempels voor PV-updates worden nu alleen geschreven als het gerelateerde functionele resultaat daadwerkelijk verandert. Dit maakt de adapter merkbaar stiller en vermijdt onnodige statusupdates zonder de bestaande besturingslogica te veranderen.",
12
+ "fr": "Version de correction de bugs. Réduction des écritures d'état inutiles dans les aides d'état et photovoltaïques. Les horodatages récapitulatifs et les horodatages de mise à jour PV ne sont désormais écrits que lorsque le résultat fonctionnel associé change réellement. Cela rend l'adaptateur sensiblement plus silencieux et évite les mises à jour d'état inutiles sans modifier la logique de contrôle existante.",
13
+ "it": "Rilascio di correzione bug. Ridotte le scritture di stato non necessarie nello stato e gli aiutanti fotovoltaici. I timestamp di riepilogo e quelli di aggiornamento PV ora vengono scritti solo quando il relativo risultato funzionale cambia effettivamente. Ciò rende l'adattatore notevolmente più silenzioso ed evita aggiornamenti di stato inutili senza modificare la logica di controllo esistente.",
14
+ "es": "Lanzamiento de corrección de errores. Reducción de escrituras de estado innecesarias en el estado y ayudantes fotovoltaicos. Las marcas de tiempo de resumen y las marcas de tiempo de actualización de PV ahora solo se escriben cuando el resultado funcional relacionado realmente cambia. Esto hace que el adaptador sea notablemente más silencioso y evita actualizaciones de estado innecesarias sin cambiar la lógica de control existente.",
15
+ "pl": "Wydanie poprawek błędów. Redukcja zbędnych zapisów stanu w statusie i pomocnikach fotowoltaicznych. Sumaryczne znaczniki czasu i znaczniki czasu aktualizacji PV są teraz zapisywane tylko wtedy, gdy faktycznie zmienia się powiązany wynik funkcjonalny. Dzięki temu adapter jest zauważalnie cichszy i pozwala uniknąć niepotrzebnych aktualizacji stanu bez zmiany istniejącej logiki sterowania.",
16
+ "uk": "Реліз виправлення помилок. Зменшено непотрібні записи стану в статусі та фотоелектричні помічники. Підсумкові мітки часу та мітки часу оновлення PV тепер записуються лише тоді, коли відповідний функціональний результат фактично змінюється. Це робить адаптер помітно тихішим і дозволяє уникнути непотрібних оновлень стану без зміни існуючої логіки керування.",
17
+ "zh-cn": "错误修复版本。减少状态和光伏助手中不必要的状态写入。摘要时间戳和 PV 更新时间戳现在仅在相关功能结果实际更改时写入。这使得适配器明显更安静,并且在不改变现有控制逻辑的情况下避免了不必要的状态更新。"
18
+ },
19
+ "1.2.19": {
20
+ "en": "Bugfix release. Fixes an interaction issue between photovoltaicHelper and controlHelper where automatic follow-up pumping could be interrupted unexpectedly. The photovoltaic stop logic now respects controlHelper priority and no longer stops the pump while automatic follow-up pumping is active. In addition, the read-only state photovoltaic.threshold_w is now synchronized correctly with the instance configuration so that changes in the adapter settings are reflected reliably in the visible datapoint.",
21
+ "de": "Bugfix-Release. Behebt ein Zusammenspielproblem zwischen photovoltaicHelper und controlHelper, durch das automatisches Nachpumpen unerwartet unterbrochen werden konnte. Die Abschaltlogik des PV-Helfers respektiert nun den Vorrang des controlHelper und stoppt die Pumpe nicht mehr, solange automatisches Nachpumpen aktiv ist. Zusätzlich wird der schreibgeschützte Datenpunkt photovoltaic.threshold_w jetzt korrekt mit der Instanzkonfiguration synchronisiert, sodass Änderungen in den Adaptereinstellungen zuverlässig im sichtbaren Datenpunkt übernommen werden.",
22
+ "ru": "Выпуск с исправлением ошибок. Устранена проблема взаимодействия между фотоэлектрическим помощником и controlHelper, из-за которой автоматическая последующая откачка могла неожиданно прерваться. Логика фотоэлектрической остановки теперь учитывает приоритет controlHelper и больше не останавливает насос, пока активна автоматическая последующая откачка. Кроме того, состояние только для чтения photovoltaic.threshold_w теперь правильно синхронизируется с конфигурацией экземпляра, так что изменения в настройках адаптера надежно отражаются в видимой точке данных.",
23
+ "pt": "Lançamento de correção de bug. Corrige um problema de interação entre photovoltaicHelper e controlHelper onde o bombeamento de acompanhamento automático poderia ser interrompido inesperadamente. A lógica de paragem fotovoltaica respeita agora a prioridade controlHelper e já não para a bomba enquanto o bombeamento de acompanhamento automático estiver ativo. Além disso, o estado somente leitura photovoltaic.threshold_w agora está sincronizado corretamente com a configuração da instância para que as alterações nas configurações do adaptador sejam refletidas de forma confiável no ponto de dados visível.",
24
+ "nl": "Bugfix-release. Er is een interactieprobleem opgelost tussen photovoltaicHelper en controlHelper waarbij automatisch napompen onverwacht kon worden onderbroken. De fotovoltaïsche stoplogica respecteert nu de prioriteit van controlHelper en stopt de pomp niet langer terwijl automatisch napompen actief is. Bovendien wordt de alleen-lezen status photovoltaic.threshold_w nu correct gesynchroniseerd met de instanceconfiguratie, zodat wijzigingen in de adapterinstellingen betrouwbaar worden weerspiegeld in het zichtbare datapunt.",
25
+ "fr": "Version de correction de bugs. Corrige un problème d'interaction entre photovoltaicHelper et controlHelper où le pompage de suivi automatique pouvait être interrompu de manière inattendue. La logique d'arrêt photovoltaïque respecte désormais la priorité controlHelper et n'arrête plus la pompe lorsque le pompage de suivi automatique est actif. De plus, l'état en lecture seule photovoltaic.threshold_w est désormais correctement synchronisé avec la configuration de l'instance afin que les modifications apportées aux paramètres de l'adaptateur soient reflétées de manière fiable dans le point de données visible.",
26
+ "it": "Rilascio di correzione bug. Risolve un problema di interazione tra fotovoltaicoHelper e controlHelper in cui il pompaggio automatico di follow-up poteva essere interrotto inaspettatamente. La logica di arresto fotovoltaico ora rispetta la priorità di controlHelper e non arresta più la pompa mentre è attivo il pompaggio di follow-up automatico. Inoltre, lo stato di sola lettura fotovoltaico.threshold_w è ora sincronizzato correttamente con la configurazione dell'istanza in modo che le modifiche nelle impostazioni dell'adattatore si riflettano in modo affidabile nel punto dati visibile.",
27
+ "es": "Lanzamiento de corrección de errores. Soluciona un problema de interacción entre photovoltaicHelper y controlHelper donde el bombeo de seguimiento automático podría interrumpirse inesperadamente. La lógica de parada fotovoltaica ahora respeta la prioridad de controlHelper y ya no detiene la bomba mientras el bombeo de seguimiento automático está activo. Además, el estado de solo lectura photovoltaic.threshold_w ahora está sincronizado correctamente con la configuración de la instancia para que los cambios en la configuración del adaptador se reflejen de manera confiable en el punto de datos visible.",
28
+ "pl": "Wydanie poprawek błędów. Rozwiązuje problem interakcji pomiędzy photovoltaicHelper i controlHelper, powodujący nieoczekiwane przerwanie automatycznego pompowania uzupełniającego. Logika zatrzymania fotowoltaiki uwzględnia teraz priorytet ControlHelper i nie zatrzymuje już pompy, gdy aktywne jest automatyczne pompowanie uzupełniające. Ponadto stan tylko do odczytu photovoltaic.threshold_w jest teraz poprawnie zsynchronizowany z konfiguracją instancji, dzięki czemu zmiany w ustawieniach adaptera są niezawodnie odzwierciedlane w widocznym punkcie danych.",
29
+ "uk": "Реліз виправлення помилок. Вирішує проблему взаємодії між photovoltaicHelper і controlHelper, через яку автоматичне подальше відкачування може бути несподівано перервано. Логіка фотоелектричної зупинки тепер враховує пріоритет controlHelper і більше не зупиняє насос, поки активна автоматична подальша перекачування. Крім того, стан тільки для читання photovoltaic.threshold_w тепер правильно синхронізовано з конфігурацією екземпляра, щоб зміни в налаштуваннях адаптера надійно відображалися у видимій точці даних.",
30
+ "zh-cn": "错误修复版本。修复了 PVHelper 和 controlHelper 之间的交互问题,其中自动后续泵送可能会意外中断。光伏停止逻辑现在尊重 controlHelper 优先级,并且在自动后续泵送处于活动状态时不再停止泵。此外,只读状态 PV.threshold_w 现在已与实例配置正确同步,以便适配器设置中的更改能够可靠地反映在可见数据点中。"
31
+ },
6
32
  "1.2.18": {
7
33
  "en": "Fixed persistence issues for season and frost states. Season_active is now no longer overwritten on adapter start. Frost protection settings are now stored persistently.",
8
34
  "de": "Persistenzprobleme für Saison- und Frost-States behoben. season_active wird beim Adapterstart nicht mehr überschrieben. Frostschutz-Einstellungen werden nun dauerhaft gespeichert.",
@@ -29,19 +55,6 @@
29
55
  "uk": "Виправлення: вирішено проблему, через яку кнопка скидання навчання тиску не спрацьовувала надійно. PumpHelper4 тепер явно підписується на свої відповідні внутрішні стани (наприклад, значення скидання та конфігурації), забезпечуючи правильну обробку подій і негайне виконання логіки скидання.",
30
56
  "zh-cn": "修复:解决了压力学习重置按钮无法可靠触发的问题。 PumpHelper4 现在显式订阅其相关的内部状态(例如重置和配置值),确保正确的事件处理和立即执行重置逻辑。"
31
57
  },
32
- "1.2.16": {
33
- "en": "Fix: Resolved an issue where the pressure learning reset button did not trigger reliably. The pumpHelper4 now explicitly subscribes to its relevant internal states (e.g. reset and configuration values), ensuring proper event handling and immediate execution of the reset logic.",
34
- "de": "Fix: Problem behoben, bei dem der Reset-Button für das Druck-Lernsystem nicht zuverlässig ausgelöst wurde. Der pumpHelper4 abonniert nun explizit die relevanten eigenen States (z. B. Reset und Konfigurationswerte), wodurch die Eventverarbeitung und die sofortige Ausführung der Reset-Logik sichergestellt sind.",
35
- "ru": "Исправление: решена проблема, из-за которой кнопка сброса обучения давлению не срабатывала надежно. PumpHelper4 теперь явно подписывается на соответствующие внутренние состояния (например, значения сброса и конфигурации), обеспечивая правильную обработку событий и немедленное выполнение логики сброса.",
36
- "pt": "Correção: Resolvido um problema em que o botão de redefinição do aprendizado de pressão não acionava de maneira confiável. O pumpHelper4 agora assina explicitamente seus estados internos relevantes (por exemplo, valores de redefinição e configuração), garantindo o tratamento adequado de eventos e a execução imediata da lógica de redefinição.",
37
- "nl": "Oplossing: een probleem opgelost waarbij de resetknop voor het leren van de druk niet betrouwbaar werd geactiveerd. De pumpHelper4 onderschrijft nu expliciet de relevante interne statussen (bijvoorbeeld reset- en configuratiewaarden), waardoor een juiste afhandeling van gebeurtenissen en onmiddellijke uitvoering van de resetlogica wordt gegarandeerd.",
38
- "fr": "Correction : Résolution d'un problème où le bouton de réinitialisation de l'apprentissage de la pression ne se déclenchait pas de manière fiable. Le PumpHelper4 s'abonne désormais explicitement à ses états internes pertinents (par exemple, les valeurs de réinitialisation et de configuration), garantissant une gestion appropriée des événements et l'exécution immédiate de la logique de réinitialisation.",
39
- "it": "Correzione: risolto un problema per cui il pulsante di ripristino dell'apprendimento della pressione non si attivava in modo affidabile. Il pumpHelper4 ora sottoscrive esplicitamente i suoi stati interni rilevanti (ad esempio valori di ripristino e configurazione), garantendo la corretta gestione degli eventi e l'esecuzione immediata della logica di ripristino.",
40
- "es": "Solución: se resolvió un problema por el cual el botón de reinicio del aprendizaje de presión no se activaba de manera confiable. El pumpHelper4 ahora se suscribe explícitamente a sus estados internos relevantes (por ejemplo, valores de reinicio y configuración), lo que garantiza un manejo adecuado de eventos y la ejecución inmediata de la lógica de reinicio.",
41
- "pl": "Poprawka: rozwiązano problem polegający na tym, że przycisk resetowania uczenia się ciśnienia nie uruchamiał się niezawodnie. PumpHelper4 teraz jawnie subskrybuje swoje odpowiednie stany wewnętrzne (np. wartości resetowania i konfiguracji), zapewniając prawidłową obsługę zdarzeń i natychmiastowe wykonanie logiki resetowania.",
42
- "uk": "Виправлення: вирішено проблему, через яку кнопка скидання навчання тиску не спрацьовувала надійно. PumpHelper4 тепер явно підписується на свої відповідні внутрішні стани (наприклад, значення скидання та конфігурації), забезпечуючи правильну обробку подій і негайне виконання логіки скидання.",
43
- "zh-cn": "修复:解决了压力学习重置按钮无法可靠触发的问题。 PumpHelper4 现在显式订阅其相关的内部状态(例如重置和配置值),确保正确的事件处理和立即执行重置逻辑。"
44
- },
45
58
  "1.2.15": {
46
59
  "en": "Fix i18n usage (replace I18n.t with I18n.translate) to resolve adapter startup crash and restart loop on certain systems.",
47
60
  "de": "i18n-Nutzung korrigiert (I18n.t durch I18n.translate ersetzt), um Absturz beim Adapterstart und Restart-Loop auf bestimmten Systemen zu beheben.",
@@ -54,19 +67,6 @@
54
67
  "pl": "Napraw użycie i18n (zamień I18n.t na I18n.translate), aby rozwiązać awarię uruchamiania adaptera i pętlę restartu w niektórych systemach.",
55
68
  "uk": "Виправте використання i18n (замініть I18n.t на I18n.translate), щоб усунути збій запуску адаптера та цикл перезапуску в певних системах.",
56
69
  "zh-cn": "修复 i18n 使用情况(将 I18n.t 替换为 I18n.translate),以解决某些系统上的适配器启动崩溃和重新启动循环问题。"
57
- },
58
- "1.2.14": {
59
- "en": "Add i18n support for chemistry help (common.states and help texts), fix React issues caused by invalid translations, and improve multilingual user guidance.",
60
- "de": "i18n-Unterstützung für Chemie-Hilfe hinzugefügt (common.states und Hilfetexte), React-Fehler durch fehlerhafte Übersetzungen behoben und mehrsprachige Benutzerführung verbessert.",
61
- "ru": "Добавьте поддержку i18n для справки по химии (common.states и справочные тексты), исправьте проблемы React, вызванные неверными переводами, и улучшите многоязычное руководство пользователя.",
62
- "pt": "Adicione suporte i18n para ajuda química (common.states e textos de ajuda), corrija problemas do React causados ​​por traduções inválidas e melhore a orientação multilíngue do usuário.",
63
- "nl": "Voeg i18n-ondersteuning toe voor scheikundige hulp (common.states en helpteksten), repareer React-problemen veroorzaakt door ongeldige vertalingen en verbeter de meertalige gebruikersbegeleiding.",
64
- "fr": "Ajoutez la prise en charge d'i18n pour l'aide chimique (common.states et textes d'aide), corrigez les problèmes de React causés par des traductions non valides et améliorez le guidage utilisateur multilingue.",
65
- "it": "Aggiungi il supporto i18n per la guida in chimica (common.states e testi di aiuto), risolvi i problemi di React causati da traduzioni non valide e migliora la guida utente multilingue.",
66
- "es": "Agregue soporte i18n para ayuda sobre química (estados comunes y textos de ayuda), solucione problemas de React causados ​​por traducciones no válidas y mejore la guía del usuario multilingüe.",
67
- "pl": "Dodaj obsługę i18n dla pomocy chemicznej (stany wspólne i teksty pomocy), rozwiąż problemy z React spowodowane nieprawidłowymi tłumaczeniami i ulepsz wielojęzyczne wskazówki dla użytkownika.",
68
- "uk": "Додайте підтримку i18n для довідки з хімії (common.states і тексти довідки), виправте проблеми з React, викликані недійсними перекладами, і покращте багатомовні інструкції для користувачів.",
69
- "zh-cn": "添加对化学帮助(common.states 和帮助文本)的 i18n 支持,修复无效翻译导致的 React 问题,并改进多语言用户指南。"
70
70
  }
71
71
  },
72
72
  "titleLang": {
@@ -131,10 +131,17 @@ async function _runDailyCirculationCheck() {
131
131
  }
132
132
  }
133
133
 
134
+ async function _isAutoPumpingStillRunning() {
135
+ const activeHelper = (await adapter.getStateAsync('pump.active_helper'))?.val || '';
136
+ const pumpSwitch = !!(await adapter.getStateAsync('pump.pump_switch'))?.val;
137
+
138
+ return activeHelper === 'controlHelper' && pumpSwitch === true;
139
+ }
140
+
134
141
  /**
135
142
  * Startet automatisches Nachpumpen.
136
143
  *
137
- * @param {number} missingLiter - Fehlende Umwälzmenge in Litern
144
+ * @param {number} missingLiter Fehlende Umwälzmenge in Litern
138
145
  */
139
146
  async function _startAutoPumping(missingLiter) {
140
147
  try {
@@ -160,6 +167,22 @@ async function _startAutoPumping(missingLiter) {
160
167
  const total = Math.round((await adapter.getStateAsync('circulation.daily_total'))?.val || 0);
161
168
  const required = Math.round((await adapter.getStateAsync('circulation.daily_required'))?.val || 0);
162
169
 
170
+ const stillRunning = await _isAutoPumpingStillRunning();
171
+ if (!stillRunning) {
172
+ adapter.clearInterval(autoPumpingInterval);
173
+ autoPumpingInterval = null;
174
+
175
+ adapter.log.warn(
176
+ '[controlHelper] automatic pumping aborted because pump control was lost or pump_switch is no longer true.',
177
+ );
178
+
179
+ await adapter.setStateAsync('pump.mode', { val: previousPumpMode, ack: true });
180
+ await adapter.setStateAsync('pump.active_helper', { val: '', ack: true });
181
+ await adapter.setStateAsync('pump.reason', { val: '', ack: true });
182
+ previousPumpMode = null;
183
+ return;
184
+ }
185
+
163
186
  if (total >= required) {
164
187
  adapter.clearInterval(autoPumpingInterval);
165
188
  autoPumpingInterval = null;
@@ -44,6 +44,7 @@ const photovoltaicHelper = {
44
44
  this.adapter.subscribeStates('photovoltaic.ignore_on_circulation');
45
45
  this.adapter.subscribeStates('status.season_active');
46
46
  this.adapter.subscribeStates('pump.mode');
47
+ this.adapter.subscribeStates('pump.active_helper');
47
48
 
48
49
  this._safeRecalc('init');
49
50
  this.adapter.log.info('[photovoltaicHelper] Initialization completed.');
@@ -76,8 +77,8 @@ const photovoltaicHelper = {
76
77
  return;
77
78
  }
78
79
 
79
- if (id.endsWith('status.season_active') || id.endsWith('pump.mode')) {
80
- await this._safeRecalc('mode/season');
80
+ if (id.endsWith('status.season_active') || id.endsWith('pump.mode') || id.endsWith('pump.active_helper')) {
81
+ await this._safeRecalc('mode/season/owner');
81
82
  return;
82
83
  }
83
84
  } catch (err) {
@@ -129,18 +130,39 @@ const photovoltaicHelper = {
129
130
 
130
131
  // Überschussberechnung
131
132
  const surplus = Math.max(0, gen - house);
132
- await this._updateNumberState('photovoltaic.power_surplus_w', surplus);
133
133
 
134
134
  // **NEU:** Einschaltlogik = Pumpenleistung + Sicherheitsaufschlag
135
135
  const requiredPower = pumpMax + threshold;
136
136
  const surplusActive = surplus >= requiredPower && seasonActive;
137
- await this._updateBoolState('photovoltaic.surplus_active', surplusActive);
138
137
 
139
138
  const txt = surplusActive
140
139
  ? `Überschuss aktiv (${surplus} W ≥ ${pumpMax}+${threshold} W)`
141
140
  : `Kein Überschuss (${surplus} W < ${pumpMax}+${threshold} W)`;
142
- await this._updateStringState('photovoltaic.status_text', txt);
143
- await this._updateStringState('photovoltaic.last_update', new Date().toISOString());
141
+
142
+ // FIX: Bestehende Ergebnisstates zuerst lesen, damit last_update nur bei echter Ergebnisänderung gesetzt wird
143
+ const currentSurplus = Number((await this.adapter.getStateAsync('photovoltaic.power_surplus_w'))?.val ?? 0);
144
+ const currentSurplusActive = !!(await this.adapter.getStateAsync('photovoltaic.surplus_active'))?.val;
145
+ const currentStatusText = (await this.adapter.getStateAsync('photovoltaic.status_text'))?.val ?? '';
146
+
147
+ const surplusChanged = currentSurplus !== surplus;
148
+ const surplusActiveChanged = currentSurplusActive !== surplusActive;
149
+ const statusTextChanged = currentStatusText !== txt;
150
+
151
+ if (surplusChanged) {
152
+ await this._updateNumberState('photovoltaic.power_surplus_w', surplus); // FIX
153
+ }
154
+
155
+ if (surplusActiveChanged) {
156
+ await this._updateBoolState('photovoltaic.surplus_active', surplusActive); // FIX
157
+ }
158
+
159
+ if (statusTextChanged) {
160
+ await this._updateStringState('photovoltaic.status_text', txt); // FIX
161
+ }
162
+
163
+ if (surplusChanged || surplusActiveChanged || statusTextChanged) {
164
+ await this._updateStringState('photovoltaic.last_update', new Date().toISOString()); // FIX
165
+ }
144
166
 
145
167
  // Saison/Modus prüfen
146
168
  if (!seasonActive) {
@@ -211,6 +233,11 @@ const photovoltaicHelper = {
211
233
  return this._maybeStopPump(false, afterrunMin, 'pv_ended_afterrun');
212
234
  },
213
235
 
236
+ async _isControlHelperPriorityActive() {
237
+ const activeHelper = (await this.adapter.getStateAsync('pump.active_helper'))?.val || '';
238
+ return activeHelper === 'controlHelper';
239
+ },
240
+
214
241
  async _maybeStartPump(reason) {
215
242
  if (this._desiredPump === true) {
216
243
  return;
@@ -226,6 +253,19 @@ const photovoltaicHelper = {
226
253
  },
227
254
 
228
255
  async _maybeStopPump(immediate, afterrunMin, tag) {
256
+ if (await this._isControlHelperPriorityActive()) {
257
+ if (this.afterrunTimer) {
258
+ clearTimeout(this.afterrunTimer);
259
+ this.afterrunTimer = null;
260
+ }
261
+ this._pvPumpHoldUntil = 0;
262
+ this._desiredPump = false;
263
+ this.adapter.log.debug(
264
+ `[photovoltaicHelper] Stop '${tag}' suppressed because controlHelper currently has priority.`,
265
+ );
266
+ return;
267
+ }
268
+
229
269
  if (immediate || !afterrunMin || afterrunMin <= 0) {
230
270
  if (this._desiredPump === false) {
231
271
  return;
@@ -242,6 +282,14 @@ const photovoltaicHelper = {
242
282
  clearTimeout(this.afterrunTimer);
243
283
  }
244
284
  this.afterrunTimer = setTimeout(async () => {
285
+ if (await this._isControlHelperPriorityActive()) {
286
+ this.adapter.log.debug(
287
+ '[photovoltaicHelper] Afterrun stop suppressed because controlHelper currently has priority.',
288
+ );
289
+ this._desiredPump = false;
290
+ return;
291
+ }
292
+
245
293
  const active = !!(await this.adapter.getStateAsync('photovoltaic.surplus_active'))?.val;
246
294
  if (active) {
247
295
  this.adapter.log.debug('[photovoltaicHelper] Afterrun canceled – surplus active again.');
@@ -229,7 +229,7 @@ const statisticsHelperMonth = {
229
229
  await adapter.setStateAsync(`${basePath}.temp_max`, { val: newMax, ack: true });
230
230
  await adapter.setStateAsync(`${basePath}.temp_avg`, { val: Math.round(newAvg * 100) / 100, ack: true });
231
231
  await adapter.setStateAsync(`${basePath}.data_points_count`, { val: newCount, ack: true });
232
- await adapter.setStateAsync(`${basePath}.last_update`, { val: now, ack: true });
232
+ await adapter.setStateAsync(`${basePath}.last_update`, { val: now, ack: true }); // FIX: Doppelwrite entfernt
233
233
 
234
234
  const summary = {
235
235
  name: 'Monatsstatistik',
@@ -157,16 +157,8 @@ const statusHelper = {
157
157
  }
158
158
  text += `. Tageslaufzeit: ${runtimeFormatted} (${circulationPct}% der Soll-Umwälzung).`;
159
159
 
160
- // In States schreiben (nur bei Änderung)
161
- const current = (await this.adapter.getStateAsync('status.summary'))?.val;
162
- if (current !== text) {
163
- await this.adapter.setStateAsync('status.summary', { val: text, ack: true });
164
- }
165
-
166
- await this.adapter.setStateAsync('status.last_summary_update', {
167
- val: new Date().toISOString(),
168
- ack: true,
169
- });
160
+ // FIX: Bestehende Werte zuerst lesen, damit last_summary_update nur bei echter Änderung gesetzt wird
161
+ const currentSummary = (await this.adapter.getStateAsync('status.summary'))?.val ?? '';
170
162
 
171
163
  // JSON-Übersicht bauen
172
164
  const json = {
@@ -179,10 +171,29 @@ const statusHelper = {
179
171
  runtime_formatted: runtimeFormatted,
180
172
  circulation_pct: circulationPct,
181
173
  };
182
- await this.adapter.setStateAsync('status.overview_json', {
183
- val: JSON.stringify(json),
184
- ack: true,
185
- });
174
+ const overviewJson = JSON.stringify(json);
175
+ const currentOverview = (await this.adapter.getStateAsync('status.overview_json'))?.val ?? '';
176
+
177
+ const summaryChanged = currentSummary !== text;
178
+ const overviewChanged = currentOverview !== overviewJson;
179
+
180
+ if (summaryChanged) {
181
+ await this.adapter.setStateAsync('status.summary', { val: text, ack: true }); // FIX
182
+ }
183
+
184
+ if (overviewChanged) {
185
+ await this.adapter.setStateAsync('status.overview_json', {
186
+ val: overviewJson,
187
+ ack: true,
188
+ }); // FIX
189
+ }
190
+
191
+ if (summaryChanged || overviewChanged) {
192
+ await this.adapter.setStateAsync('status.last_summary_update', {
193
+ val: new Date().toISOString(),
194
+ ack: true,
195
+ }); // FIX: nur bei echter Summary-/Overview-Änderung
196
+ }
186
197
  } catch (err) {
187
198
  this.adapter.log.warn(`[statusHelper] Error while updating summary: ${err.message}`);
188
199
  }
@@ -146,7 +146,7 @@ async function createPhotovoltaicStates(adapter) {
146
146
  unit: 'W',
147
147
  read: true,
148
148
  write: false,
149
- def: 200,
149
+ def: Number(adapter.config?.threshold_w ?? 200),
150
150
  },
151
151
  {
152
152
  id: 'status_text',
@@ -212,6 +212,11 @@ async function createPhotovoltaicStates(adapter) {
212
212
  }
213
213
  }
214
214
 
215
+ await adapter.setStateAsync('photovoltaic.threshold_w', {
216
+ val: Number(adapter.config?.threshold_w ?? 200),
217
+ ack: true,
218
+ });
219
+
215
220
  adapter.log.info('[createPhotovoltaicStates] Initialization completed.');
216
221
  }
217
222
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "1.2.18",
3
+ "version": "1.2.20",
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",