iobroker.poolcontrol 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "poolcontrol",
4
- "version": "0.9.0",
4
+ "version": "0.9.1",
5
5
  "news": {
6
+ "0.9.1": {
7
+ "en": "Extended heating / heat pump control (heatHelper) with configurable pump pre-run before heating start. The pump can now be started a defined time before the heater is activated to ensure sufficient water flow and pressure (e.g. for heat pumps). Includes new states for pre-run timing and status, fully integrated into the existing priority, ownership, and safety logic.",
8
+ "de": "Erweiterte Heizungs- / Wärmepumpensteuerung (heatHelper) um eine konfigurierbare Pumpen-Vorlaufzeit vor Heizstart. Die Pumpe kann nun für eine definierte Zeit vor dem Einschalten der Heizung gestartet werden, um ausreichend Wasserdurchfluss und Druck sicherzustellen (z. B. bei Wärmepumpen). Enthält neue Datenpunkte für Vorlaufzeit und Vorlaufstatus, vollständig integriert in die bestehende Vorrangs-, Ownership- und Sicherheitslogik.",
9
+ "ru": "Расширенная система управления отоплением / тепловым насосом (heatHelper) с настраиваемым предварительным запуском насоса перед началом нагрева. Насос может запускаться за заданное время до включения отопления для обеспечения достаточного потока и давления воды (например, для тепловых насосов). Добавлены новые состояния для времени предварительного запуска и его статуса, полностью интегрированные в существующую логику приоритетов, владения и безопасности.",
10
+ "pt": "Controlo de aquecimento / bomba de calor (heatHelper) alargado com pré-funcionamento configurável da bomba antes do início do aquecimento. A bomba pode agora ser ligada durante um período definido antes da ativação do aquecedor para garantir caudal e pressão de água suficientes (por exemplo, em bombas de calor). Inclui novos estados para tempo e estado do pré-funcionamento, totalmente integrados na lógica existente de prioridades, propriedade e segurança.",
11
+ "nl": "Uitgebreide verwarmings- / warmtepompregeling (heatHelper) met configureerbare pomp-voorloop vóór de start van de verwarming. De pomp kan nu een ingestelde tijd vóór het inschakelen van de verwarming worden gestart om voldoende waterdoorstroming en druk te garanderen (bijv. voor warmtepompen). Bevat nieuwe states voor voorlooptijd en -status, volledig geïntegreerd in de bestaande prioriteits-, eigendoms- en veiligheidslogica.",
12
+ "fr": "Extension du contrôle de chauffage / pompe à chaleur (heatHelper) avec un préfonctionnement configurable de la pompe avant le démarrage du chauffage. La pompe peut désormais être démarrée un temps défini avant l’activation du chauffage afin d’assurer un débit et une pression d’eau suffisants (par ex. pour les pompes à chaleur). Ajout de nouveaux états pour la durée et le statut du préfonctionnement, entièrement intégrés à la logique existante de priorité, de propriété et de sécurité.",
13
+ "it": "Controllo di riscaldamento / pompa di calore (heatHelper) esteso con pre-avviamento configurabile della pompa prima dell’inizio del riscaldamento. La pompa può ora essere avviata per un periodo definito prima dell’attivazione del riscaldamento per garantire un flusso e una pressione dell’acqua sufficienti (ad es. per le pompe di calore). Include nuovi stati per il tempo e lo stato del pre-avviamento, completamente integrati nella logica esistente di priorità, proprietà e sicurezza.",
14
+ "es": "Control de calefacción / bomba de calor (heatHelper) ampliado con prefuncionamiento configurable de la bomba antes del inicio de la calefacción. La bomba puede iniciarse ahora durante un tiempo definido antes de activar la calefacción para garantizar un caudal y una presión de agua suficientes (p. ej., para bombas de calor). Incluye nuevos estados para el tiempo y el estado del prefuncionamiento, totalmente integrados en la lógica existente de prioridades, propiedad y seguridad.",
15
+ "pl": "Rozszerzony system sterowania ogrzewaniem / pompą ciepła (heatHelper) o konfigurowalny wstępny bieg pompy przed rozpoczęciem grzania. Pompa może być uruchamiana na określony czas przed włączeniem ogrzewania w celu zapewnienia odpowiedniego przepływu i ciśnienia wody (np. dla pomp ciepła). Dodano nowe stany dla czasu i statusu biegu wstępnego, w pełni zintegrowane z istniejącą logiką priorytetów, własności i bezpieczeństwa.",
16
+ "uk": "Розширене керування опаленням / тепловим насосом (heatHelper) з налаштовуваним попереднім запуском насоса перед початком нагріву. Насос може запускатися за визначений час до увімкнення опалення для забезпечення достатнього потоку та тиску води (наприклад, для теплових насосів). Додано нові стани для часу та статусу попереднього запуску, повністю інтегровані в існуючу логіку пріоритетів, володіння та безпеки.",
17
+ "zh-cn": "扩展了加热 / 热泵控制功能(heatHelper),新增可配置的加热前水泵预运行时间。水泵可在加热设备启动前提前运行一段时间,以确保足够的水流和水压(例如用于热泵)。新增了预运行时间和状态的数据点,已完全集成到现有的优先级、所有权和安全逻辑中。"
18
+ },
6
19
  "0.9.0": {
7
20
  "en": "New heating / heat pump control (heatHelper). Automatic control based on pool temperature with configurable target and maximum temperature, pump after-run time, and full priority handling (e.g. maintenance mode). Works only in automatic pump mode and respects season status. Supports both switchable sockets and boolean control states. Includes ownership protection to avoid interfering with other pump controllers.",
8
21
  "de": "Neue Heizungs- / Wärmepumpensteuerung (heatHelper). Automatische Regelung basierend auf der Pooltemperatur mit konfigurierbarer Ziel- und Maximaltemperatur, Pumpen-Nachlaufzeit sowie vollständiger Vorranglogik (z. B. Wartungsmodus). Arbeitet ausschließlich im Automatikmodus der Pumpe und berücksichtigt den Saisonstatus. Unterstützt schaltbare Steckdosen und boolesche Steuer-States. Enthält Ownership-Schutz, um Konflikte mit anderen Pumpensteuerungen zu vermeiden.",
@@ -80,19 +93,6 @@
80
93
  "pl": "Poprawka pozdrowień sezonowych: życzenia świąteczne pojawiają się teraz prawidłowo tylko między 20 a 27 grudnia. Błędna przedwczesna aktywacja została naprawiona.",
81
94
  "uk": "Виправлено сезонні вітання: Різдвяне привітання тепер з’являється лише з 20 по 27 грудня. Помилкове передчасне спрацьовування виправлено.",
82
95
  "zh-cn": "修复季节性问候:圣诞问候现在仅在 12 月 20 日至 27 日之间显示。已修复错误的提前触发问题。"
83
- },
84
- "0.7.2": {
85
- "en": "Added new info system: The adapter now writes seasonal greetings and the installed adapter version to info.* states. Includes automatic daily refresh at 00:01 and full Easter date calculation.",
86
- "de": "Neues Info-System hinzugefügt: Der Adapter schreibt nun saisonale Grüße und die installierte Adapterversion in die info.* States. Enthält eine automatische tägliche Aktualisierung um 00:01 sowie eine vollständige Oster-Berechnung.",
87
- "ru": "Добавлена новая информационная система: адаптер теперь записывает сезонные поздравления и установленную версию адаптера в состояния info.*. Включает ежедневное обновление в 00:01 и полный расчёт даты Пасхи.",
88
- "pt": "Novo sistema de informações adicionado: o adaptador agora grava saudações sazonais e a versão instalada do adaptador nos estados info.*. Inclui atualização diária automática às 00:01 e cálculo completo da data da Páscoa.",
89
- "nl": "Nieuw infosysteem toegevoegd: de adapter schrijft nu seizoensgroeten en de geïnstalleerde adapterversie naar info.*-states. Inclusief automatische dagelijkse update om 00:01 en volledige berekening van Pasen.",
90
- "fr": "Nouveau système d'informations ajouté : l'adaptateur écrit désormais des messages saisonniers et la version installée dans les états info.*. Comprend une mise à jour quotidienne automatique à 00:01 et un calcul complet de la date de Pâques.",
91
- "it": "Aggiunto nuovo sistema informativo: l'adattatore ora scrive i saluti stagionali e la versione installata negli stati info.*. Include aggiornamento giornaliero automatico alle 00:01 e calcolo completo della data di Pasqua.",
92
- "es": "Nuevo sistema de información añadido: el adaptador ahora escribe saludos estacionales y la versión instalada en los estados info.*. Incluye actualización automática diaria a las 00:01 y cálculo completo de la fecha de Pascua.",
93
- "pl": "Dodano nowy system informacji: adapter zapisuje teraz sezonowe pozdrowienia oraz zainstalowaną wersję adaptera w stanach info.*. Zawiera automatyczne codzienne odświeżanie o 00:01 oraz pełne wyliczenie daty Wielkanocy.",
94
- "uk": "Додано нову інформаційну систему: адаптер тепер записує сезонні привітання та встановлену версію адаптера в стани info.*. Містить щоденне автоматичне оновлення о 00:01 і повний розрахунок дати Великодня.",
95
- "zh-cn": "新增信息系统:适配器现在会将季节性问候和已安装的适配器版本写入 info.* 状态。包括每天 00:01 的自动刷新和完整的复活节日期计算。"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -24,6 +24,7 @@ const heatHelper = {
24
24
  // dynamische Steuer-ID (foreign)
25
25
  _heatControlForeignId: '',
26
26
  _afterrunTimer: null,
27
+ _prerunTimer: null, // NEU: Pumpen-Vorlauf vor Heizstart
27
28
 
28
29
  // Ownership / Merker
29
30
  _ownsPump: false,
@@ -40,6 +41,7 @@ const heatHelper = {
40
41
  this.adapter.subscribeStates('heat.target_temperature');
41
42
  this.adapter.subscribeStates('heat.max_temperature');
42
43
  this.adapter.subscribeStates('heat.pump_afterrun_minutes');
44
+ this.adapter.subscribeStates('heat.pump_prerun_minutes'); // NEU
43
45
 
44
46
  // Abhängigkeiten
45
47
  this.adapter.subscribeStates('status.season_active');
@@ -81,7 +83,8 @@ const heatHelper = {
81
83
  id.endsWith('status.season_active') ||
82
84
  id.endsWith('pump.mode') ||
83
85
  id.endsWith('temperature.surface.current') ||
84
- id.endsWith('control.pump.maintenance_active')
86
+ id.endsWith('control.pump.maintenance_active') ||
87
+ id.endsWith('heat.pump_prerun_minutes')
85
88
  ) {
86
89
  await this._safeEvaluate('state_change');
87
90
  return;
@@ -216,6 +219,46 @@ const heatHelper = {
216
219
  return;
217
220
  }
218
221
 
222
+ // -------------------------------------------------
223
+ // NEU: Pumpen-Prerun vor Heizstart
224
+ // -------------------------------------------------
225
+ const prerunMin = Math.max(
226
+ 0,
227
+ Number((await this.adapter.getStateAsync('heat.pump_prerun_minutes'))?.val ?? 0) || 0,
228
+ );
229
+
230
+ const pumpState = await this.adapter.getStateAsync('pump.pump_switch');
231
+ const pumpIsOn = !!pumpState?.val;
232
+
233
+ // Prerun nur, wenn:
234
+ // - Zeit > 0
235
+ // - Pumpe aktuell AUS
236
+ // - kein Prerun aktiv
237
+ if (prerunMin > 0 && !pumpIsOn && !this._prerunTimer) {
238
+ this.adapter.log.info(`[heatHelper] Starte Pumpen-Prerun (${prerunMin} min)`);
239
+
240
+ // Pumpe einschalten + Ownership übernehmen
241
+ this._ownsPump = true;
242
+ await this.adapter.setStateAsync('pump.pump_switch', { val: true, ack: false });
243
+
244
+ // Prerun-Status setzen
245
+ await this.adapter.setStateAsync('heat.prerun_active', { val: true, ack: true });
246
+
247
+ const holdMs = Math.round(prerunMin * 60 * 1000);
248
+
249
+ this._prerunTimer = setTimeout(async () => {
250
+ this._prerunTimer = null;
251
+
252
+ await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
253
+
254
+ // Nach Prerun erneut bewerten → Heizung darf jetzt starten
255
+ await this._safeEvaluate('prerun_done');
256
+ }, holdMs);
257
+
258
+ // WICHTIG: Heizung JETZT noch NICHT einschalten
259
+ return;
260
+ }
261
+
219
262
  this._desiredHeat = true;
220
263
 
221
264
  // Nachlauf ggf. abbrechen
@@ -278,6 +321,13 @@ const heatHelper = {
278
321
  },
279
322
 
280
323
  async _applyBlockedState(mode, reason, afterrunMin) {
324
+ // NEU: laufenden Prerun abbrechen
325
+ if (this._prerunTimer) {
326
+ clearTimeout(this._prerunTimer);
327
+ this._prerunTimer = null;
328
+ await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
329
+ }
330
+
281
331
  // blockiert => Heizung aus, Request false
282
332
  await this._setHeatingDevice(false, (await this.adapter.getStateAsync('heat.control_object_id'))?.val || '');
283
333
 
@@ -295,6 +345,13 @@ const heatHelper = {
295
345
  },
296
346
 
297
347
  async _applyOffState(mode, reason, afterrunMin) {
348
+ // NEU: laufenden Prerun abbrechen
349
+ if (this._prerunTimer) {
350
+ clearTimeout(this._prerunTimer);
351
+ this._prerunTimer = null;
352
+ await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
353
+ }
354
+
298
355
  // off => Heizung aus, Request false
299
356
  await this._setHeatingDevice(false, (await this.adapter.getStateAsync('heat.control_object_id'))?.val || '');
300
357
 
@@ -371,6 +428,7 @@ const heatHelper = {
371
428
  } finally {
372
429
  this._ownsPump = false;
373
430
  await this.adapter.setStateAsync('heat.afterrun_active', { val: false, ack: true });
431
+ await this.adapter.setStateAsync('heat.prerun_active', { val: false, ack: true });
374
432
  this.adapter.log.info(`[heatHelper] Pumpe AUS (${tag})`);
375
433
  }
376
434
  },
@@ -442,6 +500,11 @@ const heatHelper = {
442
500
  clearTimeout(this._afterrunTimer);
443
501
  this._afterrunTimer = null;
444
502
  }
503
+ if (this._prerunTimer) {
504
+ clearTimeout(this._prerunTimer);
505
+ this._prerunTimer = null;
506
+ }
507
+
445
508
  this._ownsPump = false;
446
509
  this._desiredHeat = null;
447
510
  },
@@ -9,6 +9,15 @@
9
9
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
10
10
  */
11
11
  async function createGeneralStates(adapter) {
12
+ // Channel: Allgemein
13
+ await adapter.setObjectNotExistsAsync('general', {
14
+ type: 'channel',
15
+ common: {
16
+ name: 'Allgemeine Einstellungen',
17
+ },
18
+ native: {},
19
+ });
20
+
12
21
  // Poolname
13
22
  await adapter.setObjectNotExistsAsync('general.pool_name', {
14
23
  type: 'state',
@@ -129,6 +129,28 @@ async function createHeatStates(adapter) {
129
129
  });
130
130
  }
131
131
 
132
+ // --- NEU: Pumpen-Vorlaufzeit vor Heizstart ---
133
+ await adapter.setObjectNotExistsAsync(`${channelId}.pump_prerun_minutes`, {
134
+ type: 'state',
135
+ common: {
136
+ name: 'Pumpen-Vorlaufzeit vor Heizung',
137
+ type: 'number',
138
+ role: 'value.interval',
139
+ unit: 'min',
140
+ read: true,
141
+ write: true,
142
+ persist: true,
143
+ },
144
+ native: {},
145
+ });
146
+ const existingPrerun = await adapter.getStateAsync(`${channelId}.pump_prerun_minutes`);
147
+ if (existingPrerun === null || existingPrerun.val === null || existingPrerun.val === undefined) {
148
+ await adapter.setStateAsync(`${channelId}.pump_prerun_minutes`, {
149
+ val: 0,
150
+ ack: true,
151
+ });
152
+ }
153
+
132
154
  await adapter.setObjectNotExistsAsync(`${channelId}.pump_afterrun_minutes`, {
133
155
  type: 'state',
134
156
  common: {
@@ -190,6 +212,19 @@ async function createHeatStates(adapter) {
190
212
  native: {},
191
213
  });
192
214
 
215
+ // --- NEU: Pumpen-Vorlauf aktiv ---
216
+ await adapter.setObjectNotExistsAsync(`${channelId}.prerun_active`, {
217
+ type: 'state',
218
+ common: {
219
+ name: 'Pumpen-Vorlauf aktiv',
220
+ type: 'boolean',
221
+ role: 'indicator.working',
222
+ read: true,
223
+ write: false,
224
+ },
225
+ native: {},
226
+ });
227
+
193
228
  await adapter.setObjectNotExistsAsync(`${channelId}.afterrun_active`, {
194
229
  type: 'state',
195
230
  common: {
@@ -13,6 +13,15 @@
13
13
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
14
14
  */
15
15
  async function createPumpStates(adapter) {
16
+ // Channel: Pumpe
17
+ await adapter.setObjectNotExistsAsync('pump', {
18
+ type: 'channel',
19
+ common: {
20
+ name: 'Pumpe',
21
+ },
22
+ native: {},
23
+ });
24
+
16
25
  // Max. Pumpenleistung (W)
17
26
  await adapter.setObjectNotExistsAsync('pump.pump_max_watt', {
18
27
  type: 'state',
@@ -14,6 +14,15 @@
14
14
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
15
15
  */
16
16
  async function createSolarStates(adapter) {
17
+ // Channel: Solar
18
+ await adapter.setObjectNotExistsAsync('solar', {
19
+ type: 'channel',
20
+ common: {
21
+ name: 'Solar',
22
+ },
23
+ native: {},
24
+ });
25
+
17
26
  // Solarsteuerung aktiv (mit Persist-Schutz)
18
27
  await adapter.setObjectNotExistsAsync('solar.solar_control_active', {
19
28
  type: 'state',
@@ -9,6 +9,15 @@
9
9
  * @param {import("iobroker").Adapter} adapter - ioBroker Adapter-Instanz
10
10
  */
11
11
  async function createTimeStates(adapter) {
12
+ // Channel: Zeitsteuerung
13
+ await adapter.setObjectNotExistsAsync('timecontrol', {
14
+ type: 'channel',
15
+ common: {
16
+ name: 'Zeitsteuerung',
17
+ },
18
+ native: {},
19
+ });
20
+
12
21
  async function createTimeWindow(prefix, label) {
13
22
  // Aktiv
14
23
  await adapter.setObjectNotExistsAsync(`timecontrol.${prefix}_active`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Steuerung & Automatisierung für den Pool (Pumpe, Heizung, Ventile, Sensoren).",
5
5
  "author": "DasBo1975 <dasbo1975@outlook.de>",
6
6
  "homepage": "https://github.com/DasBo1975/ioBroker.poolcontrol",