iobroker.poolcontrol 1.3.3 → 1.3.6

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
@@ -188,6 +188,25 @@ New features are added regularly – please refer to the changelog.
188
188
  ---
189
189
 
190
190
  ## Changelog
191
+ ### 1.3.6 (2026-04-21)
192
+
193
+ frostHelper
194
+ - Fixed incorrect pump shutdown when other helpers (e.g. photovoltaicHelper) are active
195
+ - frostHelper now only disables the pump if it previously activated it itself
196
+ - improved internal ownership logic for safer multi-helper interaction
197
+ - corrected frost speech state handling (no longer based on current pump state)
198
+ - switched timer to adapter.setInterval / adapter.clearInterval for better stability and ioBroker compliance
199
+
200
+ ### 1.3.5 (2026-04-19)
201
+
202
+ - Fixed critical i18n issue in solarInsightsHelper and solarLogbookHelper that could lead to instability or crashes
203
+ - Switched translation handling to I18n.translate() for stable and consistent i18n behavior
204
+
205
+ ### 1.3.4 (2026-04-19)
206
+
207
+ - Fixed critical i18n issue in solarInsightsHelper and solarLogbookHelper that could lead to instability or crashes
208
+ - Switched translation handling to I18n.translate() for stable and consistent i18n behavior
209
+
191
210
  ### 1.3.3 (2026-04-18)
192
211
 
193
212
  - Added solar COP calculation to evaluate system efficiency
@@ -202,28 +221,6 @@ New features are added regularly – please refer to the changelog.
202
221
  - Improvement: Replaced global timers with adapter timers in solarExtendedHelper
203
222
  - Cleanup: Removed duplicate reading of request_active state
204
223
 
205
- ### 1.3.1 (2026-04-17)
206
-
207
- - Fix: Solar Extended now correctly controls the pump
208
- - Fix: Integrated Solar Extended into existing solar status handling via `speech.solar_active`
209
- - Improvement: Consistent pump status display for Solar and Solar Extended
210
- - Minor bug fixes and internal optimizations
211
-
212
- ### 1.3.0 (2026-04-16)
213
-
214
- - Added extended solar control (delta-based temperature logic)
215
- - Support for external actuator control (boolean/socket)
216
- - Standard / Extended solar mode selection
217
- - Priority and blocking logic (controlHelper, timeHelper, pump mode, season)
218
- - Improved status states (active, request, blocked, reason, info)
219
- - Added i18n support for solar extended status texts
220
- - Added selectable configuration for temperature source and control type
221
-
222
- ### 1.2.22 (2026-04-16)
223
-
224
- - Added new read-only state `solar.request_active` to indicate when solar logic would request the pump
225
- - Improved solarHelper robustness by handling invalid temperature values
226
-
227
224
  ## Support
