iobroker.pv-notifications 1.0.92 → 1.0.98

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
@@ -339,6 +339,19 @@ sadam6752@gmail.com
339
339
  ### **WORK IN PROGRESS**
340
340
  -->
341
341
 
342
+ ### 1.0.98 (2026-03-01)
343
+
344
+ * (FIX) Weekly/monthly stats now read directly from external states using getForeignStateAsync (not from internal states)
345
+
346
+ ### 1.0.97 (2026-03-01)
347
+
348
+ * (FIX) Weekly/monthly statistics now read from internal states (statistics.currentTotalProduction, etc.) instead of external config
349
+
350
+ ### 1.0.93 (2026-02-27)
351
+
352
+ * (FIX) size attributes (xs, xl) added for number fields in jsonConfig.json (E5507)
353
+ * (FIX) VSCode schema definitions updated for io-package.json and jsonConfig.json (W4040, W4042)
354
+
342
355
  ### 1.0.92 (2026-02-27)
343
356
 
344
357
  * (ADD) VSCode settings added with JSON schema definitions (S4036)
@@ -184,9 +184,11 @@
184
184
  "batteryCapacityWh": {
185
185
  "type": "number",
186
186
  "label": "label_batteryCapacityWh",
187
+ "xs": 12,
187
188
  "sm": 6,
188
189
  "md": 6,
189
190
  "lg": 6,
191
+ "xl": 6,
190
192
  "min": 1000,
191
193
  "max": 100000,
192
194
  "step": 100
@@ -194,36 +196,44 @@
194
196
  "thresholdFull": {
195
197
  "type": "number",
196
198
  "label": "label_thresholdFull",
199
+ "xs": 12,
197
200
  "sm": 3,
198
201
  "md": 3,
199
202
  "lg": 3,
203
+ "xl": 3,
200
204
  "min": 0,
201
205
  "max": 100
202
206
  },
203
207
  "thresholdEmpty": {
204
208
  "type": "number",
205
209
  "label": "label_thresholdEmpty",
210
+ "xs": 12,
206
211
  "sm": 3,
207
212
  "md": 3,
208
213
  "lg": 3,
214
+ "xl": 3,
209
215
  "min": 0,
210
216
  "max": 100
211
217
  },
212
218
  "thresholdResetFull": {
213
219
  "type": "number",
214
220
  "label": "label_thresholdResetFull",
221
+ "xs": 12,
215
222
  "sm": 3,
216
223
  "md": 3,
217
224
  "lg": 3,
225
+ "xl": 3,
218
226
  "min": 0,
219
227
  "max": 100
220
228
  },
221
229
  "thresholdResetEmpty": {
222
230
  "type": "number",
223
231
  "label": "label_thresholdResetEmpty",
232
+ "xs": 12,
224
233
  "sm": 3,
225
234
  "md": 3,
226
235
  "lg": 3,
236
+ "xl": 3,
227
237
  "min": 0,
228
238
  "max": 100
229
239
  },
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "pv-notifications",
4
- "version": "1.0.92",
4
+ "version": "1.0.98",
5
5
  "titleLang": {
6
6
  "en": "PV Notifications",
7
7
  "de": "PV-Benachrichtigungen",
@@ -67,6 +67,19 @@
67
67
  }
68
68
  ],
