iobroker.poolcontrol 0.7.3 → 0.8.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.
@@ -4,10 +4,13 @@
4
4
  * aiStates.js
5
5
  * ----------------------------------------------------------
6
6
  * Definiert alle States für den KI-Bereich des PoolControl-Adapters.
7
- * Struktur:
8
- * ai.switches.*
9
- * ai.schedule.*
10
- * ai.outputs.*
7
+ *
8
+ * Neue Struktur:
9
+ * ai.enabled → globaler KI-Hauptschalter
10
+ *
11
+ * ai.weather.switches.* → Schalter für Wetter-KI
12
+ * ai.weather.schedule.* → Zeitpläne für Wetter-KI
13
+ * ai.weather.outputs.* → Textausgaben der Wetter-KI
11
14
  * ----------------------------------------------------------
12
15
  *
13
16
  * @param {import('iobroker').Adapter} adapter - ioBroker Adapterinstanz
@@ -21,7 +24,9 @@
21
24
  async function createAiStates(adapter) {
22
25
  adapter.log.debug('[aiStates] Initialisierung gestartet');
23
26
 
24
- // Hauptordner
27
+ // ------------------------------------------------------
28
+ // Hauptordner: ai
29
+ // ------------------------------------------------------
25
30
  await adapter.setObjectNotExistsAsync('ai', {
26
31
  type: 'channel',
27
32
  common: { name: 'KI / AI-Funktionen' },
@@ -29,26 +34,67 @@ async function createAiStates(adapter) {
29
34
  });
30
35
 
31
36
  // ------------------------------------------------------
32
- // Unterordner: switches
37
+ // NEU / GEÄNDERT:
38
+ // Globaler KI-Hauptschalter (anstatt ai.switches.enabled)
39
+ // ------------------------------------------------------
40
+ await adapter.setObjectNotExistsAsync('ai.enabled', {
41
+ type: 'state',
42
+ common: {
43
+ name: 'KI aktivieren',
44
+ desc: 'Globaler Hauptschalter für alle KI-Funktionen',
45
+ type: 'boolean',
46
+ role: 'switch',
47
+ read: true,
48
+ write: true,
49
+ def: false,
50
+ persist: true,
51
+ },
52
+ native: {},
53
+ });
54
+
55
+ // ------------------------------------------------------
56
+ // NEU: Wetter-Hauptordner
57
+ // ------------------------------------------------------
58
+ await adapter.setObjectNotExistsAsync('ai.weather', {
59
+ type: 'channel',
60
+ common: {
61
+ name: 'Wetterbezogene KI-Funktionen',
62
+ desc: 'Alle KI-Funktionen rund um Wetter, Vorhersagen und Pooltipps',
63
+ },
64
+ native: {},
65
+ });
66
+
67
+ // ------------------------------------------------------
68
+ // NEU: Unterordner Wetter-Switches
33
69
  // ------------------------------------------------------
34
- await adapter.setObjectNotExistsAsync('ai.switches', {
70
+ await adapter.setObjectNotExistsAsync('ai.weather.switches', {
35
71
  type: 'channel',
36
- common: { name: 'Schalter (KI-Steuerung)' },
72
+ common: {
73
+ name: 'Schalter (Wetter-KI)',
74
+ desc: 'Einzelne Schalter für wetterbezogene KI-Funktionen',
75
+ },
37
76
  native: {},
38
77
  });
39
78
 
40
- const switches = [
41
- { id: 'enabled', name: 'KI aktivieren', def: false },
42
- { id: 'allow_speech', name: 'Sprachausgabe durch KI erlauben', def: false },
79
+ // NEU / GEÄNDERT:
80
+ // Alle bisherigen wetterbezogenen Switches liegen jetzt unter ai.weather.switches.*
81
+ const weatherSwitches = [
82
+ // Steuerung & Debug für Wetter-KI
83
+ { id: 'allow_speech', name: 'Sprachausgabe für Wetter-KI erlauben', def: false }, // GEÄNDERT: von ai.switches → ai.weather.switches
84
+ { id: 'debug_mode', name: 'Debugmodus für Wetter-KI', def: false }, // GEÄNDERT: von ai.switches → ai.weather.switches
85
+
86
+ // Modulspezifische Schalter
43
87
  { id: 'daily_summary_enabled', name: 'Tägliche Zusammenfassung aktiv', def: false },
44
88
  { id: 'daily_pool_tips_enabled', name: 'Tägliche Pool-Tipps aktiv', def: false },
45
89
  { id: 'weather_advice_enabled', name: 'Wetterhinweise aktiv', def: false },
46
90
  { id: 'weekend_summary_enabled', name: 'Wochenende-Zusammenfassung aktiv', def: false },
47
- { id: 'debug_mode', name: 'KI-Debugmodus', def: false },
91
+
92
+ // NEU: Schalter für "Vorhersage für morgen"
93
+ { id: 'tomorrow_forecast_enabled', name: 'Vorhersage für morgen aktiv', def: false }, // NEU
48
94
  ];
49
95
 
50
- for (const s of switches) {
51
- await adapter.setObjectNotExistsAsync(`ai.switches.${s.id}`, {
96
+ for (const s of weatherSwitches) {
97
+ await adapter.setObjectNotExistsAsync(`ai.weather.switches.${s.id}`, {
52
98
  type: 'state',
53
99
  common: {
54
100
  name: s.name,
@@ -64,23 +110,31 @@ async function createAiStates(adapter) {
64
110
  }
65
111
 
66
112
  // ------------------------------------------------------
67
- // Unterordner: schedule
113
+ // NEU: Unterordner Wetter-Schedule
68
114
  // ------------------------------------------------------
69
- await adapter.setObjectNotExistsAsync('ai.schedule', {
115
+ await adapter.setObjectNotExistsAsync('ai.weather.schedule', {
70
116
  type: 'channel',
71
- common: { name: 'Zeitpläne (KI-Ausgaben)' },
117
+ common: {
118
+ name: 'Zeitpläne (Wetter-KI)',
119
+ desc: 'Zeitsteuerung für wetterbezogene KI-Ausgaben',
120
+ },
72
121
  native: {},
73
122
  });
74
123
 
75
- const schedule = [
124
+ // NEU / GEÄNDERT:
125
+ // Alle Zeitpläne liegen jetzt unter ai.weather.schedule.*
126
+ const weatherSchedule = [
76
127
  { id: 'daily_summary_time', name: 'Zeit für tägliche Zusammenfassung', def: '09:00' },
77
128
  { id: 'daily_pool_tips_time', name: 'Zeit für tägliche Pool-Tipps', def: '10:00' },
78
129
  { id: 'weather_advice_time', name: 'Zeit für Wetterhinweise', def: '08:00' },
79
130
  { id: 'weekend_summary_time', name: 'Zeit für Wochenend-Zusammenfassung', def: '18:00' },
131
+
132
+ // NEU: Zeitplan für "Vorhersage für morgen"
133
+ { id: 'tomorrow_forecast_time', name: 'Zeit für morgige Vorhersage', def: '19:00' }, // NEU
80
134
  ];
81
135
 
82
- for (const t of schedule) {
83
- await adapter.setObjectNotExistsAsync(`ai.schedule.${t.id}`, {
136
+ for (const t of weatherSchedule) {
137
+ await adapter.setObjectNotExistsAsync(`ai.weather.schedule.${t.id}`, {
84
138
  type: 'state',
85
139
  common: {
86
140
  name: t.name,
@@ -96,24 +150,34 @@ async function createAiStates(adapter) {
96
150
  }
97
151
 
98
152
  // ------------------------------------------------------
99
- // Unterordner: outputs
153
+ // NEU: Unterordner Wetter-Outputs
100
154
  // ------------------------------------------------------
101
- await adapter.setObjectNotExistsAsync('ai.outputs', {
155
+ await adapter.setObjectNotExistsAsync('ai.weather.outputs', {
102
156
  type: 'channel',
103
- common: { name: 'KI-Ausgaben (Texte)' },
157
+ common: {
158
+ name: 'KI-Ausgaben (Wetter-Texte)',
159
+ desc: 'Textausgaben der Wetter-KI (Hinweise, Tipps, Zusammenfassungen)',
160
+ },
104
161
  native: {},
105
162
  });
106
163
 
107
- const outputs = [
164
+ // NEU / GEÄNDERT:
165
+ // Alle bisherigen Ausgaben + neue Vorhersage + last_message unter ai.weather.outputs.*
166
+ const weatherOutputs = [
108
167
  { id: 'daily_summary', name: 'Tägliche Zusammenfassung' },
109
168
  { id: 'pool_tips', name: 'Pool-Tipps' },
110
169
  { id: 'weather_advice', name: 'Wetterhinweise' },
111
170
  { id: 'weekend_summary', name: 'Wochenende-Zusammenfassung' },
112
- { id: 'last_message', name: 'Letzte KI-Meldung' },
171
+
172
+ // NEU: Ausgabefeld für die Vorhersage für morgen
173
+ { id: 'tomorrow_forecast', name: 'Vorhersage für morgen' }, // NEU
174
+
175
+ // GEÄNDERT: last_message gehört aktuell zur Wetter-KI
176
+ { id: 'last_message', name: 'Letzte Wetter-KI-Meldung' }, // GEÄNDERT: von ai.outputs → ai.weather.outputs
113
177
  ];
114
178
 
115
- for (const o of outputs) {
116
- await adapter.setObjectNotExistsAsync(`ai.outputs.${o.id}`, {
179
+ for (const o of weatherOutputs) {
180
+ await adapter.setObjectNotExistsAsync(`ai.weather.outputs.${o.id}`, {
117
181
  type: 'state',
118
182
  common: {
119
183
  name: o.name,
@@ -277,7 +277,16 @@ async function createControlStates(adapter) {
277
277
  } catch (err) {
278
278
  adapter.log.warn(`[controlStates] persist-Flag für control.circulation.mode nicht gesetzt: ${err.message}`);
279
279
  }
280
- await adapter.setStateAsync('control.circulation.mode', { val: 'notify', ack: true });
280
+
281
+ // FIX: Default nur setzen, wenn noch kein Wert existiert (Überinstall-Schutz)
282
+ const existingCirculationMode = await adapter.getStateAsync('control.circulation.mode');
283
+ if (
284
+ existingCirculationMode === null ||
285
+ existingCirculationMode.val === null ||
286
+ existingCirculationMode.val === undefined
287
+ ) {
288
+ await adapter.setStateAsync('control.circulation.mode', { val: 'notify', ack: true });
289
+ }
281
290
 
282
291
  // Prüfzeitpunkt (mit Persist-Schutz)
283
292
  await adapter.setObjectNotExistsAsync('control.circulation.check_time', {
package/main.js CHANGED
@@ -22,6 +22,7 @@ const frostHelper = require('./lib/helpers/frostHelper');
22
22
  const statusHelper = require('./lib/helpers/statusHelper');
23
23
  const photovoltaicHelper = require('./lib/helpers/photovoltaicHelper');
24
24
  const aiHelper = require('./lib/helpers/aiHelper');
25
+ const aiForecastHelper = require('./lib/helpers/aiForecastHelper');
25
26
  const controlHelper = require('./lib/helpers/controlHelper');
26
27
  const controlHelper2 = require('./lib/helpers/controlHelper2');
27
28
  const debugLogHelper = require('./lib/helpers/debugLogHelper');
@@ -133,7 +134,8 @@ class Poolcontrol extends utils.Adapter {
133
134
  consumptionHelper.init(this);
134
135
  solarHelper.init(this);
135
136
  photovoltaicHelper.init(this);
136
- aiHelper.init(this);
137
+ aiHelper.init(this);
138
+ aiForecastHelper.init(this);
137
139
  frostHelper.init(this);
138
140
  statusHelper.init(this);
139
141
  infoHelper.init(this);
@@ -193,9 +195,12 @@ class Poolcontrol extends utils.Adapter {
193
195
  if (speechTextHelper.cleanup) {
194
196
  speechTextHelper.cleanup();
195
197
  }
196
- if (aiHelper.cleanup) {
198
+ if (aiHelper.cleanup) {
197
199
  aiHelper.cleanup();
198
200
  }
201
+ if (aiForecastHelper.cleanup) {
202
+ aiForecastHelper.cleanup();
203
+ }
199
204
  if (infoHelper.cleanup) {
200
205
  infoHelper.cleanup();
201
206
  }
@@ -267,12 +272,17 @@ class Poolcontrol extends utils.Adapter {
267
272
  } catch (e) {
268
273
  this.log.warn(`[photovoltaicHelper] Fehler in handleStateChange: ${e.message}`);
269
274
  }
270
- // --- AI-Helper ---
275
+ // --- AI-Helper ---
271
276
  try {
272
277
  aiHelper.handleStateChange(id, state);
273
278
  } catch (e) {
274
279
  this.log.warn(`[main] Fehler in aiHelper.handleStateChange: ${e.message}`);
275
280
  }
281
+ try {
282
+ aiForecastHelper.handleStateChange(id, state);
283
+ } catch (e) {
284
+ this.log.warn(`[main] Fehler in aiForecastHelper.handleStateChange: ${e.message}`);
285
+ }
276
286
  try {
277
287
  statusHelper.handleStateChange(id, state);
278
288
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "0.7.3",
3
+ "version": "0.8.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",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "https://github.com/DasBo1975/ioBroker.poolcontrol.git"
18
+ "url": "git+https://github.com/DasBo1975/ioBroker.poolcontrol.git"
19
19
  },
20
20
  "engines": {
21
21
  "node": ">= 20"