iobroker.pv-notifications 1.0.93 → 1.0.99
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 +10 -0
- package/io-package.json +1 -1
- package/main.js +105 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -339,6 +339,16 @@ sadam6752@gmail.com
|
|
|
339
339
|
### **WORK IN PROGRESS**
|
|
340
340
|
-->
|
|
341
341
|
|
|
342
|
+
### 1.0.99 (2026-03-01)
|
|
343
|
+
|
|
344
|
+
* (FIX) Weekly stats auto-saved every Sunday at 23:55 (before sourceanalytix reset at 00:00)
|
|
345
|
+
* (FIX) Monthly stats auto-saved on last day of month at 23:55 (before sourceanalytix reset at 00:00)
|
|
346
|
+
* (ADD) User can freely configure send time for weekly/monthly stats via statsWeekDay, statsWeekTime, monthlyStatsDay, monthlyStatsTime
|
|
347
|
+
|
|
348
|
+
### 1.0.98 (2026-03-01)
|
|
349
|
+
|
|
350
|
+
* (FIX) Weekly/monthly stats now read directly from external states using getForeignStateAsync (not from internal states)
|
|
351
|
+
|
|
342
352
|
### 1.0.93 (2026-02-27)
|
|
343
353
|
|
|
344
354
|
* (FIX) size attributes (xs, xl) added for number fields in jsonConfig.json (E5507)
|
package/io-package.json
CHANGED
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
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
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
|
|
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, ...)
|
|
@@ -1227,59 +1266,79 @@ ${statusText}`;
|
|
|
1227
1266
|
}
|
|
1228
1267
|
|
|
1229
1268
|
/**
|
|
1230
|
-
* Reset weekly statistics
|
|
1269
|
+
* Reset weekly statistics - AUTOMATISCH am Sonntag um 23:55 (vor sourceanalytix Reset)
|
|
1231
1270
|
*/
|
|
1232
|
-
resetWeeklyStats() {
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
this.
|
|
1271
|
+
async resetWeeklyStats() {
|
|
1272
|
+
const now = new Date();
|
|
1273
|
+
const jsDay = now.getDay(); // JavaScript: 0=So, 1=Mo, ..., 6=Sa
|
|
1274
|
+
const hours = now.getHours();
|
|
1275
|
+
const minutes = now.getMinutes();
|
|
1276
|
+
|
|
1277
|
+
// Automatische Speicherung: Jeden Sonntag um 23:55 (vor Mitternacht)
|
|
1278
|
+
// JavaScript: 0 = Sonntag → genau das wollen wir!
|
|
1279
|
+
if (jsDay === 0 && hours === 23 && minutes === 55) {
|
|
1280
|
+
this.log.info('Auto-saving weekly statistics (Sunday 23:55, before sourceanalytix reset)');
|
|
1281
|
+
|
|
1282
|
+
// Aktuelle Daten aus externen States lesen (direkter Zugriff)
|
|
1283
|
+
const totalProd = await this.getForeignStateAsync(this.config.totalProduction);
|
|
1284
|
+
const consumption = await this.getForeignStateAsync(this.config.consumption);
|
|
1285
|
+
const feedIn = await this.getForeignStateAsync(this.config.feedIn);
|
|
1286
|
+
const gridPower = await this.getForeignStateAsync(this.config.gridPower);
|
|
1287
|
+
|
|
1288
|
+
this.stats.lastWeekProduction = totalProd && totalProd.val !== null ? totalProd.val : 0;
|
|
1289
|
+
this.stats.lastWeekConsumption = consumption && consumption.val !== null ? consumption.val : 0;
|
|
1290
|
+
this.stats.lastWeekFeedIn = feedIn && feedIn.val !== null ? feedIn.val : 0;
|
|
1291
|
+
this.stats.lastWeekGridPower = gridPower && gridPower.val !== null ? gridPower.val : 0;
|
|
1242
1292
|
this.stats.lastWeekFullCycles = this.stats.weekFullCycles;
|
|
1243
1293
|
this.stats.lastWeekEmptyCycles = this.stats.weekEmptyCycles;
|
|
1244
1294
|
|
|
1245
1295
|
// Wöchentliche Statistik zurücksetzen
|
|
1246
1296
|
this.stats.weekFullCycles = 0;
|
|
1247
1297
|
this.stats.weekEmptyCycles = 0;
|
|
1248
|
-
this.stats.lastWeekReset = today;
|
|
1249
1298
|
|
|
1250
1299
|
this.saveStatistics();
|
|
1251
|
-
this.
|
|
1300
|
+
this.log.info(`Weekly stats saved: Production=${this.stats.lastWeekProduction} kWh, FeedIn=${this.stats.lastWeekFeedIn} kWh`);
|
|
1301
|
+
// KEIN Senden hier - Senden erfolgt nur in startScheduledTasks() zur konfigurierten Zeit
|
|
1252
1302
|
}
|
|
1253
1303
|
}
|
|
1254
1304
|
|
|
1255
1305
|
/**
|
|
1256
|
-
* Monatsstatistik zurücksetzen
|
|
1306
|
+
* Monatsstatistik zurücksetzen - AUTOMATISCH am letzten Tag des Monats um 23:55 (vor sourceanalytix Reset)
|
|
1257
1307
|
*/
|
|
1258
|
-
resetMonthlyStats() {
|
|
1308
|
+
async resetMonthlyStats() {
|
|
1259
1309
|
if (!this.config.monthlyStatsEnabled) {
|
|
1260
1310
|
return;
|
|
1261
1311
|
}
|
|
1262
1312
|
|
|
1263
|
-
const today = new Date().getDate();
|
|
1264
1313
|
const now = new Date();
|
|
1314
|
+
const today = now.getDate();
|
|
1265
1315
|
const hours = now.getHours();
|
|
1266
|
-
const
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
//
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
this.
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1316
|
+
const minutes = now.getMinutes();
|
|
1317
|
+
|
|
1318
|
+
// Letzten Tag des aktuellen Monats berechnen
|
|
1319
|
+
// new Date(Jahr, Monat+1, 0) gibt den letzten Tag des aktuellen Monats zurück
|
|
1320
|
+
const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
|
|
1321
|
+
|
|
1322
|
+
// Automatische Speicherung: Letzter Tag des Monats um 23:55 (vor Mitternacht)
|
|
1323
|
+
if (today === lastDayOfMonth && hours === 23 && minutes === 55) {
|
|
1324
|
+
this.log.info(`Auto-saving monthly statistics (last day of month ${today}. ${now.getMonth()+1}.${now.getFullYear()} 23:55, before sourceanalytix reset)`);
|
|
1325
|
+
|
|
1326
|
+
// Aktuelle Daten aus externen States lesen (direkter Zugriff)
|
|
1327
|
+
const totalProd = await this.getForeignStateAsync(this.config.monthlyProduction);
|
|
1328
|
+
const consumption = await this.getForeignStateAsync(this.config.monthlyConsumption);
|
|
1329
|
+
const feedIn = await this.getForeignStateAsync(this.config.monthlyFeedIn);
|
|
1330
|
+
const gridPower = await this.getForeignStateAsync(this.config.monthlyGridPower);
|
|
1331
|
+
|
|
1332
|
+
this.stats.lastMonthProduction = totalProd && totalProd.val !== null ? totalProd.val : 0;
|
|
1333
|
+
this.stats.lastMonthConsumption = consumption && consumption.val !== null ? consumption.val : 0;
|
|
1334
|
+
this.stats.lastMonthFeedIn = feedIn && feedIn.val !== null ? feedIn.val : 0;
|
|
1335
|
+
this.stats.lastMonthGridPower = gridPower && gridPower.val !== null ? gridPower.val : 0;
|
|
1278
1336
|
this.stats.lastMonthFullCycles = this.stats.fullCycles;
|
|
1279
1337
|
this.stats.lastMonthEmptyCycles = this.stats.emptyCycles;
|
|
1280
1338
|
|
|
1281
1339
|
this.stats.lastMonthReset = today;
|
|
1282
1340
|
this.saveStatistics();
|
|
1341
|
+
this.log.info(`Monthly stats saved: Production=${this.stats.lastMonthProduction} kWh, FeedIn=${this.stats.lastMonthFeedIn} kWh`);
|
|
1283
1342
|
}
|
|
1284
1343
|
}
|
|
1285
1344
|
|