iobroker.poolcontrol 1.2.0 → 1.2.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/README.md +285 -292
- package/admin/i18n/de/translations.json +158 -4
- package/admin/i18n/en/translations.json +161 -3
- package/admin/i18n/es/translations.json +158 -4
- package/admin/i18n/fr/translations.json +158 -4
- package/admin/i18n/it/translations.json +158 -4
- package/admin/i18n/nl/translations.json +158 -4
- package/admin/i18n/pl/translations.json +158 -4
- package/admin/i18n/pt/translations.json +158 -4
- package/admin/i18n/ru/translations.json +158 -4
- package/admin/i18n/uk/translations.json +158 -4
- package/admin/i18n/zh-cn/translations.json +158 -4
- package/admin/jsonConfig.json +180 -602
- package/io-package.json +107 -100
- package/lib/helpers/actuatorsHelper.js +6 -8
- package/lib/helpers/aiChemistryHelpHelper.js +7 -7
- package/lib/helpers/aiForecastHelper.js +21 -21
- package/lib/helpers/aiHelper.js +53 -63
- package/lib/helpers/consumptionHelper.js +23 -25
- package/lib/helpers/controlHelper.js +24 -24
- package/lib/helpers/controlHelper2.js +17 -17
- package/lib/helpers/debugLogHelper.js +12 -14
- package/lib/helpers/frostHelper.js +6 -6
- package/lib/helpers/heatHelper.js +14 -14
- package/lib/helpers/infoHelper.js +2 -2
- package/lib/helpers/migrationHelper.js +16 -16
- package/lib/helpers/photovoltaicHelper.js +28 -28
- package/lib/helpers/pumpHelper.js +16 -18
- package/lib/helpers/pumpHelper2.js +8 -10
- package/lib/helpers/pumpHelper3.js +9 -9
- package/lib/helpers/pumpHelper4.js +9 -9
- package/lib/helpers/pumpSpeedHelper.js +6 -6
- package/lib/helpers/runtimeHelper.js +14 -14
- package/lib/helpers/solarHelper.js +9 -9
- package/lib/helpers/speechHelper.js +13 -15
- package/lib/helpers/speechTextHelper.js +13 -13
- package/lib/helpers/statisticsHelper.js +9 -9
- package/lib/helpers/statisticsHelperMonth.js +15 -15
- package/lib/helpers/statisticsHelperWeek.js +11 -11
- package/lib/helpers/statusHelper.js +9 -9
- package/lib/helpers/temperatureHelper.js +9 -11
- package/lib/helpers/timeHelper.js +7 -9
- package/lib/stateDefinitions/actuatorsStates.js +19 -19
- package/lib/stateDefinitions/aiChemistryHelpStates.js +59 -28
- package/lib/stateDefinitions/aiStates.js +119 -31
- package/lib/stateDefinitions/consumptionStates.js +20 -14
- package/lib/stateDefinitions/controlStates.js +90 -37
- package/lib/stateDefinitions/debugLogStates.js +28 -13
- package/lib/stateDefinitions/generalStates.js +4 -4
- package/lib/stateDefinitions/heatStates.js +21 -21
- package/lib/stateDefinitions/infoStates.js +11 -5
- package/lib/stateDefinitions/photovoltaicStates.js +52 -24
- package/lib/stateDefinitions/pumpSpeedStates.js +11 -11
- package/lib/stateDefinitions/pumpStates.js +24 -15
- package/lib/stateDefinitions/pumpStates2.js +22 -10
- package/lib/stateDefinitions/pumpStates3.js +63 -24
- package/lib/stateDefinitions/pumpStates4.js +62 -32
- package/lib/stateDefinitions/runtimeStates.js +10 -10
- package/lib/stateDefinitions/solarStates.js +9 -9
- package/lib/stateDefinitions/speechStates.js +24 -21
- package/lib/stateDefinitions/statisticsStates.js +107 -29
- package/lib/stateDefinitions/statusStates.js +14 -12
- package/lib/stateDefinitions/temperatureStates.js +18 -12
- package/lib/stateDefinitions/timeStates.js +5 -5
- package/main.js +38 -0
- package/package.json +7 -8
|
@@ -38,7 +38,7 @@ const aiChemistryHelpHelper = {
|
|
|
38
38
|
*/
|
|
39
39
|
async init(adapter) {
|
|
40
40
|
this.adapter = adapter;
|
|
41
|
-
this.adapter.log.info('[aiChemistryHelpHelper]
|
|
41
|
+
this.adapter.log.info('[aiChemistryHelpHelper] initialization started');
|
|
42
42
|
|
|
43
43
|
// NEU: auf Auswahländerungen reagieren
|
|
44
44
|
this.adapter.subscribeStates('ai.chemistry_help.issue');
|
|
@@ -50,10 +50,10 @@ const aiChemistryHelpHelper = {
|
|
|
50
50
|
await this._processIssue(String(st.val));
|
|
51
51
|
}
|
|
52
52
|
} catch (e) {
|
|
53
|
-
this.adapter.log.debug(`[aiChemistryHelpHelper]
|
|
53
|
+
this.adapter.log.debug(`[aiChemistryHelpHelper] init: could not read issue: ${e.message}`);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
this.adapter.log.info('[aiChemistryHelpHelper]
|
|
56
|
+
this.adapter.log.info('[aiChemistryHelpHelper] initialization finished');
|
|
57
57
|
},
|
|
58
58
|
|
|
59
59
|
/**
|
|
@@ -61,7 +61,7 @@ const aiChemistryHelpHelper = {
|
|
|
61
61
|
*/
|
|
62
62
|
cleanup() {
|
|
63
63
|
// aktuell keine Timer / Intervalle
|
|
64
|
-
this.adapter && this.adapter.log.debug('[aiChemistryHelpHelper]
|
|
64
|
+
this.adapter && this.adapter.log.debug('[aiChemistryHelpHelper] cleanup finished');
|
|
65
65
|
},
|
|
66
66
|
|
|
67
67
|
/**
|
|
@@ -101,12 +101,12 @@ const aiChemistryHelpHelper = {
|
|
|
101
101
|
issue = obj.common.states[state.val] || 'none';
|
|
102
102
|
}
|
|
103
103
|
} catch (e) {
|
|
104
|
-
this.adapter.log.debug(`[aiChemistryHelpHelper]
|
|
104
|
+
this.adapter.log.debug(`[aiChemistryHelpHelper] could not resolve enum text: ${e.message}`);
|
|
105
105
|
}
|
|
106
106
|
} else {
|
|
107
107
|
issue = String(state.val || 'none');
|
|
108
108
|
}
|
|
109
|
-
this.adapter.log.debug(`[aiChemistryHelpHelper]
|
|
109
|
+
this.adapter.log.debug(`[aiChemistryHelpHelper] selection changed: ${issue}`);
|
|
110
110
|
|
|
111
111
|
await this._processIssue(issue);
|
|
112
112
|
},
|
|
@@ -384,7 +384,7 @@ const aiChemistryHelpHelper = {
|
|
|
384
384
|
|
|
385
385
|
await this.adapter.setStateAsync(id, { val: value, ack: true });
|
|
386
386
|
} catch (e) {
|
|
387
|
-
this.adapter.log.debug(`[aiChemistryHelpHelper] _setStateIfChanged
|
|
387
|
+
this.adapter.log.debug(`[aiChemistryHelpHelper] _setStateIfChanged error (${id}): ${e.message}`);
|
|
388
388
|
}
|
|
389
389
|
},
|
|
390
390
|
};
|
|
@@ -34,7 +34,7 @@ const aiForecastHelper = {
|
|
|
34
34
|
*/
|
|
35
35
|
async init(adapter) {
|
|
36
36
|
this.adapter = adapter;
|
|
37
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
37
|
+
this.adapter.log.info('[aiForecastHelper] initialization started');
|
|
38
38
|
|
|
39
39
|
await this._refreshTimer();
|
|
40
40
|
|
|
@@ -48,15 +48,15 @@ const aiForecastHelper = {
|
|
|
48
48
|
// ----------------------------------------------------------
|
|
49
49
|
const enabled = await this._getBool('ai.weather.switches.tomorrow_forecast_enabled', false);
|
|
50
50
|
if (enabled) {
|
|
51
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
51
|
+
this.adapter.log.info('[aiForecastHelper] running one-time immediate forecast (adapter start)');
|
|
52
52
|
try {
|
|
53
53
|
await this._runForecast();
|
|
54
54
|
} catch (err) {
|
|
55
|
-
this.adapter.log.warn(`[aiForecastHelper]
|
|
55
|
+
this.adapter.log.warn(`[aiForecastHelper] error during immediate forecast: ${err.message}`);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
59
|
+
this.adapter.log.info('[aiForecastHelper] initialization finished');
|
|
60
60
|
},
|
|
61
61
|
|
|
62
62
|
/**
|
|
@@ -67,7 +67,7 @@ const aiForecastHelper = {
|
|
|
67
67
|
clearInterval(this.timer);
|
|
68
68
|
this.timer = null;
|
|
69
69
|
}
|
|
70
|
-
this.adapter && this.adapter.log.debug('[aiForecastHelper]
|
|
70
|
+
this.adapter && this.adapter.log.debug('[aiForecastHelper] cleanup finished');
|
|
71
71
|
},
|
|
72
72
|
|
|
73
73
|
/**
|
|
@@ -95,15 +95,15 @@ const aiForecastHelper = {
|
|
|
95
95
|
// NEU: Sofortige Ausführung, wenn der Forecast aktiviert wird
|
|
96
96
|
// ----------------------------------------------------------
|
|
97
97
|
if (id.endsWith('ai.weather.switches.tomorrow_forecast_enabled') && state.val === true) {
|
|
98
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
98
|
+
this.adapter.log.info('[aiForecastHelper] forecast enabled -> one-time immediate run');
|
|
99
99
|
try {
|
|
100
100
|
await this._runForecast();
|
|
101
101
|
} catch (err) {
|
|
102
|
-
this.adapter.log.warn(`[aiForecastHelper]
|
|
102
|
+
this.adapter.log.warn(`[aiForecastHelper] error during immediate run: ${err.message}`);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
this.adapter.log.info(`[aiForecastHelper]
|
|
106
|
+
this.adapter.log.info(`[aiForecastHelper] change detected: ${id} = ${state.val}`);
|
|
107
107
|
await this._refreshTimer();
|
|
108
108
|
},
|
|
109
109
|
|
|
@@ -121,14 +121,14 @@ const aiForecastHelper = {
|
|
|
121
121
|
this._debugMode = await this._getBool('ai.weather.switches.debug_mode', false);
|
|
122
122
|
|
|
123
123
|
if (!enabled) {
|
|
124
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
124
|
+
this.adapter.log.info('[aiForecastHelper] forecast disabled - no timer active');
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
const time = await this._getTimeOrDefault('ai.weather.schedule.tomorrow_forecast_time', '19:00');
|
|
129
129
|
|
|
130
130
|
this.adapter.log.info(
|
|
131
|
-
`[aiForecastHelper]
|
|
131
|
+
`[aiForecastHelper] forecast timer set for ${time.hour}:${String(time.minute).padStart(2, '0')}`,
|
|
132
132
|
);
|
|
133
133
|
|
|
134
134
|
// minütlicher Check
|
|
@@ -138,7 +138,7 @@ const aiForecastHelper = {
|
|
|
138
138
|
try {
|
|
139
139
|
await this._runForecast();
|
|
140
140
|
} catch (err) {
|
|
141
|
-
this.adapter.log.warn(`[aiForecastHelper]
|
|
141
|
+
this.adapter.log.warn(`[aiForecastHelper] timer error: ${err.message}`);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
}, 60 * 1000);
|
|
@@ -149,17 +149,17 @@ const aiForecastHelper = {
|
|
|
149
149
|
// ---------------------------------------------------------------------
|
|
150
150
|
async _runForecast() {
|
|
151
151
|
try {
|
|
152
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
152
|
+
this.adapter.log.info('[aiForecastHelper] creating forecast for tomorrow ...');
|
|
153
153
|
|
|
154
154
|
const geo = await this._loadGeoLocation();
|
|
155
155
|
if (!geo) {
|
|
156
|
-
this.adapter.log.warn('[aiForecastHelper]
|
|
156
|
+
this.adapter.log.warn('[aiForecastHelper] abort - no geo data available');
|
|
157
157
|
return;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
const weather = await this._fetchWeather(geo.lat, geo.lon);
|
|
161
161
|
if (!weather) {
|
|
162
|
-
this.adapter.log.warn('[aiForecastHelper]
|
|
162
|
+
this.adapter.log.warn('[aiForecastHelper] abort - no weather data available');
|
|
163
163
|
return;
|
|
164
164
|
}
|
|
165
165
|
|
|
@@ -168,9 +168,9 @@ const aiForecastHelper = {
|
|
|
168
168
|
await this._writeOutput('tomorrow_forecast', text);
|
|
169
169
|
await this._maybeSpeak(text);
|
|
170
170
|
|
|
171
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
171
|
+
this.adapter.log.info('[aiForecastHelper] forecast for tomorrow created');
|
|
172
172
|
} catch (err) {
|
|
173
|
-
this.adapter.log.warn(`[aiForecastHelper]
|
|
173
|
+
this.adapter.log.warn(`[aiForecastHelper] error in _runForecast(): ${err.message}`);
|
|
174
174
|
}
|
|
175
175
|
},
|
|
176
176
|
|
|
@@ -331,7 +331,7 @@ const aiForecastHelper = {
|
|
|
331
331
|
`&timezone=auto`;
|
|
332
332
|
|
|
333
333
|
if (this._debugMode) {
|
|
334
|
-
this.adapter.log.debug(`[aiForecastHelper]
|
|
334
|
+
this.adapter.log.debug(`[aiForecastHelper] request: ${url}`);
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
return new Promise(resolve => {
|
|
@@ -363,10 +363,10 @@ const aiForecastHelper = {
|
|
|
363
363
|
await this.adapter.setStateAsync(`ai.weather.outputs.${id}`, { val: text, ack: true });
|
|
364
364
|
|
|
365
365
|
if (this._debugMode) {
|
|
366
|
-
this.adapter.log.debug(`[aiForecastHelper]
|
|
366
|
+
this.adapter.log.debug(`[aiForecastHelper] output written: ai.weather.outputs.${id}`);
|
|
367
367
|
}
|
|
368
368
|
} catch (err) {
|
|
369
|
-
this.adapter.log.error(`[aiForecastHelper]
|
|
369
|
+
this.adapter.log.error(`[aiForecastHelper] error writing output (${id}): ${err.message}`);
|
|
370
370
|
}
|
|
371
371
|
},
|
|
372
372
|
|
|
@@ -378,9 +378,9 @@ const aiForecastHelper = {
|
|
|
378
378
|
|
|
379
379
|
try {
|
|
380
380
|
await this.adapter.setStateAsync('speech.queue', { val: text, ack: false });
|
|
381
|
-
this.adapter.log.info('[aiForecastHelper]
|
|
381
|
+
this.adapter.log.info('[aiForecastHelper] speech output started');
|
|
382
382
|
} catch (err) {
|
|
383
|
-
this.adapter.log.warn(`[aiForecastHelper]
|
|
383
|
+
this.adapter.log.warn(`[aiForecastHelper] speech output error: ${err.message}`);
|
|
384
384
|
}
|
|
385
385
|
},
|
|
386
386
|
|
package/lib/helpers/aiHelper.js
CHANGED
|
@@ -61,12 +61,12 @@ const aiHelper = {
|
|
|
61
61
|
*/
|
|
62
62
|
async init(adapter) {
|
|
63
63
|
this.adapter = adapter;
|
|
64
|
-
this.adapter.log.info('[aiHelper]
|
|
64
|
+
this.adapter.log.info('[aiHelper] initialization started');
|
|
65
65
|
|
|
66
66
|
// Ersten Settings-Load + Timeraufbau
|
|
67
67
|
await this._refreshTimers();
|
|
68
68
|
|
|
69
|
-
this.adapter.log.info('[aiHelper]
|
|
69
|
+
this.adapter.log.info('[aiHelper] initialization finished');
|
|
70
70
|
},
|
|
71
71
|
|
|
72
72
|
/**
|
|
@@ -74,7 +74,7 @@ const aiHelper = {
|
|
|
74
74
|
*/
|
|
75
75
|
cleanup() {
|
|
76
76
|
this._clearTimers();
|
|
77
|
-
this.adapter && this.adapter.log.debug('[aiHelper]
|
|
77
|
+
this.adapter && this.adapter.log.debug('[aiHelper] cleanup finished (timers stopped)');
|
|
78
78
|
},
|
|
79
79
|
|
|
80
80
|
/**
|
|
@@ -112,9 +112,7 @@ const aiHelper = {
|
|
|
112
112
|
const oldVal = this._lastScheduleValues[id];
|
|
113
113
|
const newVal = state.val;
|
|
114
114
|
|
|
115
|
-
this.adapter.log.info(
|
|
116
|
-
`[aiHelper] Uhrzeit geändert: ${id}: ${oldVal || '(kein vorheriger Wert)'} → ${newVal}`,
|
|
117
|
-
);
|
|
115
|
+
this.adapter.log.info(`[aiHelper] time changed: ${id}: ${oldVal || '(no previous value)'} -> ${newVal}`);
|
|
118
116
|
|
|
119
117
|
// neuen Wert speichern
|
|
120
118
|
this._lastScheduleValues[id] = newVal;
|
|
@@ -141,7 +139,7 @@ const aiHelper = {
|
|
|
141
139
|
// Nur wenn Zielzeit HEUTE noch bevorsteht
|
|
142
140
|
if (target > now) {
|
|
143
141
|
this.adapter.log.info(
|
|
144
|
-
`[aiHelper]
|
|
142
|
+
`[aiHelper] new time is still in the future today -> running module immediately (${id})`,
|
|
145
143
|
);
|
|
146
144
|
|
|
147
145
|
if (id.endsWith('weather_advice_time')) {
|
|
@@ -159,7 +157,7 @@ const aiHelper = {
|
|
|
159
157
|
}
|
|
160
158
|
}
|
|
161
159
|
} catch (e) {
|
|
162
|
-
this.adapter.log.warn(`[aiHelper]
|
|
160
|
+
this.adapter.log.warn(`[aiHelper] error during immediate run after time change: ${e.message}`);
|
|
163
161
|
}
|
|
164
162
|
|
|
165
163
|
return;
|
|
@@ -169,7 +167,7 @@ const aiHelper = {
|
|
|
169
167
|
// FIX 3: Schalteränderungen immer melden
|
|
170
168
|
// ---------------------------------------------------------
|
|
171
169
|
if (id.includes('.ai.weather.switches.')) {
|
|
172
|
-
this.adapter.log.info(`[aiHelper]
|
|
170
|
+
this.adapter.log.info(`[aiHelper] switch changed: ${id} = ${state.val} - rebuilding timers`);
|
|
173
171
|
|
|
174
172
|
await this._refreshTimers();
|
|
175
173
|
return;
|
|
@@ -200,11 +198,11 @@ const aiHelper = {
|
|
|
200
198
|
this._debugMode = await this._getBool('ai.weather.switches.debug_mode', false);
|
|
201
199
|
|
|
202
200
|
if (!aiEnabled) {
|
|
203
|
-
this.adapter.log.info('[aiHelper]
|
|
201
|
+
this.adapter.log.info('[aiHelper] AI is disabled (ai.enabled = false) - no timers active');
|
|
204
202
|
return;
|
|
205
203
|
}
|
|
206
204
|
|
|
207
|
-
this.adapter.log.info('[aiHelper]
|
|
205
|
+
this.adapter.log.info('[aiHelper] AI is enabled - setting timers');
|
|
208
206
|
|
|
209
207
|
// --- Wetterhinweise ---
|
|
210
208
|
const weatherEnabled = await this._getBool('ai.weather.switches.weather_advice_enabled', false);
|
|
@@ -214,7 +212,7 @@ const aiHelper = {
|
|
|
214
212
|
await this._runWeatherAdvice();
|
|
215
213
|
});
|
|
216
214
|
this.adapter.log.debug(
|
|
217
|
-
`[aiHelper]
|
|
215
|
+
`[aiHelper] weather advice timer set for ${time.hour}:${String(time.minute).padStart(2, '0')}`,
|
|
218
216
|
);
|
|
219
217
|
}
|
|
220
218
|
|
|
@@ -226,7 +224,7 @@ const aiHelper = {
|
|
|
226
224
|
await this._runDailySummary();
|
|
227
225
|
});
|
|
228
226
|
this.adapter.log.debug(
|
|
229
|
-
`[aiHelper]
|
|
227
|
+
`[aiHelper] daily summary timer set for ${time.hour}:${String(time.minute).padStart(2, '0')}`,
|
|
230
228
|
);
|
|
231
229
|
}
|
|
232
230
|
|
|
@@ -238,7 +236,7 @@ const aiHelper = {
|
|
|
238
236
|
await this._runDailyPoolTips();
|
|
239
237
|
});
|
|
240
238
|
this.adapter.log.debug(
|
|
241
|
-
`[aiHelper]
|
|
239
|
+
`[aiHelper] pool tips timer set for ${time.hour}:${String(time.minute).padStart(2, '0')}`,
|
|
242
240
|
);
|
|
243
241
|
}
|
|
244
242
|
|
|
@@ -250,27 +248,27 @@ const aiHelper = {
|
|
|
250
248
|
await this._runWeekendSummary();
|
|
251
249
|
});
|
|
252
250
|
this.adapter.log.debug(
|
|
253
|
-
`[aiHelper]
|
|
251
|
+
`[aiHelper] weekend summary timer set for ${time.hour}:${String(time.minute).padStart(2, '0')}`,
|
|
254
252
|
);
|
|
255
253
|
}
|
|
256
254
|
|
|
257
255
|
//--------------------------------------------------------
|
|
258
256
|
// NEU: Stündlicher Wetter-Update-Timer
|
|
259
257
|
//--------------------------------------------------------
|
|
260
|
-
this.adapter.log.debug('[aiHelper]
|
|
258
|
+
this.adapter.log.debug('[aiHelper] setting hourly weather update timer');
|
|
261
259
|
|
|
262
260
|
const hourlyTimer = setInterval(
|
|
263
261
|
async () => {
|
|
264
262
|
try {
|
|
265
263
|
const geo = await this._loadGeoLocation();
|
|
266
264
|
if (!geo) {
|
|
267
|
-
this.adapter.log.info('[aiHelper]
|
|
265
|
+
this.adapter.log.info('[aiHelper] weather update aborted - no geo data available');
|
|
268
266
|
return;
|
|
269
267
|
}
|
|
270
268
|
|
|
271
269
|
const weather = await this._fetchWeather(geo.lat, geo.lon);
|
|
272
270
|
if (!weather) {
|
|
273
|
-
this.adapter.log.info('[aiHelper]
|
|
271
|
+
this.adapter.log.info('[aiHelper] weather update aborted - no weather data available');
|
|
274
272
|
return;
|
|
275
273
|
}
|
|
276
274
|
|
|
@@ -284,12 +282,10 @@ const aiHelper = {
|
|
|
284
282
|
await this._writeOutput('pool_tips', poolTipsText);
|
|
285
283
|
|
|
286
284
|
if (this._debugMode) {
|
|
287
|
-
this.adapter.log.debug(
|
|
288
|
-
'[aiHelper] Stündliches Wetter-Update durchgeführt (Weather + Pool-Tipps)',
|
|
289
|
-
);
|
|
285
|
+
this.adapter.log.debug('[aiHelper] hourly weather update completed (weather + pool tips)');
|
|
290
286
|
}
|
|
291
287
|
} catch (err) {
|
|
292
|
-
this.adapter.log.warn(`[aiHelper]
|
|
288
|
+
this.adapter.log.warn(`[aiHelper] error during hourly weather update: ${err.message}`);
|
|
293
289
|
}
|
|
294
290
|
},
|
|
295
291
|
60 * 60 * 1000,
|
|
@@ -319,23 +315,21 @@ const aiHelper = {
|
|
|
319
315
|
if (withinStartupWindow && diffMinutes > 0 && diffMinutes <= 2) {
|
|
320
316
|
try {
|
|
321
317
|
await callback();
|
|
322
|
-
this.adapter.log.info(
|
|
323
|
-
'[aiHelper] Nachholung ausgeführt (innerhalb der ersten 3 Minuten nach Start)',
|
|
324
|
-
);
|
|
318
|
+
this.adapter.log.info('[aiHelper] catch-up executed (within the first 3 minutes after start)');
|
|
325
319
|
} catch (err) {
|
|
326
|
-
this.adapter.log.warn(`[aiHelper]
|
|
320
|
+
this.adapter.log.warn(`[aiHelper] catch-up error: ${err.message}`);
|
|
327
321
|
}
|
|
328
322
|
}
|
|
329
323
|
|
|
330
324
|
if (now.getHours() === hour && now.getMinutes() === minute) {
|
|
331
325
|
this.adapter.log.debug(
|
|
332
|
-
`[aiHelper]
|
|
326
|
+
`[aiHelper] timer triggered: ${hour}:${String(minute).padStart(2, '0')} -> running callback`,
|
|
333
327
|
); // NEU
|
|
334
328
|
|
|
335
329
|
try {
|
|
336
330
|
await callback();
|
|
337
331
|
} catch (err) {
|
|
338
|
-
this.adapter.log.warn(`[aiHelper]
|
|
332
|
+
this.adapter.log.warn(`[aiHelper] timer callback error: ${err.message}`);
|
|
339
333
|
}
|
|
340
334
|
}
|
|
341
335
|
}, 60 * 1000); // jede Minute prüfen
|
|
@@ -354,13 +348,13 @@ const aiHelper = {
|
|
|
354
348
|
try {
|
|
355
349
|
const geo = await this._loadGeoLocation();
|
|
356
350
|
if (!geo) {
|
|
357
|
-
this.adapter.log.info('[aiHelper]
|
|
351
|
+
this.adapter.log.info('[aiHelper] weather advice aborted - no geo data available');
|
|
358
352
|
return;
|
|
359
353
|
}
|
|
360
354
|
|
|
361
355
|
const weather = await this._fetchWeather(geo.lat, geo.lon);
|
|
362
356
|
if (!weather) {
|
|
363
|
-
this.adapter.log.info('[aiHelper]
|
|
357
|
+
this.adapter.log.info('[aiHelper] weather advice aborted - no weather data available');
|
|
364
358
|
return;
|
|
365
359
|
}
|
|
366
360
|
|
|
@@ -368,9 +362,9 @@ const aiHelper = {
|
|
|
368
362
|
await this._writeOutput('weather_advice', text);
|
|
369
363
|
await this._maybeSpeak(text);
|
|
370
364
|
|
|
371
|
-
this.adapter.log.info('[aiHelper]
|
|
365
|
+
this.adapter.log.info('[aiHelper] new weather advice created');
|
|
372
366
|
} catch (err) {
|
|
373
|
-
this.adapter.log.warn(`[aiHelper]
|
|
367
|
+
this.adapter.log.warn(`[aiHelper] error in _runWeatherAdvice(): ${err.message}`);
|
|
374
368
|
}
|
|
375
369
|
},
|
|
376
370
|
|
|
@@ -398,9 +392,9 @@ const aiHelper = {
|
|
|
398
392
|
await this._writeOutput('daily_summary', text);
|
|
399
393
|
await this._maybeSpeak(text);
|
|
400
394
|
|
|
401
|
-
this.adapter.log.info('[aiHelper]
|
|
395
|
+
this.adapter.log.info('[aiHelper] new daily summary created');
|
|
402
396
|
} catch (err) {
|
|
403
|
-
this.adapter.log.warn(`[aiHelper]
|
|
397
|
+
this.adapter.log.warn(`[aiHelper] error in _runDailySummary(): ${err.message}`);
|
|
404
398
|
}
|
|
405
399
|
},
|
|
406
400
|
|
|
@@ -418,9 +412,9 @@ const aiHelper = {
|
|
|
418
412
|
await this._writeOutput('pool_tips', text);
|
|
419
413
|
await this._maybeSpeak(text);
|
|
420
414
|
|
|
421
|
-
this.adapter.log.info('[aiHelper]
|
|
415
|
+
this.adapter.log.info('[aiHelper] new pool tips created');
|
|
422
416
|
} catch (err) {
|
|
423
|
-
this.adapter.log.warn(`[aiHelper]
|
|
417
|
+
this.adapter.log.warn(`[aiHelper] error in _runDailyPoolTips(): ${err.message}`);
|
|
424
418
|
}
|
|
425
419
|
},
|
|
426
420
|
|
|
@@ -434,9 +428,7 @@ const aiHelper = {
|
|
|
434
428
|
|
|
435
429
|
// Nur Freitag oder Samstag sinnvoll
|
|
436
430
|
if (weekday !== 5 && weekday !== 6) {
|
|
437
|
-
this.adapter.log.info(
|
|
438
|
-
'[aiHelper] Wochenend-Zusammenfassung übersprungen – heute ist weder Freitag noch Samstag',
|
|
439
|
-
);
|
|
431
|
+
this.adapter.log.info('[aiHelper] weekend summary skipped - today is neither Friday nor Saturday');
|
|
440
432
|
return;
|
|
441
433
|
}
|
|
442
434
|
|
|
@@ -449,9 +441,9 @@ const aiHelper = {
|
|
|
449
441
|
await this._writeOutput('weekend_summary', text);
|
|
450
442
|
await this._maybeSpeak(text);
|
|
451
443
|
|
|
452
|
-
this.adapter.log.info('[aiHelper]
|
|
444
|
+
this.adapter.log.info('[aiHelper] new weekend summary created');
|
|
453
445
|
} catch (err) {
|
|
454
|
-
this.adapter.log.warn(`[aiHelper]
|
|
446
|
+
this.adapter.log.warn(`[aiHelper] error in _runWeekendSummary(): ${err.message}`);
|
|
455
447
|
}
|
|
456
448
|
},
|
|
457
449
|
|
|
@@ -462,13 +454,13 @@ const aiHelper = {
|
|
|
462
454
|
try {
|
|
463
455
|
const geo = await this._loadGeoLocation();
|
|
464
456
|
if (!geo) {
|
|
465
|
-
this.adapter.log.info('[aiHelper]
|
|
457
|
+
this.adapter.log.info('[aiHelper] auto weather update aborted - no geo data available');
|
|
466
458
|
return;
|
|
467
459
|
}
|
|
468
460
|
|
|
469
461
|
const weather = await this._fetchWeather(geo.lat, geo.lon);
|
|
470
462
|
if (!weather) {
|
|
471
|
-
this.adapter.log.info('[aiHelper]
|
|
463
|
+
this.adapter.log.info('[aiHelper] auto weather update aborted - no weather data available');
|
|
472
464
|
return;
|
|
473
465
|
}
|
|
474
466
|
|
|
@@ -477,10 +469,10 @@ const aiHelper = {
|
|
|
477
469
|
await this._writeOutput('weather_advice', text);
|
|
478
470
|
|
|
479
471
|
if (this._debugMode) {
|
|
480
|
-
this.adapter.log.debug('[aiHelper]
|
|
472
|
+
this.adapter.log.debug('[aiHelper] auto weather update completed successfully');
|
|
481
473
|
}
|
|
482
474
|
} catch (err) {
|
|
483
|
-
this.adapter.log.warn(`[aiHelper]
|
|
475
|
+
this.adapter.log.warn(`[aiHelper] error during auto weather update: ${err.message}`);
|
|
484
476
|
}
|
|
485
477
|
},
|
|
486
478
|
|
|
@@ -497,7 +489,7 @@ const aiHelper = {
|
|
|
497
489
|
try {
|
|
498
490
|
const obj = await this.adapter.getForeignObjectAsync('system.config');
|
|
499
491
|
if (!obj || !obj.common) {
|
|
500
|
-
this.adapter.log.warn('[aiHelper]
|
|
492
|
+
this.adapter.log.warn('[aiHelper] could not load system.config');
|
|
501
493
|
return null;
|
|
502
494
|
}
|
|
503
495
|
|
|
@@ -505,17 +497,17 @@ const aiHelper = {
|
|
|
505
497
|
const lon = Number(obj.common.longitude);
|
|
506
498
|
|
|
507
499
|
if (Number.isNaN(lat) || Number.isNaN(lon)) {
|
|
508
|
-
this.adapter.log.warn('[aiHelper]
|
|
500
|
+
this.adapter.log.warn('[aiHelper] invalid geo data - please set it in Admin under System/Location');
|
|
509
501
|
return null;
|
|
510
502
|
}
|
|
511
503
|
|
|
512
504
|
if (this._debugMode) {
|
|
513
|
-
this.adapter.log.debug(`[aiHelper]
|
|
505
|
+
this.adapter.log.debug(`[aiHelper] geo data loaded: lat=${lat}, lon=${lon}`);
|
|
514
506
|
}
|
|
515
507
|
|
|
516
508
|
return { lat, lon };
|
|
517
509
|
} catch (err) {
|
|
518
|
-
this.adapter.log.error(`[aiHelper]
|
|
510
|
+
this.adapter.log.error(`[aiHelper] error loading geo data: ${err.message}`);
|
|
519
511
|
return null;
|
|
520
512
|
}
|
|
521
513
|
},
|
|
@@ -537,7 +529,7 @@ const aiHelper = {
|
|
|
537
529
|
`&timezone=auto`;
|
|
538
530
|
|
|
539
531
|
if (this._debugMode) {
|
|
540
|
-
this.adapter.log.debug(`[aiHelper]
|
|
532
|
+
this.adapter.log.debug(`[aiHelper] fetching weather data: ${url}`);
|
|
541
533
|
}
|
|
542
534
|
|
|
543
535
|
return new Promise(resolve => {
|
|
@@ -551,23 +543,23 @@ const aiHelper = {
|
|
|
551
543
|
res.on('end', () => {
|
|
552
544
|
try {
|
|
553
545
|
if (!data) {
|
|
554
|
-
this.adapter.log.warn('[aiHelper]
|
|
546
|
+
this.adapter.log.warn('[aiHelper] weather request: received empty response');
|
|
555
547
|
return resolve(null);
|
|
556
548
|
}
|
|
557
549
|
const json = JSON.parse(data);
|
|
558
550
|
resolve(json);
|
|
559
551
|
} catch (err) {
|
|
560
|
-
this.adapter.log.warn(`[aiHelper]
|
|
552
|
+
this.adapter.log.warn(`[aiHelper] error parsing weather data: ${err.message}`);
|
|
561
553
|
resolve(null);
|
|
562
554
|
}
|
|
563
555
|
});
|
|
564
556
|
})
|
|
565
557
|
.on('error', err => {
|
|
566
|
-
this.adapter.log.warn(`[aiHelper]
|
|
558
|
+
this.adapter.log.warn(`[aiHelper] weather request error: ${err.message}`);
|
|
567
559
|
resolve(null);
|
|
568
560
|
});
|
|
569
561
|
} catch (err) {
|
|
570
|
-
this.adapter.log.warn(`[aiHelper]
|
|
562
|
+
this.adapter.log.warn(`[aiHelper] unexpected weather request error: ${err.message}`);
|
|
571
563
|
resolve(null);
|
|
572
564
|
}
|
|
573
565
|
});
|
|
@@ -975,10 +967,10 @@ const aiHelper = {
|
|
|
975
967
|
await this.adapter.setStateAsync('ai.weather.outputs.last_message', { val: text, ack: true });
|
|
976
968
|
|
|
977
969
|
if (this._debugMode) {
|
|
978
|
-
this.adapter.log.debug(`[aiHelper]
|
|
970
|
+
this.adapter.log.debug(`[aiHelper] output written -> ai.weather.outputs.${id}: ${text}`);
|
|
979
971
|
}
|
|
980
972
|
} catch (err) {
|
|
981
|
-
this.adapter.log.error(`[aiHelper]
|
|
973
|
+
this.adapter.log.error(`[aiHelper] error writing output (${id}): ${err.message}`);
|
|
982
974
|
}
|
|
983
975
|
},
|
|
984
976
|
|
|
@@ -998,18 +990,16 @@ const aiHelper = {
|
|
|
998
990
|
const allowSpeech = await this._getBool('ai.weather.switches.allow_speech', false);
|
|
999
991
|
if (!allowSpeech) {
|
|
1000
992
|
if (this._debugMode) {
|
|
1001
|
-
this.adapter.log.debug(
|
|
1002
|
-
'[aiHelper] Sprachausgabe deaktiviert (ai.weather.switches.allow_speech = false)',
|
|
1003
|
-
);
|
|
993
|
+
this.adapter.log.debug('[aiHelper] speech output disabled (ai.weather.switches.allow_speech = false)');
|
|
1004
994
|
}
|
|
1005
995
|
return;
|
|
1006
996
|
}
|
|
1007
997
|
|
|
1008
998
|
try {
|
|
1009
999
|
await this.adapter.setStateAsync('speech.queue', { val: text, ack: false });
|
|
1010
|
-
this.adapter.log.info('[aiHelper]
|
|
1000
|
+
this.adapter.log.info('[aiHelper] text sent to speech.queue');
|
|
1011
1001
|
} catch (err) {
|
|
1012
|
-
this.adapter.log.warn(`[aiHelper]
|
|
1002
|
+
this.adapter.log.warn(`[aiHelper] speech output error: ${err.message}`);
|
|
1013
1003
|
}
|
|
1014
1004
|
},
|
|
1015
1005
|
|
|
@@ -1082,14 +1072,14 @@ const aiHelper = {
|
|
|
1082
1072
|
const str = await this._getString(id, def);
|
|
1083
1073
|
|
|
1084
1074
|
// NEU: Log, welche Uhrzeit der Helper tatsächlich verwendet
|
|
1085
|
-
this.adapter.log.debug(`[aiHelper]
|
|
1075
|
+
this.adapter.log.debug(`[aiHelper] time loaded: ${id} = "${str}" (default: ${def})`);
|
|
1086
1076
|
|
|
1087
1077
|
const match = /^(\d{1,2}):(\d{2})$/.exec(str || '');
|
|
1088
1078
|
let hour = 0;
|
|
1089
1079
|
let minute = 0;
|
|
1090
1080
|
|
|
1091
1081
|
if (!match) {
|
|
1092
|
-
this.adapter.log.warn(`[aiHelper]
|
|
1082
|
+
this.adapter.log.warn(`[aiHelper] invalid time format in ${id}: "${str}" - using default ${def}`);
|
|
1093
1083
|
const defMatch = /^(\d{1,2}):(\d{2})$/.exec(def);
|
|
1094
1084
|
if (defMatch) {
|
|
1095
1085
|
hour = Number(defMatch[1]);
|