69
69
  "news": {
70
+ "1.0.93": {
71
+ "en": "Repository checker fixes: size attributes added for number fields (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), VSCode schema definitions updated",
72
+ "de": "Repository-Checker-Fixes: size-Attribute für number-Felder hinzugefügt (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), VSCode-Schema-Definitionen aktualisiert",
73
+ "ru": "Исправления репозитория: добавлены атрибуты size для числовых полей (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), обновлены определения схемы VSCode",
74
+ "pt": "Correções do repositório: atributos size adicionados para campos numéricos (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), definições de esquema VSCode atualizadas",
75
+ "nl": "Repository checker fixes: size-attributen toegevoegd voor nummervelden (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), VSCode-schema-definities bijgewerkt",
76
+ "fr": "Corrections du dépôt : attributs size ajoutés pour les champs numériques (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), définitions de schéma VSCode mises à jour",
77
+ "it": "Correzioni del repository: aggiunti attributi size per i campi numerici (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), aggiornate definizioni di schema VSCode",
78
+ "es": "Correcciones del repositorio: atributos size agregados para campos numéricos (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), definiciones de esquema VSCode actualizadas",
79
+ "pl": "Poprawki repozytorium: dodano atrybuty size dla pól liczbowych (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), zaktualizowano definicje schematu VSCode",
80
+ "uk": "Виправлення репозиторію: додано атрибути size для числових полів (batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty), оновлено визначення схеми VSCode",
81
+ "zh-cn": "仓库修复:已为数字字段添加 size 属性(batteryCapacityWh, thresholdFull/Empty/ResetFull/ResetEmpty),已更新 VSCode 架构定义"
82
+ },
70
83
  "1.0.92": {
71
84
  "en": "VSCode settings added with JSON schema definitions for better development experience",
72
85
  "de": "VSCode-Einstellungen mit JSON-Schema-Definitionen für bessere Entwicklungserfahrung hinzugefügt",
package/main.js CHANGED
@@ -414,6 +414,38 @@ class PvNotifications extends utils.Adapter {
414
414
  this.stats.lastStatsReset = today;
415
415
  await this.saveStatistics();
416
416
  }
417
+
418
+ // Load saved last week data from states
419
+ const lastWeekProduction = await this.getStateAsync('statistics.lastWeekProduction');
420
+ const lastWeekConsumption = await this.getStateAsync('statistics.lastWeekConsumption');
421
+ const lastWeekFeedIn = await this.getStateAsync('statistics.lastWeekFeedIn');
422
+ const lastWeekGridPower = await this.getStateAsync('statistics.lastWeekGridPower');
423
+ const lastWeekFullCycles = await this.getStateAsync('statistics.lastWeekFullCycles');
424
+ const lastWeekEmptyCycles = await this.getStateAsync('statistics.lastWeekEmptyCycles');
425
+
426
+ this.stats.lastWeekProduction = lastWeekProduction && lastWeekProduction.val !== null ? lastWeekProduction.val : 0;
427
+ this.stats.lastWeekConsumption = lastWeekConsumption && lastWeekConsumption.val !== null ? lastWeekConsumption.val : 0;
428
+ this.stats.lastWeekFeedIn = lastWeekFeedIn && lastWeekFeedIn.val !== null ? lastWeekFeedIn.val : 0;
429
+ this.stats.lastWeekGridPower = lastWeekGridPower && lastWeekGridPower.val !== null ? lastWeekGridPower.val : 0;
430
+ this.stats.lastWeekFullCycles = lastWeekFullCycles && lastWeekFullCycles.val !== null ? lastWeekFullCycles.val : 0;
431
+ this.stats.lastWeekEmptyCycles = lastWeekEmptyCycles && lastWeekEmptyCycles.val !== null ? lastWeekEmptyCycles.val : 0;
432
+
433
+ // Load saved last month data from states
434
+ const lastMonthProduction = await this.getStateAsync('statistics.lastMonthProduction');
435
+ const lastMonthConsumption = await this.getStateAsync('statistics.lastMonthConsumption');
436
+ const lastMonthFeedIn = await this.getStateAsync('statistics.lastMonthFeedIn');
437
+ const lastMonthGridPower = await this.getStateAsync('statistics.lastMonthGridPower');
438
+ const lastMonthFullCycles = await this.getStateAsync('statistics.lastMonthFullCycles');
439
+ const lastMonthEmptyCycles = await this.getStateAsync('statistics.lastMonthEmptyCycles');
440
+
441
+ this.stats.lastMonthProduction = lastMonthProduction && lastMonthProduction.val !== null ? lastMonthProduction.val : 0;
442
+ this.stats.lastMonthConsumption = lastMonthConsumption && lastMonthConsumption.val !== null ? lastMonthConsumption.val : 0;
443
+ this.stats.lastMonthFeedIn = lastMonthFeedIn && lastMonthFeedIn.val !== null ? lastMonthFeedIn.val : 0;
444
+ this.stats.lastMonthGridPower = lastMonthGridPower && lastMonthGridPower.val !== null ? lastMonthGridPower.val : 0;
445
+ this.stats.lastMonthFullCycles = lastMonthFullCycles && lastMonthFullCycles.val !== null ? lastMonthFullCycles.val : 0;
446
+ this.stats.lastMonthEmptyCycles = lastMonthEmptyCycles && lastMonthEmptyCycles.val !== null ? lastMonthEmptyCycles.val : 0;
447
+
448
+ this.log.info('Statistics loaded from states');
417
449
  } catch (e) {
418
450
  this.log.error(`Error loading statistics: ${e.message}`);
419
451
  }
@@ -528,24 +560,29 @@ class PvNotifications extends utils.Adapter {
528
560
  return;
529
561
  }
530
562
 
531
- // Update other data points (Production, Consumption, etc.)
532
- // if (state.ack) { // Only process status updates
533
- if (id === this.config.totalProduction) {
534
- await this.setStateAsync('statistics.currentTotalProduction', state.val, true);
535
- }
536
- if (id === this.config.feedIn) {
537
- await this.setStateAsync('statistics.currentFeedIn', state.val, true);
538
- }
539
- if (id === this.config.consumption) {
540
- await this.setStateAsync('statistics.currentConsumption', state.val, true);
541
- }
542
- if (id === this.config.gridPower) {
543
- await this.setStateAsync('statistics.currentGridPower', state.val, true);
544
- }
545
- if (id === this.config.powerProduction) {
546
- await this.setStateAsync('statistics.currentPower', state.val, true);
563
+ // Update other data points (Production, Consumption, etc.) - only ack states
564
+ if (state.ack) {
565
+ if (id === this.config.totalProduction) {
566
+ await this.setStateAsync('statistics.currentTotalProduction', state.val, true);
567
+ this.log.debug(`Updated currentTotalProduction: ${state.val}`);
568
+ }
569
+ if (id === this.config.feedIn) {
570
+ await this.setStateAsync('statistics.currentFeedIn', state.val, true);
571
+ this.log.debug(`Updated currentFeedIn: ${state.val}`);
572
+ }
573
+ if (id === this.config.consumption) {
574
+ await this.setStateAsync('statistics.currentConsumption', state.val, true);
575
+ this.log.debug(`Updated currentConsumption: ${state.val}`);
576
+ }
577
+ if (id === this.config.gridPower) {
578
+ await this.setStateAsync('statistics.currentGridPower', state.val, true);
579
+ this.log.debug(`Updated currentGridPower: ${state.val}`);
580
+ }
581
+ if (id === this.config.powerProduction) {
582
+ await this.setStateAsync('statistics.currentPower', state.val, true);
583
+ this.log.debug(`Updated currentPower: ${state.val}`);
584
+ }
547
585
  }
548
- // }
549
586
  }
550
587
  }