228
225
  - [ioBroker Forum](https://forum.iobroker.net/)
229
226
  - [GitHub Issues](https://github.com/DasBo1975/ioBroker.poolcontrol/issues)
package/io-package.json CHANGED
@@ -1,8 +1,47 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "1.3.3",
4
+ "version": "1.3.6",
5
5
  "news": {
6
+ "1.3.6": {
7
+ "en": "Fix for frostHelper: prevents incorrect pump shutdown when other helpers (e.g. photovoltaic) are active. Frost protection now only disables the pump if it previously activated it itself. Improved speech state logic for frost indication. Switched frostHelper timer to adapter.setInterval for better stability and ioBroker compliance.",
8
+ "de": "Fix für frostHelper: verhindert falsches Abschalten der Pumpe, wenn andere Helper (z. B. Photovoltaik) aktiv sind. Frostschutz schaltet die Pumpe jetzt nur noch aus, wenn er sie zuvor selbst aktiviert hat. Sprach-State für Frostanzeige korrigiert. Timer im frostHelper auf adapter.setInterval umgestellt für bessere Stabilität und ioBroker-Konformität.",
9
+ "ru": "Исправление FrostHelper: предотвращает некорректное выключение насоса, когда активны другие помощники (например, фотоэлектрические). Защита от замерзания теперь отключает насос только в том случае, если он ранее активировал его сам. Улучшена логика речевого состояния для индикации замерзания. Таймер FrostHelper переключен на адаптер.setInterval для большей стабильности и соответствия требованиям ioBroker.",
10
+ "pt": "Correção parafrostHelper: evita o desligamento incorreto da bomba quando outros auxiliares (por exemplo, fotovoltaicos) estão ativos. A proteção contra congelamento agora só desativa a bomba se ela mesma a tiver ativado anteriormente. Lógica de estado de fala aprimorada para indicação de congelamento. Mudou o temporizadorfrostHelper para adaptador.setInterval para melhor estabilidade e conformidade com ioBroker.",
11
+ "nl": "Oplossing voor FrostHelper: voorkomt onjuiste pompuitschakeling wanneer andere helpers (bijv. fotovoltaïsche energie) actief zijn. De vorstbeveiliging schakelt de pomp nu alleen uit als deze deze eerder zelf heeft geactiveerd. Verbeterde spraakstatuslogica voor vorstindicatie. FrostHelper-timer omgeschakeld naar adapter.setInterval voor betere stabiliteit en ioBroker-compliance.",
12
+ "fr": "Correctif pour frostHelper : empêche un arrêt incorrect de la pompe lorsque d'autres assistants (par exemple photovoltaïques) sont actifs. La protection antigel désactive désormais la pompe uniquement si elle l'a activée elle-même auparavant. Logique d’état vocale améliorée pour l’indication de gel. La minuterie FrostHelper a été remplacée par adapter.setInterval pour une meilleure stabilité et une meilleure conformité à ioBroker.",
13
+ "it": "Correzione per FrostHelper: impedisce lo spegnimento errato della pompa quando altri helper (ad esempio fotovoltaico) sono attivi. La protezione antigelo ora disabilita la pompa solo se precedentemente l'aveva attivata da sola. Logica dello stato vocale migliorata per l'indicazione del gelo. Cambiato il timer FrostHelper su Adapter.setInterval per una migliore stabilità e conformità con ioBroker.",
14
+ "es": "Solución para frostHelper: evita el apagado incorrecto de la bomba cuando otros ayudantes (por ejemplo, fotovoltaicos) están activos. La protección contra heladas ahora solo desactiva la bomba si previamente la activó ella misma. Lógica de estado de voz mejorada para indicación de escarcha. Se cambió el temporizador frostHelper a adaptor.setInterval para una mejor estabilidad y cumplimiento de ioBroker.",
15
+ "pl": "Poprawka dla FrostHelper: zapobiega nieprawidłowemu wyłączeniu pompy, gdy aktywne są inne pomoce (np. fotowoltaiczne). Ochrona przed zamarzaniem wyłącza teraz pompę tylko wtedy, gdy wcześniej sama ją uruchomiła. Ulepszona logika stanu mowy dla sygnalizacji mrozu. Zmieniono licznik czasu FrostHelper na adapter.setInterval, aby zapewnić lepszą stabilność i zgodność z ioBrokerem.",
16
+ "uk": "Виправлення для frostHelper: запобігає неправильному вимкненню насоса, коли інші помічники (наприклад, фотоелектричні) активні. Захист від замерзання тепер вимикає насос лише в тому випадку, якщо він раніше сам його активував. Покращена логіка стану мови для індикації морозу. Перемкнуто таймер frostHelper на adapter.setInterval для кращої стабільності та відповідності ioBroker.",
17
+ "zh-cn": "修复霜助手:防止当其他助手(例如光伏)处于活动状态时错误地关闭泵。现在,防冻保护只会在泵之前自行激活的情况下禁用泵。改进了霜冻指示的语音状态逻辑。将frostHelper计时器切换为adapter.setInterval以获得更好的稳定性和ioBroker合规性。"
18
+ },
19
+ "1.3.5": {
20
+ "en": "Fixed critical i18n issue in solarInsightsHelper and solarLogbookHelper that could lead to instability or crashes. Switched translation handling to I18n.translate() to ensure stable operation.",
21
+ "de": "Kritischer i18n-Fehler in solarInsightsHelper und solarLogbookHelper behoben, der zu Instabilität oder Abstürzen führen konnte. Übersetzungen wurden auf I18n.translate() umgestellt, um einen stabilen Betrieb sicherzustellen.",
22
+ "ru": "Исправлена ​​критическая проблема i18n в SolarInsightsHelper и SolarLogbookHelper, которая могла привести к нестабильности или сбоям. Обработку перевода переключили на I18n.translate() для обеспечения стабильной работы.",
23
+ "pt": "Foi corrigido um problema crítico do i18n no solarInsightsHelper e no solarLogbookHelper que poderia causar instabilidade ou travamentos. Manipulação de tradução alterada para I18n.translate() para garantir uma operação estável.",
24
+ "nl": "Een kritiek i18n-probleem in solarInsightsHelper en solarLogbookHelper opgelost dat tot instabiliteit of crashes kon leiden. De verwerking van de vertalingen is gewijzigd naar I18n.translate() om een ​​stabiele werking te garanderen.",
25
+ "fr": "Correction d'un problème i18n critique dans solarInsightsHelper et solarLogbookHelper qui pouvait entraîner une instabilité ou des plantages. Gestion de la traduction commutée vers I18n.translate() pour garantir un fonctionnement stable.",
26
+ "it": "Risolto un problema critico i18n in solarInsightsHelper e solarLogbookHelper che poteva portare a instabilità o arresti anomali. Modificata la gestione della traduzione su I18n.translate() per garantire un funzionamento stabile.",
27
+ "es": "Se solucionó un problema crítico de i18n en solarInsightsHelper y solarLogbookHelper que podía provocar inestabilidad o fallas. Se cambió el manejo de traducción a I18n.translate() para garantizar un funcionamiento estable.",
28
+ "pl": "Naprawiono krytyczny problem i18n w programach solarInsightsHelper i solarLogbookHelper, który mógł prowadzić do niestabilności lub awarii. Przełączono obsługę tłumaczeń na I18n.translate(), aby zapewnić stabilne działanie.",
29
+ "uk": "Виправлено критичну проблему i18n у solarInsightsHelper і solarLogbookHelper, яка могла призвести до нестабільності або збоїв. Перемкнуто обробку перекладу на I18n.translate(), щоб забезпечити стабільну роботу.",
30
+ "zh-cn": "修复了 SolarInsightsHelper 和 SolarLogbookHelper 中可能导致不稳定或崩溃的关键 i18n 问题。将翻译处理切换为 I18n.translate() 以确保稳定运行。"
31
+ },
32
+ "1.3.4": {
33
+ "en": "Fixed critical i18n issue in solarInsightsHelper and solarLogbookHelper that could lead to instability or crashes. Switched translation handling to I18n.translate() to ensure stable operation.",
34
+ "de": "Kritischer i18n-Fehler in solarInsightsHelper und solarLogbookHelper behoben, der zu Instabilität oder Abstürzen führen konnte. Übersetzungen wurden auf I18n.translate() umgestellt, um einen stabilen Betrieb sicherzustellen.",
35
+ "ru": "Исправлена ​​критическая проблема i18n в SolarInsightsHelper и SolarLogbookHelper, которая могла привести к нестабильности или сбоям. Обработку перевода переключили на I18n.translate() для обеспечения стабильной работы.",
36
+ "pt": "Foi corrigido um problema crítico do i18n no solarInsightsHelper e no solarLogbookHelper que poderia causar instabilidade ou travamentos. Manipulação de tradução alterada para I18n.translate() para garantir uma operação estável.",
37
+ "nl": "Een kritiek i18n-probleem in solarInsightsHelper en solarLogbookHelper opgelost dat tot instabiliteit of crashes kon leiden. De verwerking van de vertalingen is gewijzigd naar I18n.translate() om een ​​stabiele werking te garanderen.",
38
+ "fr": "Correction d'un problème i18n critique dans solarInsightsHelper et solarLogbookHelper qui pouvait entraîner une instabilité ou des plantages. Gestion de la traduction commutée vers I18n.translate() pour garantir un fonctionnement stable.",
39
+ "it": "Risolto un problema critico i18n in solarInsightsHelper e solarLogbookHelper che poteva portare a instabilità o arresti anomali. Modificata la gestione della traduzione su I18n.translate() per garantire un funzionamento stabile.",
40
+ "es": "Se solucionó un problema crítico de i18n en solarInsightsHelper y solarLogbookHelper que podía provocar inestabilidad o fallas. Se cambió el manejo de traducción a I18n.translate() para garantizar un funcionamiento estable.",
41
+ "pl": "Naprawiono krytyczny problem i18n w programach solarInsightsHelper i solarLogbookHelper, który mógł prowadzić do niestabilności lub awarii. Przełączono obsługę tłumaczeń na I18n.translate(), aby zapewnić stabilne działanie.",
42
+ "uk": "Виправлено критичну проблему i18n у solarInsightsHelper і solarLogbookHelper, яка могла призвести до нестабільності або збоїв. Перемкнуто обробку перекладу на I18n.translate(), щоб забезпечити стабільну роботу.",
43
+ "zh-cn": "修复了 SolarInsightsHelper 和 SolarLogbookHelper 中可能导致不稳定或崩溃的关键 i18n 问题。将翻译处理切换为 I18n.translate() 以确保稳定运行。"
44
+ },
6
45
  "1.3.3": {
7
46
  "en": "Added solar COP calculation and solar logbook helper with human-readable daily entries based on solar insights.",
8
47
  "de": "Solar-COP-Berechnung sowie Solar-Logbuch-Helper mit verständlichen Tages-Einträgen basierend auf Solar-Insights hinzugefügt.",
@@ -28,45 +67,6 @@
28
67
  "pl": "Naprawiono konflikty Solar Extended z ControlHelper/timeHelper i standardowym trybem solarnym, ulepszono obsługę zewnętrznego siłownika, dodano stabilną histerezę delta i dostosowano obsługę timera z timerami adaptera.",
29
68
  "uk": "Виправлено конфлікти Solar Extended з controlHelper/timeHelper і стандартним сонячним режимом, покращено обробку зовнішнього приводу, додано стабільний дельта-гістерезис і узгоджено обробку таймера з таймерами адаптера.",
30
69
  "zh-cn": "修复了 Solar Extended 与 controlHelper/timeHelper 和标准太阳能模式的冲突,改进了外部执行器处理,添加了稳定的增量迟滞,以及与适配器计时器对齐的计时器处理。"
31
- },
32
- "1.3.1": {
33
- "en": "Fix: Solar Extended now correctly controls the pump and integrates with existing solar status handling. The helper now uses speech.solar_active like the standard solar logic, ensuring consistent pump status display and behavior. Minor fixes and optimizations.",
34
- "de": "Fix: Solar Extended steuert jetzt korrekt die Pumpe und ist sauber in die bestehende Solar-Statuslogik integriert. Der Helper nutzt nun wie die Standard-Solarsteuerung den State speech.solar_active, wodurch Anzeige und Verhalten der Pumpe konsistent sind. Kleine Fehlerbehebungen und Optimierungen.",
35
- "ru": "Исправление: Solar Extended теперь правильно управляет насосом и интегрируется с существующей системой обработки состояния солнечной энергии. Помощник теперь использует voice.solar_active как стандартную логику Solar, обеспечивая единообразное отображение состояния и поведения насоса. Мелкие исправления и оптимизации.",
36
- "pt": "Correção: o Solar Extended agora controla corretamente a bomba e se integra ao tratamento do status solar existente. O auxiliar agora usa Speech.solar_active como a lógica solar padrão, garantindo exibição e comportamento consistentes do status da bomba. Pequenas correções e otimizações.",
37
- "nl": "Oplossing: Solar Extended bestuurt de pomp nu correct en integreert met bestaande zonnestatusafhandeling. De helper gebruikt nu speech.solar_active zoals de standaard zonnelogica, waardoor een consistente weergave en gedrag van de pompstatus wordt gegarandeerd. Kleine reparaties en optimalisaties.",
38
- "fr": "Correctif : Solar Extended contrôle désormais correctement la pompe et s'intègre à la gestion de l'état solaire existante. L'assistant utilise désormais Speech.solar_active comme la logique solaire standard, garantissant un affichage et un comportement cohérents de l'état de la pompe. Corrections mineures et optimisations.",
39
- "it": "Correzione: Solar Extended ora controlla correttamente la pompa e si integra con la gestione dello stato solare esistente. L'helper ora utilizza Speech.solar_active come la logica solare standard, garantendo una visualizzazione e un comportamento coerenti dello stato della pompa. Correzioni e ottimizzazioni minori.",
40
- "es": "Solución: Solar Extended ahora controla correctamente la bomba y se integra con el manejo del estado solar existente. El asistente ahora utiliza Speech.solar_active como la lógica solar estándar, lo que garantiza una visualización y un comportamiento consistentes del estado de la bomba. Correcciones y optimizaciones menores.",
41
- "pl": "Poprawka: Solar Extended teraz poprawnie steruje pompą i integruje się z istniejącą obsługą stanu solarnego. Pomocnik używa teraz mowy.solar_active jak standardowej logiki solarnej, zapewniając spójne wyświetlanie stanu i zachowanie pompy. Drobne poprawki i optymalizacje.",
42
- "uk": "Виправлення: Solar Extended тепер правильно керує насосом та інтегрується з існуючою обробкою стану сонячної енергії. Помічник тепер використовує speak.solar_active як стандартну сонячну логіку, забезпечуючи послідовне відображення стану насоса та поведінку. Незначні виправлення та оптимізації.",
43
- "zh-cn": "修复:Solar Extended 现在可以正确控制泵并与现有的太阳能状态处理集成。助手现在像标准太阳能逻辑一样使用pepe.solar_active,确保一致的泵状态显示和行为。小修复和优化。"
44
- },
45
- "1.3.0": {
46
- "en": "Added extended solar control with selectable standard/extended mode, delta-based control logic, external actuator support, priority/blocking handling, and localized status texts.",
47
- "de": "Erweiterte Solarsteuerung ergänzt mit wählbarem Standard-/Extended-Modus, differenzbasierter Regelung, externer Aktor-Ansteuerung, Vorrang-/Blockierlogik und lokalisierten Statusmeldungen.",
48
- "ru": "Добавлено расширенное управление солнечной батареей с возможностью выбора стандартного/расширенного режима, логикой управления на основе дельты, поддержкой внешнего исполнительного механизма, обработкой приоритета/блокировки и локализованными текстами состояния.",
49
- "pt": "Adicionado controle solar estendido com modo padrão/estendido selecionável, lógica de controle baseada em delta, suporte a atuador externo, tratamento de prioridade/bloqueio e textos de status localizados.",
50
- "nl": "Uitgebreide zonneregeling toegevoegd met selecteerbare standaard/uitgebreide modus, op delta gebaseerde besturingslogica, ondersteuning voor externe actuatoren, afhandeling van prioriteiten/blokkeringen en gelokaliseerde statusteksten.",
51
- "fr": "Ajout d'un contrôle solaire étendu avec mode standard/étendu sélectionnable, logique de contrôle basée sur le delta, prise en charge d'actionneurs externes, gestion des priorités/blocages et textes d'état localisés.",
52
- "it": "Aggiunto controllo solare esteso con modalità standard/estesa selezionabile, logica di controllo basata su delta, supporto per attuatori esterni, gestione priorità/blocco e testi di stato localizzati.",
53
- "es": "Se agregó control solar extendido con modo estándar/extendido seleccionable, lógica de control basada en delta, soporte de actuador externo, manejo de prioridad/bloqueo y textos de estado localizados.",
54
- "pl": "Dodano rozszerzone sterowanie solarne z możliwością wyboru trybu standardowego/rozszerzonego, logikę sterowania opartą na delta, obsługę zewnętrznych siłowników, obsługę priorytetów/blokowania i zlokalizowane teksty stanu.",
55
- "uk": "Додано розширене керування геліосистемою з вибором стандартного/розширеного режиму, логікою керування на основі дельти, підтримкою зовнішнього приводу, обробкою пріоритетів/блокування та локалізованими текстами стану.",
56
- "zh-cn": "添加了扩展太阳能控制,具有可选的标准/扩展模式、基于增量的控制逻辑、外部执行器支持、优先级/阻止处理和本地化状态文本。"
57
- },
58
- "1.2.22": {
59
- "en": "Added new read-only state solar.request_active to indicate when solar logic would request the pump. Improved robustness of solarHelper by handling invalid temperature values.",
60
- "de": "Neuer read-only Datenpunkt solar.request_active hinzugefügt, der anzeigt, wann die Solarlogik die Pumpe anfordern würde. Stabilität des solarHelpers verbessert durch Behandlung ungültiger Temperaturwerte.",
61
- "ru": "Добавлено новое состояние Solar.request_active, доступное только для чтения, чтобы указать, когда солнечная логика запросит насос. Повышена надежность SolarHelper за счет обработки недопустимых значений температуры.",
62
- "pt": "Adicionado novo estado somente leitura solar.request_active para indicar quando a lógica solar solicitaria a bomba. Robustez aprimorada do solarHelper ao lidar com valores de temperatura inválidos.",
63
- "nl": "Nieuwe alleen-lezen status solar.request_active toegevoegd om aan te geven wanneer de zonnelogica de pomp zou aanvragen. Verbeterde robuustheid van solarHelper door ongeldige temperatuurwaarden te verwerken.",
64
- "fr": "Ajout d'un nouvel état en lecture seule solar.request_active pour indiquer quand la logique solaire demanderait la pompe. Robustesse améliorée de solarHelper en gérant des valeurs de température invalides.",
65
- "it": "Aggiunto nuovo stato di sola lettura solar.request_active per indicare quando la logica solare richiederebbe la pompa. Robustezza migliorata di solarHelper gestendo valori di temperatura non validi.",
66
- "es": "Se agregó un nuevo estado de solo lectura solar.request_active para indicar cuándo la lógica solar solicitaría la bomba. Robustez mejorada de solarHelper al manejar valores de temperatura no válidos.",
67
- "pl": "Dodano nowy stan tylko do odczytu solar.request_active, aby wskazać, kiedy logika solarna zażąda pompy. Poprawiona niezawodność solarHelper poprzez obsługę nieprawidłowych wartości temperatur.",
68
- "uk": "Додано новий стан solar.request_active лише для читання, щоб вказати, коли сонячна логіка запитуватиме насос. Покращена надійність solarHelper завдяки обробці недійсних значень температури.",
69
- "zh-cn": "添加了新的只读状态 Solar.request_active 以指示太阳能逻辑何时请求泵。通过处理无效温度值提高了 SolarHelper 的稳健性。"
70
70
  }
71
71
  },
72
72
  "titleLang": {
@@ -27,9 +27,9 @@ const frostHelper = {
27
27
 
28
28
  _scheduleCheck() {
29
29
  if (this.checkTimer) {
30
- clearInterval(this.checkTimer);
30
+ this.adapter.clearInterval(this.checkTimer);
31
31
  }
32
- this.checkTimer = setInterval(() => this._checkFrost(), 60 * 1000);
32
+ this.checkTimer = this.adapter.setInterval(() => this._checkFrost(), 60 * 1000);
33
33
  // Beim Start sofort prüfen
34
34
  this._checkFrost();
35
35
  },
@@ -84,11 +84,12 @@ const frostHelper = {
84
84
  shouldRun = false;
85
85
  }
86
86
 
87
- // --- NEU: Sprachsignal für Frostschutz setzen ---
87
+ // FIX: Sprachsignal nur nach echter Frostlogik setzen, nicht nach aktuellem Pumpenzustand
88
+ const frostNowActive = outsideRounded <= frostTempRounded;
88
89
  const oldVal = (await this.adapter.getStateAsync('speech.frost_active'))?.val;
89
- if (oldVal !== shouldRun) {
90
+ if (oldVal !== frostNowActive) {
90
91
  await this.adapter.setStateChangedAsync('speech.frost_active', {
91
- val: shouldRun,
92
+ val: frostNowActive,
92
93
  ack: true,
93
94
  });
94
95
  }
@@ -106,26 +107,34 @@ const frostHelper = {
106
107
  // Frost als aktiven Helper/Modus setzen (damit der pumpHelper "EIN (Frostschutz)" anzeigt)
107
108
  await this.adapter.setStateAsync('pump.active_helper', { val: 'frostHelper', ack: true });
108
109
  await this.adapter.setStateAsync('pump.mode', { val: 'frostHelper', ack: true });
110
+
111
+ await this.adapter.setStateAsync('pump.pump_switch', {
112
+ val: true,
113
+ ack: false,
114
+ });
115
+ this.adapter.log.info(
116
+ `[frostHelper] Frost protection -> pump ON (outside=${outside}°C, limit=${frostTemp}°C)`,
117
+ );
109
118
  } else {
110
- // Ausschalten: Nur zurücksetzen, wenn der Frosthelfer wirklich aktiv war
119
+ // FIX: Nur ausschalten, wenn der Frosthelfer die Pumpe selbst übernommen hat
111
120
  const activeHelperNow = (await this.adapter.getStateAsync('pump.active_helper'))?.val || '';
112
121
  if (activeHelperNow === 'frostHelper') {
113
122
  const modeToRestore = this._prevModeBeforeFrost || 'auto';
114
123
  await this.adapter.setStateAsync('pump.active_helper', { val: '', ack: true });
115
124
  await this.adapter.setStateAsync('pump.mode', { val: modeToRestore, ack: true });
125
+
126
+ await this.adapter.setStateAsync('pump.pump_switch', {
127
+ val: false,
128
+ ack: false,
129
+ });
130
+ this.adapter.log.info(
131
+ `[frostHelper] Frost protection -> pump OFF (outside=${outside}°C, limit=${frostTemp}°C)`,
132
+ );
116
133
  }
117
134
  // internen Zwischenspeicher nach Ende löschen
118
135
  this._prevModeBeforeFrost = null;
119
136
  }
120
137
  // ENDE NEU
121
-
122
- await this.adapter.setStateAsync('pump.pump_switch', {
123
- val: shouldRun,
124
- ack: false,
125
- });
126
- this.adapter.log.info(
127
- `[frostHelper] Frost protection -> pump ${shouldRun ? 'ON' : 'OFF'} (outside=${outside}°C, limit=${frostTemp}°C)`,
128
- );
129
138
  }
130
139
  } catch (err) {
131
140
  this.adapter.log.warn(`[frostHelper] Error in check: ${err.message}`);
@@ -134,7 +143,7 @@ const frostHelper = {
134
143
 
135
144
  cleanup() {
136
145
  if (this.checkTimer) {
137
- clearInterval(this.checkTimer);
146
+ this.adapter.clearInterval(this.checkTimer);
138
147
  this.checkTimer = null;
139
148
  }
140
149
  },
@@ -106,12 +106,12 @@ const solarInsightsHelper = {
106
106
  });
107
107
 
108
108
  await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.last_recalculation_reason', {
109
- val: this._t('solar_insights_reason_daily_reset'),
109
+ val: I18n.translate('solar_insights_reason_daily_reset'),
110
110
  ack: true,
111
111
  });
112
112
 
113
113
  await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.debug_text', {
114
- val: this._t('solar_insights_debug_daily_reset_executed'),
114
+ val: I18n.translate('solar_insights_debug_daily_reset_executed'),
115
115
  ack: true,
116
116
  });
