iobroker.pv-notifications 1.2.10 → 1.2.11

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
@@ -344,11 +344,13 @@ sadam6752@gmail.com
344
344
  ### **WORK IN PROGRESS**
345
345
  -->
346
346
 
347
- ### 1.2.10 (2026-03-02)
347
+ ### 1.2.11 (2026-03-02)
348
348
 
349
- * (FIX) Fixed W4040/W4042: Updated schema definitions in .vscode/settings.json
349
+ * (FIX) Daily statistics: Self-consumption cannot be negative (Math.max(0, totalProd - feedIn))
350
+ * (FIX) Daily statistics: Added weather today to message (in addition to weather tomorrow)
351
+ * (FIX) Weather error logging improved (warn instead of debug for better visibility)
350
352
 
351
- ### 1.2.9 (2026-03-02)
353
+ ### 1.2.10 (2026-03-02)
352
354
 
353
355
  * (FIX) Fixed duplicate news entry in io-package.json (E1036/E2005 fix)
354
356
  * (FIX) Added full translations for common.news (pt, nl, fr, it, es, pl, uk, zh-cn)
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "pv-notifications",
4
- "version": "1.2.10",
4
+ "version": "1.2.11",
5
5
  "titleLang": {
6
6
  "en": "PV Notifications",
7
7
  "de": "PV-Benachrichtigungen",
@@ -29,6 +29,19 @@
29
29
  "zh-cn": "发送 Telegram 通知用于 PV 电池状态"
30
30
  },
31
31
  "news": {
32
+ "1.2.11": {
33
+ "en": "Fixed daily statistics: self-consumption cannot be negative (Math.max), added weather today to daily stats message",
34
+ "de": "Tagesstatistik fixiert: Eigenverbrauch kann nicht negativ sein (Math.max), Wetter heute zur Tagesstatistik hinzugefügt",
35
+ "ru": "Исправлена дневная статистика: собственное потребление не может быть отрицательным (Math.max), добавлена погода сегодня в дневную статистику",
36
+ "pt": "Estatísticas diárias corrigidas: autoconsumo não pode ser negativo (Math.max), adicionado clima de hoje às estatísticas diárias",
37
+ "nl": "Dagelijkse statistieken hersteld: eigen verbruik kan niet negatief zijn (Math.max), weer vandaag toegevoegd aan dagelijkse statistieken",
38
+ "fr": "Statistiques quotidiennes corrigées : l'autoconsommation ne peut pas être négative (Math.max), météo d'aujourd'hui ajoutée aux statistiques quotidiennes",
39
+ "it": "Statistiche giornaliere corrette: l'autoconsumo non può essere negativo (Math.max), aggiunto meteo di oggi alle statistiche giornaliere",
40
+ "es": "Estadísticas diarias corregidas: el autoconsumo no puede ser negativo (Math.max), agregado clima de hoy a las estadísticas diarias",
41
+ "pl": "Naprawiono statystyki dzienne: zużycie własne nie może być ujemne (Math.max), dodano pogodę dzisiaj do statystyk dziennych",
42
+ "uk": "Виправлено денну статистику: власне споживання не може бути від'ємним (Math.max), додано погоду сьогодні до денної статистики",
43
+ "zh-cn": "已修复每日统计:自用电量不能为负数(Math.max),已添加今日天气到每日统计"
44
+ },
32
45
  "1.2.10": {
33
46
  "en": "Fixed W4040/W4042: Updated schema definitions in .vscode/settings.json (fileMatch without leading slashes, URLs with /master/)",
34
47
  "de": "W4040/W4042 behoben: Schema-Definitionen in .vscode/settings.json aktualisiert (fileMatch ohne führende Slashes, URLs mit /master/)",
@@ -106,19 +119,6 @@
106
119
  "pl": "Dodano atrybuty rozmiaru (xs, xl) dla pól monthlyStatsEnabled, minIntervalIntermediate, statsDayTime, statsWeekDay, statsWeekTime (poprawka E5507)",
107
120
  "uk": "Додано атрибути розміру (xs, xl) для полів monthlyStatsEnabled, minIntervalIntermediate, statsDayTime, statsWeekDay, statsWeekTime (виправлення E5507)",
108
121
  "zh-cn": "已为 monthlyStatsEnabled、minIntervalIntermediate、statsDayTime、statsWeekDay、statsWeekTime 字段添加大小属性(xs, xl)(E5507 修复)"
109
- },
110
- "1.2.4": {
111
- "en": "Added LICENSE file and fixed copyright formatting (W6009/W6011/W7004 fixes)",
112
- "de": "LICENSE-Datei hinzugefügt und Copyright-Formatierung korrigiert (W6009/W6011/W7004 Fixes)",
113
- "ru": "Добавлен файл LICENSE и исправлено форматирование авторских прав (исправления W6009/W6011/W7004)",
114
- "pt": "Arquivo LICENSE adicionado e formatação de copyright corrigida (correções W6009/W6011/W7004)",
115
- "nl": "LICENSE-bestand toegevoegd en copyright-opmaak hersteld (W6009/W6011/W7007 fixes)",
116
- "fr": "Fichier LICENSE ajouté et formatage des droits d'auteur corrigé (corrections W6009/W6011/W7004)",
117
- "it": "Aggiunto file LICENSE e corretta formattazione del copyright (correzioni W6009/W6011/W7004)",
118
- "es": "Archivo LICENSE agregado y formato de derechos de autor corregido (correcciones W6009/W6011/W7004)",
119
- "pl": "Dodano plik LICENSE i poprawiono formatowanie praw autorskich (poprawki W6009/W6011/W7004)",
120
- "uk": "Додано файл LICENSE та виправлено форматування авторських прав (виправлення W6009/W6011/W7004)",
121
- "zh-cn": "已添加 LICENSE 文件并修复版权格式(W6009/W6011/W7004 修复)"
122
122
  }
123
123
  },