551
588
 
@@ -1166,7 +1203,9 @@ ${statusText}`;
1166
1203
  const now = new Date();
1167
1204
  const hours = now.getHours();
1168
1205
  const minutes = now.getMinutes();
1169
- const day = now.getDay(); // 0=So, 1=Mo, ..., 6=Sa
1206
+ const jsDay = now.getDay(); // JavaScript: 0=So, 1=Mo, ..., 6=Sa
1207
+ // Umwandeln in ioBroker-Format: 0=Mo, 1=Di, ..., 6=So
1208
+ const day = jsDay === 0 ? 6 : jsDay - 1;
1170
1209
  const date = now.getDate();
1171
1210
 
1172
1211
  // Alle 5 Minuten: Statistik prüfen (um :00, :05, :10, ...)
@@ -1229,16 +1268,25 @@ ${statusText}`;
1229
1268
  /**
1230
1269
  * Reset weekly statistics
1231
1270
  */
1232
- resetWeeklyStats() {
1233
- const today = new Date().getDay();
1271
+ async resetWeeklyStats() {
1272
+ const jsDay = new Date().getDay(); // JavaScript: 0=So, 1=Mo, ..., 6=Sa
1273
+ // Umwandeln in ioBroker-Format: 0=Mo, 1=Di, ..., 6=So
1274
+ const today = jsDay === 0 ? 6 : jsDay - 1;
1275
+
1234
1276
  if (today === this.config.statsWeekDay && today !== this.stats.lastWeekReset) {
1235
1277
  this.log.info('Resetting weekly statistics');
1236
1278
 
1237
- // Aktuelle Daten als "letzte Woche" speichern
1238
- this.stats.lastWeekProduction = this.getStateValue(this.config.weeklyProduction);
1239
- this.stats.lastWeekConsumption = this.getStateValue(this.config.weeklyConsumption);
1240
- this.stats.lastWeekFeedIn = this.getStateValue(this.config.weeklyFeedIn);
1241
- this.stats.lastWeekGridPower = this.getStateValue(this.config.weeklyGridPower);
1279
+ // Aktuelle Daten aus internen States lesen (aktualisiert in Echtzeit)
1280
+ // Fallback: Wenn interne States leer, direkt aus externen States lesen
1281
+ const totalProd = await this.getForeignStateAsync(this.config.totalProduction);
1282
+ const consumption = await this.getForeignStateAsync(this.config.consumption);
1283
+ const feedIn = await this.getForeignStateAsync(this.config.feedIn);
1284
+ const gridPower = await this.getForeignStateAsync(this.config.gridPower);
1285
+
1286
+ this.stats.lastWeekProduction = totalProd && totalProd.val !== null ? totalProd.val : 0;
1287
+ this.stats.lastWeekConsumption = consumption && consumption.val !== null ? consumption.val : 0;
1288
+ this.stats.lastWeekFeedIn = feedIn && feedIn.val !== null ? feedIn.val : 0;
1289
+ this.stats.lastWeekGridPower = gridPower && gridPower.val !== null ? gridPower.val : 0;
1242
1290
  this.stats.lastWeekFullCycles = this.stats.weekFullCycles;
1243
1291
  this.stats.lastWeekEmptyCycles = this.stats.weekEmptyCycles;
1244
1292
 
@@ -1248,14 +1296,15 @@ ${statusText}`;
1248
1296
  this.stats.lastWeekReset = today;
1249
1297
 
1250
1298
  this.saveStatistics();
1251
- this.sendTelegram(this.buildWeeklyStatsMessage());
1299
+ this.log.info(`Weekly stats saved: Production=${this.stats.lastWeekProduction} kWh`);
1300
+ // KEIN Senden hier - Senden erfolgt nur in startScheduledTasks() zur konfigurierten Zeit
1252
1301
  }
1253
1302
  }
1254
1303
 
1255
1304
  /**
1256
1305
  * Monatsstatistik zurücksetzen
1257
1306
  */
1258
- resetMonthlyStats() {
1307
+ async resetMonthlyStats() {
1259
1308
  if (!this.config.monthlyStatsEnabled) {
1260
1309
  return;
1261
1310
  }
@@ -1263,23 +1312,30 @@ ${statusText}`;
1263
1312
  const today = new Date().getDate();
1264
1313
  const now = new Date();
1265
1314
  const hours = now.getHours();
1266
- const [statHours] = this.config.monthlyStatsTime.split(':').map(Number);
1267
- // const [statMinutes] = ... // ESLint: unused
1315
+ const minutes = now.getMinutes();
1316
+ const [statHours, statMinutes] = this.config.monthlyStatsTime.split(':').map(Number);
1268
1317
 
1269
- // Daten am konfigurierten Tag nach der Sendezeit speichern
1270
- if (today === this.config.monthlyStatsDay && this.stats.lastMonthReset !== today && hours >= statHours) {
1318
+ // Daten am konfigurierten Tag zur konfigurierten Zeit speichern (nicht vorher)
1319
+ if (today === this.config.monthlyStatsDay && this.stats.lastMonthReset !== today &&
1320
+ (hours > statHours || (hours === statHours && minutes >= statMinutes))) {
1271
1321
  this.log.info('Resetting monthly statistics');
1272
1322
 
1273
- // Aktuelle Daten als "letzter Monat" speichern
1274
- this.stats.lastMonthProduction = this.getStateValue(this.config.monthlyProduction);
1275
- this.stats.lastMonthConsumption = this.getStateValue(this.config.monthlyConsumption);
1276
- this.stats.lastMonthFeedIn = this.getStateValue(this.config.monthlyFeedIn);
1277
- this.stats.lastMonthGridPower = this.getStateValue(this.config.monthlyGridPower);
1323
+ // Aktuelle Daten aus externen States lesen (direkter Zugriff)
1324
+ const totalProd = await this.getForeignStateAsync(this.config.monthlyProduction);
1325
+ const consumption = await this.getForeignStateAsync(this.config.monthlyConsumption);
1326
+ const feedIn = await this.getForeignStateAsync(this.config.monthlyFeedIn);
1327
+ const gridPower = await this.getForeignStateAsync(this.config.monthlyGridPower);
1328
+
1329
+ this.stats.lastMonthProduction = totalProd && totalProd.val !== null ? totalProd.val : 0;
1330
+ this.stats.lastMonthConsumption = consumption && consumption.val !== null ? consumption.val : 0;
1331
+ this.stats.lastMonthFeedIn = feedIn && feedIn.val !== null ? feedIn.val : 0;
1332
+ this.stats.lastMonthGridPower = gridPower && gridPower.val !== null ? gridPower.val : 0;
1278
1333
  this.stats.lastMonthFullCycles = this.stats.fullCycles;
1279
1334
  this.stats.lastMonthEmptyCycles = this.stats.emptyCycles;
1280
1335
 
1281
1336
  this.stats.lastMonthReset = today;
1282
1337
  this.saveStatistics();
1338
+ this.log.info(`Monthly stats saved: Production=${this.stats.lastMonthProduction} kWh`);
1283
1339
  }
1284
1340
  }
1285
1341
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.pv-notifications",
3
- "version": "1.0.92",
3
+ "version": "1.0.98",
4
4
  "description": "PV-Anlage Batterie-Status Telegram Benachrichtigungen",
5
5
  "author": {
6
6
  "name": "Alex1808 via LLM: Qwen",