117
117
 
@@ -404,7 +404,6 @@ const solarInsightsHelper = {
404
404
  }
405
405
 
406
406
  const summaryJson = {
407
- block: 7,
408
407
  mode: 'estimated_daily_gain',
409
408
  solar_ran_today: solarRanToday,
410
409
  solar_effective_now: solarEffectiveNow,
@@ -431,32 +430,32 @@ const solarInsightsHelper = {
431
430
  active_minutes_today: Number.isFinite(activeMinutesToday) ? activeMinutesToday : null,
432
431
  peak_power_today_w: Number.isFinite(peakPowerTodayW) ? peakPowerTodayW : null,
433
432
  },
434
- note: this._t('solar_insights_summary_note_block_7'),
433
+ note: I18n.translate('solar_insights_summary_note_block_7'),
435
434
  };
436
435
 
437
436
  const summaryHtml = [
438
437
  '<div>',
439
- `<b>${this._t('solar_insights_label_mode')}:</b> ${this._t('solar_insights_mode_estimated_daily_gain')}<br>`,
440
- `<b>${this._t('solar_insights_label_solar_ran_today')}:</b> ${solarRanToday}<br>`,
441
- `<b>${this._t('solar_insights_label_solar_effective_now')}:</b> ${solarEffectiveNow}<br>`,
442
- `<b>${this._t('solar_insights_label_pool_reference_source')}:</b> ${poolReferenceSource}<br>`,
443
- `<b>${this._t('solar_insights_label_flow_source')}:</b> ${flowSource}<br>`,
444
- `<b>${this._t('solar_insights_label_weather_correction_active')}:</b> ${weatherCorrectionActive}<br>`,
445
- `<b>${this._t('solar_insights_label_confidence')}:</b> ${confidencePercent} %<br>`,
446
- `<b>${this._t('solar_insights_label_used_sensors')}:</b> ${usedSensors.join(', ') || this._t('solar_insights_value_none')}<br>`,
447
- `<b>${this._t('solar_insights_label_collector')}:</b> ${Number.isFinite(collectorTemp) ? `${collectorTemp} °C` : this._t('solar_insights_value_na')}<br>`,
448
- `<b>${this._t('solar_insights_label_pool_reference')}:</b> ${Number.isFinite(poolReferenceTemp) ? `${poolReferenceTemp} °C` : this._t('solar_insights_value_na')}<br>`,
449
- `<b>${this._t('solar_insights_label_delta_t')}:</b> ${Number.isFinite(deltaTUsed) ? `${deltaTUsed} K` : this._t('solar_insights_value_na')}<br>`,
450
- `<b>${this._t('solar_insights_label_surface_ground_delta')}:</b> ${Number.isFinite(surfaceGroundDelta) ? `${surfaceGroundDelta} K` : this._t('solar_insights_value_na')}<br>`,
451
- `<b>${this._t('solar_insights_label_outside')}:</b> ${Number.isFinite(outsideTemp) ? `${outsideTemp} °C` : this._t('solar_insights_value_na')}<br>`,
452
- `<b>${this._t('solar_insights_label_flow')}:</b> ${Number.isFinite(currentFlowLh) ? `${currentFlowLh} l/h` : this._t('solar_insights_value_na')}<br>`,
453
- `<b>${this._t('solar_insights_label_pump_power')}:</b> ${Number.isFinite(pumpCurrentPowerW) ? `${pumpCurrentPowerW} W` : this._t('solar_insights_value_na')}<br>`,
454
- `<b>${this._t('solar_insights_label_thermal_power')}:</b> ${Number.isFinite(thermalPowerW) ? `${thermalPowerW} W (${thermalPowerKW} kW)` : this._t('solar_insights_value_na')}<br>`,
455
- `<b>${this._t('solar_insights_label_estimated_efficiency_ratio')}:</b> ${Number.isFinite(estimatedEfficiencyRatio) ? estimatedEfficiencyRatio : this._t('solar_insights_value_na')}<br>`,
456
- `<b>${this._t('solar_insights_label_gain_today')}:</b> ${Number.isFinite(estimatedGainTodayWh) ? `${estimatedGainTodayWh} Wh (${estimatedGainTodayKWh} kWh)` : this._t('solar_insights_value_na')}<br>`,
457
- `<b>${this._t('solar_insights_label_active_minutes_today')}:</b> ${Number.isFinite(activeMinutesToday) ? `${activeMinutesToday} min` : this._t('solar_insights_value_na')}<br>`,
458
- `<b>${this._t('solar_insights_label_peak_power_today')}:</b> ${Number.isFinite(peakPowerTodayW) ? `${peakPowerTodayW} W` : this._t('solar_insights_value_na')}<br>`,
459
- `<b>${this._t('solar_insights_label_note')}:</b> ${this._t('solar_insights_html_note_block_7')}`,
438
+ `<b>${I18n.translate('solar_insights_label_mode')}:</b> ${I18n.translate('solar_insights_mode_estimated_daily_gain')}<br>`,
439
+ `<b>${I18n.translate('solar_insights_label_solar_ran_today')}:</b> ${solarRanToday}<br>`,
440
+ `<b>${I18n.translate('solar_insights_label_solar_effective_now')}:</b> ${solarEffectiveNow}<br>`,
441
+ `<b>${I18n.translate('solar_insights_label_pool_reference_source')}:</b> ${poolReferenceSource}<br>`,
442
+ `<b>${I18n.translate('solar_insights_label_flow_source')}:</b> ${flowSource}<br>`,
443
+ `<b>${I18n.translate('solar_insights_label_weather_correction_active')}:</b> ${weatherCorrectionActive}<br>`,
444
+ `<b>${I18n.translate('solar_insights_label_confidence')}:</b> ${confidencePercent} %<br>`,
445
+ `<b>${I18n.translate('solar_insights_label_used_sensors')}:</b> ${usedSensors.join(', ') || I18n.translate('solar_insights_value_none')}<br>`,
446
+ `<b>${I18n.translate('solar_insights_label_collector')}:</b> ${Number.isFinite(collectorTemp) ? `${collectorTemp} °C` : I18n.translate('solar_insights_value_na')}<br>`,
447
+ `<b>${I18n.translate('solar_insights_label_pool_reference')}:</b> ${Number.isFinite(poolReferenceTemp) ? `${poolReferenceTemp} °C` : I18n.translate('solar_insights_value_na')}<br>`,
448
+ `<b>${I18n.translate('solar_insights_label_delta_t')}:</b> ${Number.isFinite(deltaTUsed) ? `${deltaTUsed} K` : I18n.translate('solar_insights_value_na')}<br>`,
449
+ `<b>${I18n.translate('solar_insights_label_surface_ground_delta')}:</b> ${Number.isFinite(surfaceGroundDelta) ? `${surfaceGroundDelta} K` : I18n.translate('solar_insights_value_na')}<br>`,
450
+ `<b>${I18n.translate('solar_insights_label_outside')}:</b> ${Number.isFinite(outsideTemp) ? `${outsideTemp} °C` : I18n.translate('solar_insights_value_na')}<br>`,
451
+ `<b>${I18n.translate('solar_insights_label_flow')}:</b> ${Number.isFinite(currentFlowLh) ? `${currentFlowLh} l/h` : I18n.translate('solar_insights_value_na')}<br>`,
452
+ `<b>${I18n.translate('solar_insights_label_pump_power')}:</b> ${Number.isFinite(pumpCurrentPowerW) ? `${pumpCurrentPowerW} W` : I18n.translate('solar_insights_value_na')}<br>`,
453
+ `<b>${I18n.translate('solar_insights_label_thermal_power')}:</b> ${Number.isFinite(thermalPowerW) ? `${thermalPowerW} W (${thermalPowerKW} kW)` : I18n.translate('solar_insights_value_na')}<br>`,
454
+ `<b>${I18n.translate('solar_insights_label_estimated_efficiency_ratio')}:</b> ${Number.isFinite(estimatedEfficiencyRatio) ? estimatedEfficiencyRatio : I18n.translate('solar_insights_value_na')}<br>`,
455
+ `<b>${I18n.translate('solar_insights_label_gain_today')}:</b> ${Number.isFinite(estimatedGainTodayWh) ? `${estimatedGainTodayWh} Wh (${estimatedGainTodayKWh} kWh)` : I18n.translate('solar_insights_value_na')}<br>`,
456
+ `<b>${I18n.translate('solar_insights_label_active_minutes_today')}:</b> ${Number.isFinite(activeMinutesToday) ? `${activeMinutesToday} min` : I18n.translate('solar_insights_value_na')}<br>`,
457
+ `<b>${I18n.translate('solar_insights_label_peak_power_today')}:</b> ${Number.isFinite(peakPowerTodayW) ? `${peakPowerTodayW} W` : I18n.translate('solar_insights_value_na')}<br>`,
458
+ `<b>${I18n.translate('solar_insights_label_note')}:</b> ${I18n.translate('solar_insights_html_note_block_7')}`,
460
459
  '</div>',
461
460
  ].join('');