124
124
  "authors": [
package/main.js CHANGED
@@ -1205,8 +1205,8 @@ ${statusText}`;
1205
1205
  const gridPowerState = await this.getStateAsync('statistics.currentGridPower');
1206
1206
  const gridPower = gridPowerState && gridPowerState.val !== null ? this.round(gridPowerState.val, 0) : 0;
1207
1207
 
1208
- // Eigenverbrauch berechnen
1209
- const selfConsumption = this.round(totalProd - feedIn, 1);
1208
+ // Eigenverbrauch berechnen (kann nicht negativ sein)
1209
+ const selfConsumption = this.round(Math.max(0, totalProd - feedIn), 1);
1210
1210
  const selfConsumptionRate = totalProd > 0 ? this.round((selfConsumption / totalProd) * 100, 1) : 0;
1211
1211
 
1212
1212
  let message = `📊 *${this.translate('Daily statistics PV system')}*
@@ -1219,40 +1219,93 @@ ${statusText}`;
1219
1219
  🔌 ${this.translate('Feed-in')}: ${feedIn} kWh
1220
1220
  ⚡ ${this.translate('Grid consumption')}: ${gridPower} kWh`;
1221
1221
 
1222
- // Wetter-Prognose für morgen hinzufügen (optional, nur wenn weatherInDailyStats aktiv)
1222
+ // Wetter-Prognose für heute und morgen hinzufügen (optional, nur wenn weatherInDailyStats aktiv)
1223
+ const weatherTodayConfigured = this.config.weatherTodayText || this.config.weatherTodayTemp;
1224
+ const weatherTomorrowConfigured = this.config.weatherTomorrowText || this.config.weatherTomorrow;
1225
+
1223
1226
  if (
1224
1227
  this.config.weatherEnabled !== false &&
1225
1228
  this.config.weatherInDailyStats !== false &&
1226
- (this.config.weatherTomorrowText || this.config.weatherTomorrow)
1229
+ (weatherTodayConfigured || weatherTomorrowConfigured)
1227
1230
  ) {
1228
1231
  try {
1229
- const weatherTomorrowTextState = await this.getForeignStateAsync(this.config.weatherTomorrowText);
1230
- const weatherTomorrowState = await this.getForeignStateAsync(this.config.weatherTomorrow);
1231
- const tempTomorrowState = await this.getForeignStateAsync(this.config.weatherTomorrowTemp);
1232
+ let weatherAdded = false;
1232
1233
 
1233
- const weatherTomorrowText =
1234
- weatherTomorrowTextState && weatherTomorrowTextState.val !== null
1235
- ? weatherTomorrowTextState.val
1234
+ // Wetter heute lesen
1235
+ if (weatherTodayConfigured) {
1236
+ const weatherTodayTextState = this.config.weatherTodayText
1237
+ ? await this.getForeignStateAsync(this.config.weatherTodayText)
1236
1238
  : null;
1237
- const weatherTomorrow =
1238
- weatherTomorrowState && weatherTomorrowState.val !== null ? weatherTomorrowState.val : null;
1239
- const tempTomorrow = tempTomorrowState && tempTomorrowState.val !== null ? tempTomorrowState.val : null;
1240
- const tempText = tempTomorrow ? ` ${this.round(tempTomorrow, 1)}°C` : '';
1241
-
1242
- const weatherText = weatherTomorrowText || weatherTomorrow;
1243
- if (weatherText) {
1244
- const weatherDesc = this.getWeatherDescription(weatherText);
1245
- message += `\n━━━━━━━━━━━━━━━━━━━━━━\n🌤️ *${this.translate('Weather tomorrow')}:* ${weatherDesc}${tempText}`;
1246
-
1247
- // Zusätzliche Info bei gutem/schlechtem Wetter
1248
- if (this.isWeatherGood(weatherText)) {
1249
- message += `\n☀️ ${this.translate('Good PV production expected')}`;
1250
- } else if (this.isWeatherBad(weatherText)) {
1251
- message += `\n⛅ ${this.translate('Less PV production expected')}`;
1239
+ const weatherTodayTempState = this.config.weatherTodayTemp
1240
+ ? await this.getForeignStateAsync(this.config.weatherTodayTemp)
1241
+ : null;
1242
+
1243
+ const weatherTodayText =
1244
+ weatherTodayTextState && weatherTodayTextState.val !== null ? weatherTodayTextState.val : null;
1245
+ const weatherTodayTemp =
1246
+ weatherTodayTempState && weatherTodayTempState.val !== null ? weatherTodayTempState.val : null;
1247
+ const todayTempText = weatherTodayTemp ? ` ${this.round(weatherTodayTemp, 1)}°C` : '';
1248
+
1249
+ if (weatherTodayText || weatherTodayTemp) {
1250
+ const weatherDesc = weatherTodayText ? this.getWeatherDescription(weatherTodayText) : '🌡️';
1251
+ message += `\n━━━━━━━━━━━━━━━━━━━━━━\n🌤️ *${this.translate('Weather today')}:* ${weatherDesc}${todayTempText}`;
1252
+ weatherAdded = true;
1252
1253
  }
1253
1254
  }
1255
+
1256
+ // Wetter morgen lesen
1257
+ if (weatherTomorrowConfigured) {
1258
+ const weatherTomorrowTextState = this.config.weatherTomorrowText
1259
+ ? await this.getForeignStateAsync(this.config.weatherTomorrowText)
1260
+ : null;
1261
+ const weatherTomorrowState = this.config.weatherTomorrow
1262
+ ? await this.getForeignStateAsync(this.config.weatherTomorrow)
1263
+ : null;
1264
+ const tempTomorrowState = this.config.weatherTomorrowTemp
1265
+ ? await this.getForeignStateAsync(this.config.weatherTomorrowTemp)
1266
+ : null;
1267
+
1268
+ const weatherTomorrowText =
1269
+ weatherTomorrowTextState && weatherTomorrowTextState.val !== null
1270
+ ? weatherTomorrowTextState.val
1271
+ : null;
1272
+ const weatherTomorrow =
1273
+ weatherTomorrowState && weatherTomorrowState.val !== null ? weatherTomorrowState.val : null;
1274
+ const tempTomorrow =
1275
+ tempTomorrowState && tempTomorrowState.val !== null ? tempTomorrowState.val : null;
1276
+ const tempText = tempTomorrow ? ` ${this.round(tempTomorrow, 1)}°C` : '';
1277
+
1278
+ const weatherText = weatherTomorrowText || weatherTomorrow;
1279
+ if (weatherText) {
1280
+ const weatherDesc = this.getWeatherDescription(weatherText);
1281
+ message += `\n🌤️ *${this.translate('Weather tomorrow')}:* ${weatherDesc}${tempText}`;
1282
+ weatherAdded = true;
1283
+
1284
+ // Zusätzliche Info bei gutem/schlechtem Wetter
1285
+ if (this.isWeatherGood(weatherText)) {
1286
+ message += `\n☀️ ${this.translate('Good PV production expected')}`;
1287
+ } else if (this.isWeatherBad(weatherText)) {
1288
+ message += `\n⛅ ${this.translate('Less PV production expected')}`;
1289
+ }
1290
+ }
1291
+ }
1292
+
1293
+ if (weatherAdded) {
1294
+ message += `\n`;
1295
+ }
1254
1296
  } catch (e) {
1255
- this.log.debug(`Weather data for tomorrow not available: ${e.message}`);
1297
+ this.log.warn(`Weather data error in daily stats: ${e.message}`);
1298
+ this.log.warn(`Please check weather configuration in adapter settings`);
1299
+ }
1300
+ } else {
1301
+ if (this.config.weatherEnabled === false) {
1302
+ this.log.debug('Weather disabled (weatherEnabled=false)');
1303
+ }
1304
+ if (this.config.weatherInDailyStats === false) {
1305
+ this.log.debug('Weather in daily stats disabled (weatherInDailyStats=false)');
1306
+ }
1307
+ if (!weatherTodayConfigured && !weatherTomorrowConfigured) {
1308
+ this.log.debug('No weather data points configured for daily stats');
1256
1309
  }
1257
1310
  }
1258
1311
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.pv-notifications",
3
- "version": "1.2.10",
3
+ "version": "1.2.11",
4
4
  "description": "PV-Anlage Batterie-Status Telegram Benachrichtigungen",
5
5
  "author": {
6
6
  "name": "Alex1808 via LLM: Qwen",