iobroker.pv-notifications 1.0.98 → 1.1.0

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,13 +339,14 @@ sadam6752@gmail.com
339
339
  ### **WORK IN PROGRESS**
340
340
  -->
341
341
 
342
- ### 1.0.98 (2026-03-01)
342
+ ### 1.1.0 (2026-03-01)
343
343
 
344
- * (FIX) Weekly/monthly stats now read directly from external states using getForeignStateAsync (not from internal states)
344
+ * (FIX) buildFullMessage() and buildEmptyMessage() now read from INTERNAL states (statistics.currentPower, etc.) instead of external config states
345
+ * (FIX) buildFullMessage() and buildEmptyMessage() converted to async functions with await
345
346
 
346
- ### 1.0.97 (2026-03-01)
347
+ ### 1.0.99 (2026-03-01)
347
348
 
348
- * (FIX) Weekly/monthly statistics now read from internal states (statistics.currentTotalProduction, etc.) instead of external config
349
+ * (FIX) Weekly stats auto-saved every Sunday at 23:55 (before sourceanalytix reset at 00:00)
349
350
 
350
351
  ### 1.0.93 (2026-02-27)
351
352
 
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "pv-notifications",
4
- "version": "1.0.98",
4
+ "version": "1.1.0",
5
5
  "titleLang": {
6
6
  "en": "PV Notifications",
7
7
  "de": "PV-Benachrichtigungen",
package/main.js CHANGED
@@ -639,7 +639,7 @@ class PvNotifications extends utils.Adapter {
639
639
  const allowNotification = (!nightTime || !nightModeActive) && (!quietTime || !quietModeActive);
640
640
 
641
641
  if (allowNotification && !this.status.full && this.canNotify('full')) {
642
- const message = this.buildFullMessage(soc);
642
+ const message = await this.buildFullMessage(soc);
643
643
  this.sendTelegram(message, 'high');
644
644
  this.status.full = true;
645
645
  this.status.lastNotification.full = Date.now();
@@ -668,7 +668,7 @@ class PvNotifications extends utils.Adapter {
668
668
  const blockedByQuietTime = quietTime && quietModeActive;
669
669
 
670
670
  if (allowEmptyNotification && !blockedByQuietTime) {
671
- const message = this.buildEmptyMessage(soc);
671
+ const message = await this.buildEmptyMessage(soc);
672
672
  this.sendTelegram(message, 'high');
673
673
  this.status.empty = true;
674
674
  this.status.lastNotification.empty = Date.now();
@@ -852,11 +852,17 @@ class PvNotifications extends utils.Adapter {
852
852
  *
853
853
  * @param {number} soc - Battery state of charge in percent
854
854
  */
855
- buildFullMessage(soc) {
856
- const power = this.getStateValue(this.config.powerProduction);
857
- const totalProd = this.getStateValue(this.config.totalProduction);
858
- const feedIn = this.getStateValue(this.config.feedIn);
859
- const consumption = this.getStateValue(this.config.consumption);
855
+ async buildFullMessage(soc) {
856
+ // Werte aus INTERNEN States lesen (aktualisiert in Echtzeit durch onStateChange)
857
+ const powerState = await this.getStateAsync('statistics.currentPower');
858
+ const totalProdState = await this.getStateAsync('statistics.currentTotalProduction');
859
+ const feedInState = await this.getStateAsync('statistics.currentFeedIn');
860
+ const consumptionState = await this.getStateAsync('statistics.currentConsumption');
861
+
862
+ const power = powerState && powerState.val !== null ? powerState.val : 0;
863
+ const totalProd = totalProdState && totalProdState.val !== null ? totalProdState.val : 0;
864
+ const feedIn = feedInState && feedInState.val !== null ? feedInState.val : 0;
865
+ const consumption = consumptionState && consumptionState.val !== null ? consumptionState.val : 0;
860
866
 
861
867
  let message = `🔋 *${this.translate('Battery full')}* (${soc}%)
862
868
 
@@ -900,9 +906,13 @@ class PvNotifications extends utils.Adapter {
900
906
  *
901
907
  * @param {number} soc - Battery state of charge in percent
902
908
  */
903
- buildEmptyMessage(soc) {
904
- const gridPower = this.getStateValue(this.config.gridPower);
905
- const consumption = this.getStateValue(this.config.consumption);
909
+ async buildEmptyMessage(soc) {
910
+ // Werte aus INTERNEN States lesen (aktualisiert in Echtzeit durch onStateChange)
911
+ const gridPowerState = await this.getStateAsync('statistics.currentGridPower');
912
+ const consumptionState = await this.getStateAsync('statistics.currentConsumption');
913
+
914
+ const gridPower = gridPowerState && gridPowerState.val !== null ? gridPowerState.val : 0;
915
+ const consumption = consumptionState && consumptionState.val !== null ? consumptionState.val : 0;
906
916
 
907
917
  let message = `🔋 *${this.translate('Battery empty')}* (${soc}%)
908
918
 
@@ -1266,18 +1276,20 @@ ${statusText}`;
1266
1276
  }
1267
1277
 
1268
1278
  /**
1269
- * Reset weekly statistics
1279
+ * Reset weekly statistics - AUTOMATISCH am Sonntag um 23:55 (vor sourceanalytix Reset)
1270
1280
  */
1271
1281
  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;
1282
+ const now = new Date();
1283
+ const jsDay = now.getDay(); // JavaScript: 0=So, 1=Mo, ..., 6=Sa
1284
+ const hours = now.getHours();
1285
+ const minutes = now.getMinutes();
1275
1286
 
1276
- if (today === this.config.statsWeekDay && today !== this.stats.lastWeekReset) {
1277
- this.log.info('Resetting weekly statistics');
1287
+ // Automatische Speicherung: Jeden Sonntag um 23:55 (vor Mitternacht)
1288
+ // JavaScript: 0 = Sonntag → genau das wollen wir!
1289
+ if (jsDay === 0 && hours === 23 && minutes === 55) {
1290
+ this.log.info('Auto-saving weekly statistics (Sunday 23:55, before sourceanalytix reset)');
1278
1291
 
1279
- // Aktuelle Daten aus internen States lesen (aktualisiert in Echtzeit)
1280
- // Fallback: Wenn interne States leer, direkt aus externen States lesen
1292
+ // Aktuelle Daten aus externen States lesen (direkter Zugriff)
1281
1293
  const totalProd = await this.getForeignStateAsync(this.config.totalProduction);
1282
1294
  const consumption = await this.getForeignStateAsync(this.config.consumption);
1283
1295
  const feedIn = await this.getForeignStateAsync(this.config.feedIn);
@@ -1293,32 +1305,33 @@ ${statusText}`;
1293
1305
  // Wöchentliche Statistik zurücksetzen
1294
1306
  this.stats.weekFullCycles = 0;
1295
1307
  this.stats.weekEmptyCycles = 0;
1296
- this.stats.lastWeekReset = today;
1297
1308
 
1298
1309
  this.saveStatistics();
1299
- this.log.info(`Weekly stats saved: Production=${this.stats.lastWeekProduction} kWh`);
1310
+ this.log.info(`Weekly stats saved: Production=${this.stats.lastWeekProduction} kWh, FeedIn=${this.stats.lastWeekFeedIn} kWh`);
1300
1311
  // KEIN Senden hier - Senden erfolgt nur in startScheduledTasks() zur konfigurierten Zeit
1301
1312
  }
1302
1313
  }
1303
1314
 
1304
1315
  /**
1305
- * Monatsstatistik zurücksetzen
1316
+ * Monatsstatistik zurücksetzen - AUTOMATISCH am letzten Tag des Monats um 23:55 (vor sourceanalytix Reset)
1306
1317
  */
1307
1318
  async resetMonthlyStats() {
1308
1319
  if (!this.config.monthlyStatsEnabled) {
1309
1320
  return;
1310
1321
  }
1311
1322
 
1312
- const today = new Date().getDate();
1313
1323
  const now = new Date();
1324
+ const today = now.getDate();
1314
1325
  const hours = now.getHours();
1315
1326
  const minutes = now.getMinutes();
1316
- const [statHours, statMinutes] = this.config.monthlyStatsTime.split(':').map(Number);
1317
1327
 
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))) {
1321
- this.log.info('Resetting monthly statistics');
1328
+ // Letzten Tag des aktuellen Monats berechnen
1329
+ // new Date(Jahr, Monat+1, 0) gibt den letzten Tag des aktuellen Monats zurück
1330
+ const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
1331
+
1332
+ // Automatische Speicherung: Letzter Tag des Monats um 23:55 (vor Mitternacht)
1333
+ if (today === lastDayOfMonth && hours === 23 && minutes === 55) {
1334
+ this.log.info(`Auto-saving monthly statistics (last day of month ${today}. ${now.getMonth()+1}.${now.getFullYear()} 23:55, before sourceanalytix reset)`);
1322
1335
 
1323
1336
  // Aktuelle Daten aus externen States lesen (direkter Zugriff)
1324
1337
  const totalProd = await this.getForeignStateAsync(this.config.monthlyProduction);
@@ -1335,7 +1348,7 @@ ${statusText}`;
1335
1348
 
1336
1349
  this.stats.lastMonthReset = today;
1337
1350
  this.saveStatistics();
1338
- this.log.info(`Monthly stats saved: Production=${this.stats.lastMonthProduction} kWh`);
1351
+ this.log.info(`Monthly stats saved: Production=${this.stats.lastMonthProduction} kWh, FeedIn=${this.stats.lastMonthFeedIn} kWh`);
1339
1352
  }
1340
1353
  }
1341
1354
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.pv-notifications",
3
- "version": "1.0.98",
3
+ "version": "1.1.0",
4
4
  "description": "PV-Anlage Batterie-Status Telegram Benachrichtigungen",
5
5
  "author": {
6
6
  "name": "Alex1808 via LLM: Qwen",