462
461
 
@@ -550,8 +549,8 @@ const solarInsightsHelper = {
550
549
  });
551
550
  await this.adapter.setStateChangedAsync('analytics.insights.solar.results.solar_gain_state', {
552
551
  val: solarRanToday
553
- ? this._t('solar_insights_status_estimated_daily_gain_ready')
554
- : this._t('solar_insights_status_no_solar_runtime_today'),
552
+ ? I18n.translate('solar_insights_status_estimated_daily_gain_ready')
553
+ : I18n.translate('solar_insights_status_no_solar_runtime_today'),
555
554
  ack: true,
556
555
  });
557
556
 
@@ -631,16 +630,16 @@ const solarInsightsHelper = {
631
630
 
632
631
  // --- Calculation ---
633
632
  await this.adapter.setStateChangedAsync('analytics.insights.solar.calculation.mode', {
634
- val: this._t('solar_insights_mode_estimated_daily_gain'),
633
+ val: I18n.translate('solar_insights_mode_estimated_daily_gain'),
635
634
  ack: true,
636
635
  });
637
636
  await this.adapter.setStateChangedAsync('analytics.insights.solar.calculation.quality_level', {
638
637
  val:
639
638
  confidencePercent >= 85
640
- ? this._t('solar_insights_quality_advanced')
639
+ ? I18n.translate('solar_insights_quality_advanced')
641
640
  : confidencePercent >= 70
642
- ? this._t('solar_insights_quality_enhanced')
643
- : this._t('solar_insights_quality_basic'),
641
+ ? I18n.translate('solar_insights_quality_enhanced')
642
+ : I18n.translate('solar_insights_quality_basic'),
644
643
  ack: true,
645
644
  });
646
645
  await this.adapter.setStateChangedAsync('analytics.insights.solar.calculation.confidence_percent', {
@@ -660,17 +659,13 @@ const solarInsightsHelper = {
660
659
  ack: true,
661
660
  });
662
661
  await this.adapter.setStateChangedAsync('analytics.insights.solar.calculation.note', {
663
- val: this._t('solar_insights_calculation_note_block_7'),
662
+ val: I18n.translate('solar_insights_calculation_note_block_7'),
664
663
  ack: true,
665
664
  });
666
665
 
667
666
  // --- Debug ---
668
- await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.last_update', {
669
- val: new Date().toISOString(),
670
- ack: true,
671
- });
672
667
  await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.last_recalculation_reason', {
673
- val: this._t('solar_insights_reason_block_7_update'),
668
+ val: I18n.translate('solar_insights_reason_block_7_update'),
674
669
  ack: true,
675
670
  });
676
671
  await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.last_valid_mode', {
@@ -682,7 +677,7 @@ const solarInsightsHelper = {
682
677
  ack: true,
683
678
  });
684
679
  await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.debug_text', {
685
- val: `${this._t('solar_insights_debug_block_7_updated')} ${usedSensors.join(', ') || this._t('solar_insights_value_none')}`,
680
+ val: `${I18n.translate('solar_insights_debug_block_7_updated')} ${usedSensors.join(', ') || I18n.translate('solar_insights_value_none')}`,
686
681
  ack: true,
687
682
  });
688
683
 
@@ -700,7 +695,7 @@ const solarInsightsHelper = {
700
695
  ack: true,
701
696
  });
702
697
  await this.adapter.setStateChangedAsync('analytics.insights.solar.debug.debug_text', {
703
- val: `${this._t('solar_insights_debug_block_7_error')} ${err.message}`,
698
+ val: `${I18n.translate('solar_insights_debug_block_7_error')} ${err.message}`,
704
699
  ack: true,
705
700
  });
706
701
  }
@@ -752,14 +747,6 @@ const solarInsightsHelper = {
752
747
  return String(state.val);
753
748
  },
754
749
 
755
- _t(text) {
756
- try {
757
- return I18n.t(text);
758
- } catch {
759
- return text;
760
- }
761
- },
762
-
763
750
  cleanup() {
764
751
  if (this.checkTimer) {
765
752
  this.adapter.clearTimeout(this.checkTimer);
@@ -305,24 +305,24 @@ const solarLogbookHelper = {
305
305
  } = data;
306
306
 
307
307
  const sentences = [];
308
- const usedSensors = usedSensorsText || this._t('solar_log_value_unknown');
308
+ const usedSensors = usedSensorsText || I18n.translate('solar_log_value_unknown');
309
309
  const confidenceText = Number.isFinite(confidencePercent)
310
- ? this._tf('solar_log_confidence_text', this._formatNumber(confidencePercent, 0))
310
+ ? I18n.translate('solar_log_confidence_text').replace('%s', this._formatNumber(confidencePercent, 0))
311
311
  : '';
312
312
  const weatherTextShort = this._extractShortWeather(weatherSummary);
313
313
 
314
314
  if (!solarRanToday) {
315
- sentences.push(this._t('solar_log_text_no_runtime_today'));
315
+ sentences.push(I18n.translate('solar_log_text_no_runtime_today'));
316
316
 
317
317
  if (weatherTextShort !== '') {
318
- sentences.push(this._tf('solar_log_text_weather_short', weatherTextShort));
318
+ sentences.push(I18n.translate('solar_log_text_weather_short').replace('%s', weatherTextShort));
319
319
  }
320
320
 
321
321
  if (confidenceText !== '') {
322
322
  sentences.push(confidenceText);
323
323
  }
324
324
 
325
- sentences.push(this._tf('solar_log_text_used_sensors', usedSensors));
325
+ sentences.push(I18n.translate('solar_log_text_used_sensors').replace('%s', usedSensors));
326
326
 
327
327
  const text = sentences.join(' ');
328
328
  return {
@@ -333,62 +333,56 @@ const solarLogbookHelper = {
333
333
  }
334
334
 
335
335
  if (solarEffectiveNow && Number.isFinite(thermalPowerKW) && thermalPowerKW > 0) {
336
- sentences.push(this._tf('solar_log_text_active_effective', this._formatNumber(thermalPowerKW, 2)));
336
+ sentences.push(
337
+ I18n.translate('solar_log_text_active_effective').replace('%s', this._formatNumber(thermalPowerKW, 2)),
338
+ );
337
339
  } else if (solarEffectiveNow) {
338
- sentences.push(this._t('solar_log_text_active_without_clear_gain'));
340
+ sentences.push(I18n.translate('solar_log_text_active_without_clear_gain'));
339
341
  } else {
340
- sentences.push(this._t('solar_log_text_not_active_now'));
342
+ sentences.push(I18n.translate('solar_log_text_not_active_now'));
341
343
  }
342
344
 
343
345
  if (Number.isFinite(gainTodayKWh) && gainTodayKWh >= 3) {
344
- sentences.push(this._tf('solar_log_text_good_day', this._formatNumber(gainTodayKWh, 2)));
346
+ sentences.push(
347
+ I18n.translate('solar_log_text_good_day').replace('%s', this._formatNumber(gainTodayKWh, 2)),
348
+ );
345
349
  } else if (Number.isFinite(gainTodayKWh) && gainTodayKWh >= 1) {
346
- sentences.push(this._tf('solar_log_text_moderate_day', this._formatNumber(gainTodayKWh, 2)));
350
+ sentences.push(
351
+ I18n.translate('solar_log_text_moderate_day').replace('%s', this._formatNumber(gainTodayKWh, 2)),
352
+ );
347
353
  } else if (Number.isFinite(gainTodayKWh) && gainTodayKWh > 0) {
348
- sentences.push(this._tf('solar_log_text_low_day', this._formatNumber(gainTodayKWh, 2)));
354
+ sentences.push(I18n.translate('solar_log_text_low_day').replace('%s', this._formatNumber(gainTodayKWh, 2)));
349
355
  } else {
350
- sentences.push(this._t('solar_log_text_no_clear_day_gain'));
356
+ sentences.push(I18n.translate('solar_log_text_no_clear_day_gain'));
351
357
  }
352
358
 
353
359
  if (Number.isFinite(collectorTemp) && Number.isFinite(poolReferenceTemp) && Number.isFinite(deltaTUsed)) {
354
360
  if (deltaTUsed > 0.5) {
355
- sentences.push(
356
- this._tf(
357
- 'solar_log_text_temperature_positive',
358
- this._formatNumber(collectorTemp, 1),
359
- this._formatNumber(poolReferenceTemp, 1),
360
- this._formatNumber(deltaTUsed, 1),
361
- ),
362
- );
361
+ let text = I18n.translate('solar_log_text_temperature_positive');
362
+ text = text.replace('%s', this._formatNumber(collectorTemp, 1));
363
+ text = text.replace('%s', this._formatNumber(poolReferenceTemp, 1));
364
+ text = text.replace('%s', this._formatNumber(deltaTUsed, 1));
365
+ sentences.push(text);
363
366
  } else if (deltaTUsed <= 0.5 && deltaTUsed >= -0.5) {
364
- sentences.push(
365
- this._tf(
366
- 'solar_log_text_temperature_neutral',
367
- this._formatNumber(collectorTemp, 1),
368
- this._formatNumber(poolReferenceTemp, 1),
369
- ),
370
- );
367
+ let text = I18n.translate('solar_log_text_temperature_neutral');
368
+ text = text.replace('%s', this._formatNumber(collectorTemp, 1));
369
+ text = text.replace('%s', this._formatNumber(poolReferenceTemp, 1));
370
+ sentences.push(text);
371
371
  } else {
372
- sentences.push(
373
- this._tf(
374
- 'solar_log_text_temperature_negative',
375
- this._formatNumber(collectorTemp, 1),
376
- this._formatNumber(poolReferenceTemp, 1),
377
- ),
378
- );
372
+ let text = I18n.translate('solar_log_text_temperature_negative');
373
+ text = text.replace('%s', this._formatNumber(collectorTemp, 1));
374
+ text = text.replace('%s', this._formatNumber(poolReferenceTemp, 1));
375
+ sentences.push(text);
379
376
  }
380
377
  }
381
378
 
382
379
  if (Number.isFinite(flowLhUsed) && flowLhUsed > 0 && Number.isFinite(pumpPowerWUsed) && pumpPowerWUsed > 0) {
383
- sentences.push(
384
- this._tf(
385
- 'solar_log_text_flow_and_pump',
386
- this._formatNumber(flowLhUsed, 0),
387
- this._formatNumber(pumpPowerWUsed, 0),
388
- ),
389
- );
380
+ let text = I18n.translate('solar_log_text_flow_and_pump');
381
+ text = text.replace('%s', this._formatNumber(flowLhUsed, 0));
382
+ text = text.replace('%s', this._formatNumber(pumpPowerWUsed, 0));
383
+ sentences.push(text);
390
384
  } else if (Number.isFinite(flowLhUsed) && flowLhUsed > 0) {
391
- sentences.push(this._tf('solar_log_text_flow_only', this._formatNumber(flowLhUsed, 0)));
385
+ sentences.push(I18n.translate('solar_log_text_flow_only').replace('%s', this._formatNumber(flowLhUsed, 0)));
392
386
  }
393
387
 
394
388
  if (
@@ -397,60 +391,78 @@ const solarLogbookHelper = {
397
391
  Number.isFinite(peakPowerTodayW) &&
398
392
  peakPowerTodayW > 0
399
393
  ) {
400
- sentences.push(
401
- this._tf(
402
- 'solar_log_text_power_and_peak',
403
- this._formatNumber(thermalPowerW, 0),
404
- this._formatNumber(peakPowerTodayW, 0),
405
- ),
406
- );
394
+ let text = I18n.translate('solar_log_text_power_and_peak');
395
+ text = text.replace('%s', this._formatNumber(thermalPowerW, 0));
396
+ text = text.replace('%s', this._formatNumber(peakPowerTodayW, 0));
397
+ sentences.push(text);
407
398
  }
408
399
 
409
400
  if (Number.isFinite(efficiencyRatio) && efficiencyRatio > 0) {
410
401
  if (efficiencyRatio >= 5) {
411
- sentences.push(this._tf('solar_log_text_efficiency_high', this._formatNumber(efficiencyRatio, 2)));
402
+ sentences.push(
403
+ I18n.translate('solar_log_text_efficiency_high').replace(
404
+ '%s',
405
+ this._formatNumber(efficiencyRatio, 2),
406
+ ),
407
+ );
412
408
  } else if (efficiencyRatio >= 2) {
413
- sentences.push(this._tf('solar_log_text_efficiency_medium', this._formatNumber(efficiencyRatio, 2)));
409
+ sentences.push(
410
+ I18n.translate('solar_log_text_efficiency_medium').replace(
411
+ '%s',
412
+ this._formatNumber(efficiencyRatio, 2),
413
+ ),
414
+ );
414
415
  } else {
415
- sentences.push(this._tf('solar_log_text_efficiency_low', this._formatNumber(efficiencyRatio, 2)));
416
+ sentences.push(
417
+ I18n.translate('solar_log_text_efficiency_low').replace(
418
+ '%s',
419
+ this._formatNumber(efficiencyRatio, 2),
420
+ ),
421
+ );
416
422
  }
417
423
  }
418
424
 
419
425
  if (Number.isFinite(activeMinutesToday) && activeMinutesToday > 0) {
420
- sentences.push(this._tf('solar_log_text_active_minutes', this._formatNumber(activeMinutesToday, 0)));
426
+ sentences.push(
427
+ I18n.translate('solar_log_text_active_minutes').replace(
428
+ '%s',
429
+ this._formatNumber(activeMinutesToday, 0),
430
+ ),
431
+ );
421
432
  }
422
433
 
423
434
  if (Number.isFinite(outsideTemp)) {
424
- sentences.push(this._tf('solar_log_text_outside_temp', this._formatNumber(outsideTemp, 1)));
435
+ sentences.push(
436
+ I18n.translate('solar_log_text_outside_temp').replace('%s', this._formatNumber(outsideTemp, 1)),
437
+ );
425
438
  }
426
439
 
427
440
  if (weatherCorrectionActive) {
428
441
  if (weatherTextShort !== '') {
429
- sentences.push(this._tf('solar_log_text_weather_supported_with_text', weatherTextShort));
442
+ sentences.push(
443
+ I18n.translate('solar_log_text_weather_supported_with_text').replace('%s', weatherTextShort),
444
+ );
430
445
  } else {
431
- sentences.push(this._t('solar_log_text_weather_supported'));
446
+ sentences.push(I18n.translate('solar_log_text_weather_supported'));
432
447
  }
433
448
  }
434
449
 
435
450
  if (Number.isFinite(gainTodayWh) && gainTodayWh > 0 && gainTodayWh < 1000 && Number.isFinite(gainTodayKWh)) {
436
- sentences.push(
437
- this._tf(
438
- 'solar_log_text_small_gain_detail',
439
- this._formatNumber(gainTodayWh, 0),
440
- this._formatNumber(gainTodayKWh, 2),
441
- ),
442
- );
451
+ let text = I18n.translate('solar_log_text_small_gain_detail');
452
+ text = text.replace('%s', this._formatNumber(gainTodayWh, 0));
453
+ text = text.replace('%s', this._formatNumber(gainTodayKWh, 2));
454
+ sentences.push(text);
443
455
  }
444
456
 
445
457
  if (qualityLevel !== '') {
446
- sentences.push(this._tf('solar_log_text_quality_level', qualityLevel));
458
+ sentences.push(I18n.translate('solar_log_text_quality_level').replace('%s', qualityLevel));
447
459
  }
448
460
 
449
461
  if (confidenceText !== '') {
450
462
  sentences.push(confidenceText);
451
463
  }
452
464
 
453
- sentences.push(this._tf('solar_log_text_used_sensors', usedSensors));
465
+ sentences.push(I18n.translate('solar_log_text_used_sensors').replace('%s', usedSensors));
454
466
 
455
467
  const text = sentences.join(' ');
456
468
  return {
@@ -549,28 +561,6 @@ const solarLogbookHelper = {
549
561
  .replace(/'/g, '&#39;');
550
562
  },
551
563
 
552
- _t(key) {
553
- try {
554
- return I18n.t(key);
555
- } catch {
556
- return key;
557
- }
558
- },
559
-
560
- _tf(key, ...args) {
561
- try {
562
- let text = I18n.t(key);
563
-
564
- for (const arg of args) {
565
- text = text.replace('%s', String(arg));
566
- }
567
-
568
- return text;
569
- } catch {
570
- return key;
571
- }
572
- },
573
-
574
564
  cleanup() {
575
565
  if (this.checkTimer) {
576
566
  this.adapter.clearTimeout(this.checkTimer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "1.3.3",
3
+ "version": "1.3.6",
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",