iobroker.sigenergy 3.0.9 → 3.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
@@ -44,6 +44,16 @@ Supports the Sigenergy Modbus Protocol V2.9 (released 2026-05-13).
44
44
 
45
45
  ---
46
46
 
47
+ ## Requirements
48
+
49
+ | Component | Minimum version |
50
+ |-----------|-----------------|
51
+ | **js-controller** | >= 6.0.11 |
52
+ | **admin** | >= 8.0.0 |
53
+ | **Node.js** | >= 22 |
54
+
55
+ ---
56
+
47
57
  ## Default Modbus Addresses
48
58
 
49
59
  | Device | Address |
@@ -245,6 +255,18 @@ Status and power readings for the DC charger.
245
255
 
246
256
  ## Changelog
247
257
 
258
+ ### 3.1.0 (2026-08-05)
259
+ - (MMeinhardt1) feat: statistics module improvements — new states `pvToBatteryPower`, `batteryToHousePower`, `gridImportToday`, `gridExportToday`, `currentSoc`, `currentPvPower` and `h:mm` formatted durations for all time statistics
260
+ - (MMeinhardt1) feat: daily statistics (SOC min/max, coverage time, grid energy, charging time) are restored from persisted states and now survive an adapter restart mid-day
261
+ - (MMeinhardt1) change: `batteryDailyChargeTime` now reports the cumulative time spent charging today instead of the time until the battery was first full
262
+ - (MMeinhardt1) fix: battery coverage time is accumulated incrementally instead of being derived from the capped history buffer, which only spanned ~1 hour
263
+ - (ssbingo) chore: minimum requirements raised — js-controller >= 6.0.11, admin >= 8.0.0, Node.js >= 22
264
+ - (ssbingo) fix: add missing admin i18n translations for the new battery flow power option across all 11 languages
265
+ - (ssbingo) chore: update dependencies (@iobroker/adapter-core 3.4.3, @iobroker/testing 5.3.0, @types/node 22.20.1, ws 8.21.1, actions/setup-node v7, testing-action-deploy 1.5.2)
266
+
267
+ ### 3.0.10 (2026-06-29)
268
+ - (ssbingo) chore: bump js-yaml from 4.1.1 to 4.3.0
269
+
248
270
  ### 3.0.9 (2026-06-29)
249
271
  - (ssbingo) chore: pin CI actions to major version (@v1) instead of patch version
250
272
 
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Autarkiequote",
17
17
  "Average PV power output over the last 15 minutes": "Durchschnittliche PV-Leistung der letzten 15 Minuten",
18
18
  "Battery / ESS": "Batterie / ESS",
19
+ "Battery charge/discharge source power": "Lade-/Entladeleistung der Batterie (Quelle)",
19
20
  "Battery coverage time today": "Batterie-Abdeckungszeit heute",
20
21
  "Battery time remaining": "Verbleibende Batterielaufzeit",
21
22
  "Baud Rate": "Baudrate",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Aktueller Schritt",
33
34
  "DC Charger": "DC-Ladegerät",
34
35
  "DC fast charging (via inverter)": "DC-Schnellladen (über Wechselrichter)",
35
- "Daily charge completion time": "Tägliche Vollladezeitpunkt",
36
+ "Daily charging time": "Tägliche Ladezeit",
36
37
  "Data Bits": "Datenbits",
37
38
  "Default Modbus Addresses": "Standard-Modbus-Adressen",
38
39
  "Default: 1": "Standard: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Verbindung testen",
118
119
  "Time to full charge": "Zeit bis zur vollen Ladung",
119
- "Today: how long it took until the battery was fully charged": "Heute: wie lange es gedauert hat bis die Batterie voll geladen war",
120
+ "Today: cumulative time the battery spent actively charging": "Heute: kumulierte Zeit, in der die Batterie aktiv geladen hat",
120
121
  "Track daily grid export and import energy": "Tägliche Netzeinspeisung und -bezug erfassen",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Verwende den SigenMicro-Reiter, um den Scan durchzuführen und gefundene Geräte zu verwalten. Die Geräteliste und Einzel-Aktivierungen werden automatisch gespeichert.",
122
123
  "💾 Save selection": "💾 Auswahl speichern",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Geräte konfigurieren, die automatisch schalten, wenn Sigenergy in den Off-Grid-Modus (Inselbetrieb) wechselt. Gerät 1 wird bei Netzausfall immer AUS und nach stabiler Netzzurückkehr EIN geschaltet. Geräte 2–4 sind optional — Schaltrichtung individuell wählbar.",
145
146
  "Stable delay after grid return (minutes)": "Stabilisierungszeit nach Netzzurückkehr (Minuten)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Diese Anzahl Minuten stabilen Netzbetriebs abwarten, bevor Geräte wieder eingeschaltet werden.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "Beim Laden: PV-Leistung, die aktuell in die Batterie fließt. Beim Entladen: Batterieleistung, die aktuell den Hausverbrauch deckt",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Gerät 1 — bei Netzausfall AUS, nach stabiler Erholung EIN (erforderlich bei aktiver Notabschaltung)",
148
150
  "Device 1 — Object ID": "Gerät 1 — Objekt-ID",
149
151
  "Device 2 (optional)": "Gerät 2 (optional)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Autarky rate",
17
17
  "Average PV power output over the last 15 minutes": "Average PV power output over the last 15 minutes",
18
18
  "Battery / ESS": "Battery / ESS",
19
+ "Battery charge/discharge source power": "Battery charge/discharge source power",
19
20
  "Battery coverage time today": "Battery coverage time today",
20
21
  "Battery time remaining": "Battery time remaining",
21
22
  "Baud Rate": "Baud Rate",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Current step",
33
34
  "DC Charger": "DC Charger",
34
35
  "DC fast charging (via inverter)": "DC fast charging (via inverter)",
35
- "Daily charge completion time": "Daily charge completion time",
36
+ "Daily charging time": "Daily charging time",
36
37
  "Data Bits": "Data Bits",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Default: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Test Connection",
118
119
  "Time to full charge": "Time to full charge",
119
- "Today: how long it took until the battery was fully charged": "Today: how long it took until the battery was fully charged",
120
+ "Today: cumulative time the battery spent actively charging": "Today: cumulative time the battery spent actively charging",
120
121
  "Track daily grid export and import energy": "Track daily grid export and import energy",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.",
145
146
  "Stable delay after grid return (minutes)": "Stable delay after grid return (minutes)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Wait this many minutes of stable on-grid operation before switching devices back on.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)",
148
150
  "Device 1 — Object ID": "Device 1 — Object ID",
149
151
  "Device 2 (optional)": "Device 2 (optional)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Tasa de autarquía",
17
17
  "Average PV power output over the last 15 minutes": "Potencia FV media en los últimos 15 minutos",
18
18
  "Battery / ESS": "Batería / ESS",
19
+ "Battery charge/discharge source power": "Potencia de origen de carga/descarga de la batería",
19
20
  "Battery coverage time today": "Tiempo de cobertura de batería hoy",
20
21
  "Battery time remaining": "Tiempo restante de batería",
21
22
  "Baud Rate": "Velocidad de baudios",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Paso actual",
33
34
  "DC Charger": "Cargador DC",
34
35
  "DC fast charging (via inverter)": "Carga rápida DC (a través del inversor)",
35
- "Daily charge completion time": "Hora de finalización de carga diaria",
36
+ "Daily charging time": "Tiempo de carga diario",
36
37
  "Data Bits": "Bits de datos",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Predeterminado: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Probar conexión",
118
119
  "Time to full charge": "Tiempo hasta carga completa",
119
- "Today: how long it took until the battery was fully charged": "Hoy: cuánto tiempo tardó en cargarse completamente la batería",
120
+ "Today: cumulative time the battery spent actively charging": "Hoy: tiempo acumulado que la batería estuvo cargando activamente",
120
121
  "Track daily grid export and import energy": "Seguir la exportación e importación diaria de energía",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Use la pestaña SigenMicro para ejecutar el escaneo y gestionar los dispositivos encontrados.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Configure los dispositivos que se conmutan automáticamente cuando Sigenergy entra en modo fuera de red (isla). El dispositivo 1 siempre se apaga en caso de fallo de red y se enciende tras la recuperación estable. Los dispositivos 2–4 son opcionales — elija la dirección de conmutación para cada uno.",
145
146
  "Stable delay after grid return (minutes)": "Retardo de estabilización tras retorno de red (minutos)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Esperar este número de minutos de operación estable en red antes de volver a encender los dispositivos.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "Durante la carga: potencia FV que fluye actualmente hacia la batería. Durante la descarga: potencia de la batería que cubre actualmente el consumo de la casa",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Dispositivo 1 — APAGADO en fallo de red, ENCENDIDO tras recuperación estable (requerido si la conmutación de emergencia está activa)",
148
150
  "Device 1 — Object ID": "Dispositivo 1 — ID de objeto",
149
151
  "Device 2 (optional)": "Dispositivo 2 (opcional)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Taux d'autarcie",
17
17
  "Average PV power output over the last 15 minutes": "Puissance PV moyenne sur les 15 dernières minutes",
18
18
  "Battery / ESS": "Batterie / ESS",
19
+ "Battery charge/discharge source power": "Puissance source de charge/décharge de la batterie",
19
20
  "Battery coverage time today": "Durée de couverture de la batterie aujourd'hui",
20
21
  "Battery time remaining": "Autonomie restante de la batterie",
21
22
  "Baud Rate": "Débit en bauds",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Étape actuelle",
33
34
  "DC Charger": "Chargeur DC",
34
35
  "DC fast charging (via inverter)": "Charge rapide DC (via onduleur)",
35
- "Daily charge completion time": "Heure de fin de charge quotidienne",
36
+ "Daily charging time": "Temps de charge quotidien",
36
37
  "Data Bits": "Bits de données",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Par défaut : 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Tester la connexion",
118
119
  "Time to full charge": "Temps de charge complète",
119
- "Today: how long it took until the battery was fully charged": "Aujourd'hui : combien de temps a pris la charge complète",
120
+ "Today: cumulative time the battery spent actively charging": "Aujourd'hui : temps cumulé pendant lequel la batterie a été en charge active",
120
121
  "Track daily grid export and import energy": "Suivre l'exportation et l'importation journalières d'énergie",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Utilisez l'onglet SigenMicro pour lancer le scan et gérer les appareils découverts.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Configurez les appareils à commuter automatiquement lorsque Sigenergy passe en mode hors réseau (îlot). L'appareil 1 est toujours mis HORS TENSION en cas de panne secteur et SOUS TENSION après rétablissement stable. Les appareils 2 à 4 sont optionnels — choisissez le sens de commutation pour chacun.",
145
146
  "Stable delay after grid return (minutes)": "Délai de stabilisation après retour réseau (minutes)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Attendre ce nombre de minutes de fonctionnement réseau stable avant de rallumer les appareils.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "En charge : puissance PV qui alimente actuellement la batterie. En décharge : puissance de la batterie qui couvre actuellement la consommation de la maison",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Appareil 1 — ÉTEINT en cas de panne secteur, ALLUMÉ après rétablissement stable (requis si la commutation d'urgence est activée)",
148
150
  "Device 1 — Object ID": "Appareil 1 — ID d'objet",
149
151
  "Device 2 (optional)": "Appareil 2 (optionnel)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Tasso di autosufficienza",
17
17
  "Average PV power output over the last 15 minutes": "Potenza FV media negli ultimi 15 minuti",
18
18
  "Battery / ESS": "Batteria / ESS",
19
+ "Battery charge/discharge source power": "Potenza sorgente di carica/scarica della batteria",
19
20
  "Battery coverage time today": "Tempo di copertura della batteria oggi",
20
21
  "Battery time remaining": "Autonomia residua della batteria",
21
22
  "Baud Rate": "Velocità di trasmissione",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Passo corrente",
33
34
  "DC Charger": "Caricatore DC",
34
35
  "DC fast charging (via inverter)": "Ricarica rapida DC (tramite inverter)",
35
- "Daily charge completion time": "Ora di completamento della carica giornaliera",
36
+ "Daily charging time": "Tempo di ricarica giornaliero",
36
37
  "Data Bits": "Bit di dati",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Predefinito: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Test connessione",
118
119
  "Time to full charge": "Tempo alla carica completa",
119
- "Today: how long it took until the battery was fully charged": "Oggi: quanto tempo ci è voluto per la carica completa",
120
+ "Today: cumulative time the battery spent actively charging": "Oggi: tempo cumulativo in cui la batteria è stata in carica attiva",
120
121
  "Track daily grid export and import energy": "Monitorare esportazione e importazione giornaliera di energia",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Usa la scheda SigenMicro per eseguire la scansione e gestire i dispositivi trovati.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Configura i dispositivi da commutare automaticamente quando Sigenergy entra in modalità off-grid (isola). Il dispositivo 1 viene sempre spento in caso di mancanza rete e riacceso dopo il ripristino stabile. I dispositivi 2–4 sono opzionali — scegli la direzione di commutazione per ciascuno.",
145
146
  "Stable delay after grid return (minutes)": "Ritardo di stabilizzazione dopo il ripristino rete (minuti)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Attendere questo numero di minuti di funzionamento stabile in rete prima di riaccendere i dispositivi.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "In carica: potenza FV che sta attualmente entrando nella batteria. In scarica: potenza della batteria che copre attualmente il consumo domestico",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Dispositivo 1 — SPENTO in caso di mancanza rete, ACCESO dopo ripristino stabile (obbligatorio se la commutazione di emergenza è attiva)",
148
150
  "Device 1 — Object ID": "Dispositivo 1 — ID oggetto",
149
151
  "Device 2 (optional)": "Dispositivo 2 (opzionale)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Autarkiegraad",
17
17
  "Average PV power output over the last 15 minutes": "Gemiddeld PV-vermogen de laatste 15 minuten",
18
18
  "Battery / ESS": "Batterij / ESS",
19
+ "Battery charge/discharge source power": "Bronvermogen batterij laden/ontladen",
19
20
  "Battery coverage time today": "Batterijdekkingstijd vandaag",
20
21
  "Battery time remaining": "Resterende batterijduur",
21
22
  "Baud Rate": "Baudrate",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Huidige stap",
33
34
  "DC Charger": "DC-oplader",
34
35
  "DC fast charging (via inverter)": "DC-snelladen (via omvormer)",
35
- "Daily charge completion time": "Dagelijkse laadvoltooiingstijd",
36
+ "Daily charging time": "Dagelijkse laadtijd",
36
37
  "Data Bits": "Databits",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Standaard: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Verbinding testen",
118
119
  "Time to full charge": "Tijd tot volledig opladen",
119
- "Today: how long it took until the battery was fully charged": "Vandaag: hoe lang het duurde tot de batterij volledig opgeladen was",
120
+ "Today: cumulative time the battery spent actively charging": "Vandaag: cumulatieve tijd dat de batterij actief heeft geladen",
120
121
  "Track daily grid export and import energy": "Dagelijkse netexport en -import bijhouden",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Gebruik de SigenMicro-tab om de scan uit te voeren en gevonden apparaten te beheren.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Configureer apparaten die automatisch schakelen wanneer Sigenergy naar off-grid (eiland) modus gaat. Apparaat 1 wordt altijd UIT geschakeld bij netuitval en AAN na stabiel netwerk herstel. Apparaten 2–4 zijn optioneel — kies voor elk de schakelrichting.",
145
146
  "Stable delay after grid return (minutes)": "Stabilisatievertraging na netterugkeer (minuten)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Wacht dit aantal minuten van stabiele netaansluiting voordat apparaten weer worden ingeschakeld.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "Tijdens opladen: PV-vermogen dat momenteel naar de batterij gaat. Tijdens ontladen: batterijvermogen dat momenteel het huisverbruik dekt",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Apparaat 1 — UIT bij netuitval, AAN na stabiel herstel (vereist bij actieve noodschakeling)",
148
150
  "Device 1 — Object ID": "Apparaat 1 — Object-ID",
149
151
  "Device 2 (optional)": "Apparaat 2 (optioneel)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Wskaźnik autarkii",
17
17
  "Average PV power output over the last 15 minutes": "Średnia moc PV w ciągu ostatnich 15 minut",
18
18
  "Battery / ESS": "Bateria / ESS",
19
+ "Battery charge/discharge source power": "Moc źródła ładowania/rozładowania baterii",
19
20
  "Battery coverage time today": "Czas pokrycia baterii dziś",
20
21
  "Battery time remaining": "Pozostały czas baterii",
21
22
  "Baud Rate": "Prędkość transmisji",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Bieżący krok",
33
34
  "DC Charger": "Ładowarka DC",
34
35
  "DC fast charging (via inverter)": "Szybkie ładowanie DC (przez falownik)",
35
- "Daily charge completion time": "Dzienny czas zakończenia ładowania",
36
+ "Daily charging time": "Dzienny czas ładowania",
36
37
  "Data Bits": "Bity danych",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Domyślnie: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Testuj połączenie",
118
119
  "Time to full charge": "Czas do pełnego naładowania",
119
- "Today: how long it took until the battery was fully charged": "Dziś: ile czasu zajęło pełne naładowanie baterii",
120
+ "Today: cumulative time the battery spent actively charging": "Dziś: skumulowany czas aktywnego ładowania baterii",
120
121
  "Track daily grid export and import energy": "Śledzenie dziennego eksportu i importu energii",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Użyj zakładki SigenMicro do uruchomienia skanu i zarządzania znalezionymi urządzeniami.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Skonfiguruj urządzenia, które automatycznie się przełączają gdy Sigenergy wchodzi w tryb off-grid (wyspa). Urządzenie 1 jest zawsze wyłączane przy awarii sieci i włączane po stabilnym powrocie zasilania. Urządzenia 2–4 są opcjonalne — wybierz kierunek przełączania dla każdego.",
145
146
  "Stable delay after grid return (minutes)": "Opóźnienie stabilizacji po powrocie sieci (minuty)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Odczekaj tę liczbę minut stabilnej pracy sieciowej przed ponownym włączeniem urządzeń.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "Podczas ładowania: moc PV aktualnie płynąca do baterii. Podczas rozładowania: moc baterii aktualnie pokrywająca zużycie domu",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Urządzenie 1 — WYŁ przy awarii sieci, WŁ po stabilnym powrocie (wymagane przy aktywnym przełączaniu awaryjnym)",
148
150
  "Device 1 — Object ID": "Urządzenie 1 — ID obiektu",
149
151
  "Device 2 (optional)": "Urządzenie 2 (opcjonalne)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Taxa de autarcia",
17
17
  "Average PV power output over the last 15 minutes": "Potência média FV nos últimos 15 minutos",
18
18
  "Battery / ESS": "Bateria / ESS",
19
+ "Battery charge/discharge source power": "Potência de origem de carga/descarga da bateria",
19
20
  "Battery coverage time today": "Tempo de cobertura da bateria hoje",
20
21
  "Battery time remaining": "Tempo restante da bateria",
21
22
  "Baud Rate": "Taxa de transmissão",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Passo atual",
33
34
  "DC Charger": "Carregador DC",
34
35
  "DC fast charging (via inverter)": "Carregamento rápido DC (via inversor)",
35
- "Daily charge completion time": "Tempo de conclusão de carga diária",
36
+ "Daily charging time": "Tempo de carga diário",
36
37
  "Data Bits": "Bits de dados",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "Padrão: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Testar ligação",
118
119
  "Time to full charge": "Tempo para carga completa",
119
- "Today: how long it took until the battery was fully charged": "Hoje: quanto tempo demorou até a bateria estar totalmente carregada",
120
+ "Today: cumulative time the battery spent actively charging": "Hoje: tempo acumulado em que a bateria esteve a carregar ativamente",
120
121
  "Track daily grid export and import energy": "Registar exportação e importação diária de energia",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Use a aba SigenMicro para executar o scan e gerenciar dispositivos descobertos.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Configure os dispositivos a comutar automaticamente quando a Sigenergy entra no modo off-grid (ilha). O dispositivo 1 é sempre DESLIGADO em caso de falha de rede e LIGADO após recuperação estável. Os dispositivos 2–4 são opcionais — escolha a direção de comutação para cada um.",
145
146
  "Stable delay after grid return (minutes)": "Atraso de estabilização após retorno da rede (minutos)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Aguardar este número de minutos de operação estável na rede antes de voltar a ligar os dispositivos.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "Durante a carga: potência FV que flui atualmente para a bateria. Durante a descarga: potência da bateria que cobre atualmente o consumo da casa",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Dispositivo 1 — DESLIGADO em falha de rede, LIGADO após recuperação estável (obrigatório se a comutação de emergência estiver ativa)",
148
150
  "Device 1 — Object ID": "Dispositivo 1 — ID do objeto",
149
151
  "Device 2 (optional)": "Dispositivo 2 (opcional)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Степень автономности",
17
17
  "Average PV power output over the last 15 minutes": "Средняя мощность ФЭС за последние 15 минут",
18
18
  "Battery / ESS": "Аккумулятор / ESS",
19
+ "Battery charge/discharge source power": "Мощность источника заряда/разряда батареи",
19
20
  "Battery coverage time today": "Время покрытия аккумулятором сегодня",
20
21
  "Battery time remaining": "Оставшееся время работы аккумулятора",
21
22
  "Baud Rate": "Скорость передачи",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Текущий шаг",
33
34
  "DC Charger": "DC-зарядное устройство",
34
35
  "DC fast charging (via inverter)": "DC быстрая зарядка (через инвертор)",
35
- "Daily charge completion time": "Время завершения суточного заряда",
36
+ "Daily charging time": "Ежедневное время зарядки",
36
37
  "Data Bits": "Биты данных",
37
38
  "Default Modbus Addresses": "Адреса Modbus по умолчанию",
38
39
  "Default: 1": "По умолчанию: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Тест подключения",
118
119
  "Time to full charge": "Время до полного заряда",
119
- "Today: how long it took until the battery was fully charged": "Сегодня: сколько времени потребовалось до полного заряда",
120
+ "Today: cumulative time the battery spent actively charging": "Сегодня: суммарное время активной зарядки батареи",
120
121
  "Track daily grid export and import energy": "Учёт суточного экспорта и импорта электроэнергии",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Используйте вкладку SigenMicro для запуска сканирования и управления устройствами. Список устройств сохраняется автоматически.",
122
123
  "💾 Save selection": "💾 Сохранить выбор",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Настройте устройства для автоматического переключения при переходе Sigenergy в режим off-grid (остров). Устройство 1 всегда выключается при пропадании сети и включается после восстановления. Устройства 2–4 — опциональные, направление переключения задаётся индивидуально.",
145
146
  "Stable delay after grid return (minutes)": "Задержка стабилизации после восстановления сети (минуты)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Ждать это количество минут стабильной работы в сети перед обратным включением устройств.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "При заряде: мощность СЭС, поступающая в батарею. При разряде: мощность батареи, покрывающая потребление дома",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Устройство 1 — ВЫКЛ при пропадании сети, ВКЛ после восстановления (обязательно при активном аварийном отключении)",
148
150
  "Device 1 — Object ID": "Устройство 1 — ID объекта",
149
151
  "Device 2 (optional)": "Устройство 2 (опционально)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "Ступінь автономності",
17
17
  "Average PV power output over the last 15 minutes": "Середня потужність ФЕС за останні 15 хвилин",
18
18
  "Battery / ESS": "Акумулятор / ESS",
19
+ "Battery charge/discharge source power": "Потужність джерела заряду/розряду батареї",
19
20
  "Battery coverage time today": "Час покриття акумулятором сьогодні",
20
21
  "Battery time remaining": "Залишковий час роботи акумулятора",
21
22
  "Baud Rate": "Швидкість передачі",
@@ -32,7 +33,7 @@
32
33
  "Current step": "Поточний крок",
33
34
  "DC Charger": "DC-зарядний пристрій",
34
35
  "DC fast charging (via inverter)": "DC швидке заряджання (через інвертор)",
35
- "Daily charge completion time": "Час завершення добового заряду",
36
+ "Daily charging time": "Щоденний час заряджання",
36
37
  "Data Bits": "Біти даних",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "За замовчуванням: 1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / Ethernet",
117
118
  "Test Connection": "Тест підключення",
118
119
  "Time to full charge": "Час до повного заряду",
119
- "Today: how long it took until the battery was fully charged": "Сьогодні: скільки часу знадобилося до повного заряду",
120
+ "Today: cumulative time the battery spent actively charging": "Сьогодні: сумарний час активного заряджання батареї",
120
121
  "Track daily grid export and import energy": "Облік добового експорту та імпорту електроенергії",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "Використовуйте вкладку SigenMicro для запуску сканування та керування пристроями.",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "Налаштуйте пристрої для автоматичного перемикання при переході Sigenergy в режим off-grid (острів). Пристрій 1 завжди вимикається при зникненні мережі та вмикається після відновлення. Пристрої 2–4 — опціональні, напрямок перемикання задається окремо.",
145
146
  "Stable delay after grid return (minutes)": "Затримка стабілізації після відновлення мережі (хвилини)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "Чекати цю кількість хвилин стабільної роботи в мережі перед повторним увімкненням пристроїв.",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "Під час заряду: потужність СЕС, що надходить у батарею. Під час розряду: потужність батареї, що покриває споживання будинку",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "Пристрій 1 — ВИМК при зникненні мережі, УВМ після відновлення (обов’язково при активному аварійному відключенні)",
148
150
  "Device 1 — Object ID": "Пристрій 1 — ID об’єкта",
149
151
  "Device 2 (optional)": "Пристрій 2 (необов’язково)",
@@ -16,6 +16,7 @@
16
16
  "Autarky rate": "自给率",
17
17
  "Average PV power output over the last 15 minutes": "过去15分钟的平均光伏功率输出",
18
18
  "Battery / ESS": "电池 / 储能系统",
19
+ "Battery charge/discharge source power": "电池充放电来源功率",
19
20
  "Battery coverage time today": "今日电池覆盖时间",
20
21
  "Battery time remaining": "电池剩余时间",
21
22
  "Baud Rate": "波特率",
@@ -32,7 +33,7 @@
32
33
  "Current step": "当前步骤",
33
34
  "DC Charger": "直流充电器",
34
35
  "DC fast charging (via inverter)": "直流快速充电(通过逆变器)",
35
- "Daily charge completion time": "每日充电完成时间",
36
+ "Daily charging time": "每日充电时长",
36
37
  "Data Bits": "数据位",
37
38
  "Default Modbus Addresses": "Default Modbus Addresses",
38
39
  "Default: 1": "默认:1",
@@ -116,7 +117,7 @@
116
117
  "TCP / Ethernet": "TCP / 以太网",
117
118
  "Test Connection": "测试连接",
118
119
  "Time to full charge": "充满时间",
119
- "Today: how long it took until the battery was fully charged": "今天:充满电所花费的时间",
120
+ "Today: cumulative time the battery spent actively charging": "今天:电池实际充电的累计时长",
120
121
  "Track daily grid export and import energy": "追踪每日电网出口和进口电量",
121
122
  "Use the SigenMicro tab in the adapter admin page to run the scan and manage discovered devices. The device list and individual enable/disable selections are stored automatically.": "使用SigenMicro标签页运行扫描并管理发现的设备。",
122
123
  "💾 Save selection": "💾 Save selection",
@@ -144,6 +145,7 @@
144
145
  "Configure devices to switch automatically when Sigenergy enters off-grid (island) mode. Device 1 is always switched OFF on grid failure and ON after stable grid recovery. Devices 2–4 are optional — choose the switching direction for each.": "配置 Sigenergy 进入离网(孤岛)模式时自动切换的设备。设备 1 在电网故障时始终切换为关闭,在电网稳定恢复后切换为开启。设备 2–4 为可选项,可分别选择切换方向。",
145
146
  "Stable delay after grid return (minutes)": "电网恢复后的稳定延迟(分钟)",
146
147
  "Wait this many minutes of stable on-grid operation before switching devices back on.": "在将设备重新开启之前,等待电网稳定运行此分钟数。",
148
+ "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption": "充电时:当前流入电池的光伏功率。放电时:当前用于覆盖家庭用电的电池功率",
147
149
  "Device 1 — switched OFF on grid failure, ON after stable recovery (required if emergency switching is used)": "设备 1 — 电网故障时关闭,稳定恢复后开启(启用应急切换时必填)",
148
150
  "Device 1 — Object ID": "设备 1 — 对象 ID",
149
151
  "Device 2 (optional)": "设备 2(可选)",
@@ -770,8 +770,8 @@
770
770
  },
771
771
  "calcBatteryDailyFull": {
772
772
  "type": "checkbox",
773
- "label": "Daily charge completion time",
774
- "help": "Today: how long it took until the battery was fully charged",
773
+ "label": "Daily charging time",
774
+ "help": "Today: cumulative time the battery spent actively charging",
775
775
  "default": true,
776
776
  "sm": 12,
777
777
  "md": 6,
@@ -790,6 +790,17 @@
790
790
  "lg": 6,
791
791
  "xl": 6
792
792
  },
793
+ "calcBatteryFlowPower": {
794
+ "type": "checkbox",
795
+ "label": "Battery charge/discharge source power",
796
+ "help": "While charging: PV power currently going into the battery. While discharging: battery power currently covering house consumption",
797
+ "default": true,
798
+ "sm": 12,
799
+ "md": 6,
800
+ "xs": 12,
801
+ "lg": 6,
802
+ "xl": 6
803
+ },
793
804
  "calcSelfConsumptionRate": {
794
805
  "type": "checkbox",
795
806
  "label": "Self-consumption rate",
@@ -1091,4 +1102,4 @@
1091
1102
  }
1092
1103
  },
1093
1104
  "i18n": true
1094
- }
1105
+ }
package/io-package.json CHANGED
@@ -1,20 +1,33 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sigenergy",
4
- "version": "3.0.9",
4
+ "version": "3.1.0",
5
5
  "news": {
6
- "3.0.9": {
7
- "en": "(ssbingo) chore: pin CI actions to major version (@v1) instead of patch version",
8
- "de": "(ssbingo) chore: CI-Actions auf Major-Version (@v1) statt Patch-Version fixiert",
9
- "ru": "(ssbingo) chore: закреплены CI-actions на мажорной версии (@v1) вместо патч-версии",
10
- "pt": "(ssbingo) chore: ações de CI fixadas na versão principal (@v1) em vez da versão de patch",
11
- "nl": "(ssbingo) chore: CI-actions vastgezet op hoofdversie (@v1) in plaats van patchversie",
12
- "fr": "(ssbingo) chore: actions CI fixées à la version majeure (@v1) plutôt qu'à la version de patch",
13
- "it": "(ssbingo) chore: azioni CI fissate alla versione principale (@v1) anziché alla versione patch",
14
- "es": "(ssbingo) chore: acciones de CI fijadas a la versión principal (@v1) en lugar de la versión de parche",
15
- "pl": "(ssbingo) chore: akcje CI przypięte do wersji głównej (@v1) zamiast wersji poprawkowej",
16
- "uk": "(ssbingo) chore: CI-actions закріплені на мажорній версії (@v1) замість патч-версії",
17
- "zh-cn": "(ssbingo) chore: CI actions 固定到主版本 (@v1) 而非补丁版本"
6
+ "3.1.0": {
7
+ "en": "(MMeinhardt1) feat: statistics improvements — battery flow power, daily grid import/export, h:mm durations, cumulative daily charging time; daily statistics now survive an adapter restart. (ssbingo) chore: minimum requirements raised to js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
8
+ "de": "(MMeinhardt1) feat: Statistik-Erweiterungen — Batterie-Flussleistung, täglicher Netzbezug/-einspeisung, h:mm-Zeitdauern, kumulierte tägliche Ladezeit; Tagesstatistiken überstehen jetzt einen Adapter-Neustart. (ssbingo) chore: Mindestanforderungen angehoben auf js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
9
+ "ru": "(MMeinhardt1) feat: улучшения статистики — мощность потоков батареи, суточный импорт/экспорт из сети, длительности в формате h:mm, суммарное суточное время зарядки; суточная статистика теперь сохраняется при перезапуске адаптера. (ssbingo) chore: минимальные требования повышены до js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
10
+ "pt": "(MMeinhardt1) feat: melhorias nas estatísticas — potência de fluxo da bateria, importação/exportação diária da rede, durações em h:mm, tempo de carga diário acumulado; as estatísticas diárias agora sobrevivem a um reinício do adaptador. (ssbingo) chore: requisitos mínimos elevados para js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
11
+ "nl": "(MMeinhardt1) feat: statistiekverbeteringen — batterijstroomvermogen, dagelijkse netimport/-export, h:mm-tijdsduren, cumulatieve dagelijkse laadtijd; dagstatistieken overleven nu een herstart van de adapter. (ssbingo) chore: minimumvereisten verhoogd naar js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
12
+ "fr": "(MMeinhardt1) feat : améliorations des statistiques — puissance de flux de la batterie, import/export réseau quotidien, durées au format h:mm, temps de charge quotidien cumulé ; les statistiques journalières survivent désormais à un redémarrage de l'adaptateur. (ssbingo) chore : exigences minimales relevées à js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
13
+ "it": "(MMeinhardt1) feat: miglioramenti alle statistiche — potenza di flusso della batteria, importazione/esportazione giornaliera dalla rete, durate in formato h:mm, tempo di ricarica giornaliero cumulativo; le statistiche giornaliere sopravvivono ora a un riavvio dell'adattatore. (ssbingo) chore: requisiti minimi elevati a js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
14
+ "es": "(MMeinhardt1) feat: mejoras en las estadísticas — potencia de flujo de la batería, importación/exportación diaria de la red, duraciones en h:mm, tiempo de carga diario acumulado; las estadísticas diarias ahora sobreviven a un reinicio del adaptador. (ssbingo) chore: requisitos mínimos elevados a js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
15
+ "pl": "(MMeinhardt1) feat: ulepszenia statystyk — moc przepływu baterii, dzienny import/eksport z sieci, czasy w formacie h:mm, skumulowany dzienny czas ładowania; statystyki dzienne przetrwają teraz restart adaptera. (ssbingo) chore: minimalne wymagania podniesione do js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
16
+ "uk": "(MMeinhardt1) feat: покращення статистики — потужність потоків батареї, добовий імпорт/експорт із мережі, тривалості у форматі h:mm, сумарний добовий час заряджання; добова статистика тепер зберігається під час перезапуску адаптера. (ssbingo) chore: мінімальні вимоги підвищено до js-controller 6.0.11 / admin 8.0.0 / Node.js 22",
17
+ "zh-cn": "(MMeinhardt1) feat: 统计功能改进 — 电池流量功率、每日电网进口/出口、h:mm 时长格式、每日累计充电时长;每日统计现在可在适配器重启后保留。(ssbingo) chore: 最低要求提升至 js-controller 6.0.11 / admin 8.0.0 / Node.js 22"
18
+ },
19
+ "3.0.10": {
20
+ "en": "(ssbingo) chore: bump js-yaml from 4.1.1 to 4.3.0",
21
+ "de": "(ssbingo) chore: js-yaml von 4.1.1 auf 4.3.0 aktualisiert",
22
+ "ru": "(ssbingo) chore: обновление js-yaml с 4.1.1 до 4.3.0",
23
+ "pt": "(ssbingo) chore: atualização do js-yaml de 4.1.1 para 4.3.0",
24
+ "nl": "(ssbingo) chore: js-yaml bijgewerkt van 4.1.1 naar 4.3.0",
25
+ "fr": "(ssbingo) chore: mise à jour de js-yaml de 4.1.1 vers 4.3.0",
26
+ "it": "(ssbingo) chore: aggiornamento di js-yaml da 4.1.1 a 4.3.0",
27
+ "es": "(ssbingo) chore: actualización de js-yaml de 4.1.1 a 4.3.0",
28
+ "pl": "(ssbingo) chore: aktualizacja js-yaml z 4.1.1 do 4.3.0",
29
+ "uk": "(ssbingo) chore: оновлення js-yaml з 4.1.1 до 4.3.0",
30
+ "zh-cn": "(ssbingo) chore: js-yaml 从 4.1.1 升级到 4.3.0"
18
31
  }
19
32
  },
20
33
  "titleLang": {
@@ -82,7 +95,7 @@
82
95
  ],
83
96
  "globalDependencies": [
84
97
  {
85
- "admin": ">=7.6.20"
98
+ "admin": ">=8.0.0"
86
99
  }
87
100
  ],
88
101
  "licenseInformation": {
@@ -114,6 +127,7 @@
114
127
  "calcBatteryTimeRemaining": true,
115
128
  "calcBatteryDailyFull": true,
116
129
  "calcBatteryCoverageTime": true,
130
+ "calcBatteryFlowPower": true,
117
131
  "calcSelfConsumptionRate": true,
118
132
  "calcAutarkyRate": true,
119
133
  "calcPvYield": true,
@@ -219,4 +233,4 @@
219
233
  "native": {}
220
234
  }
221
235
  ]
222
- }
236
+ }
package/lib/statistics.js CHANGED
@@ -25,6 +25,9 @@ class StatisticsCalculator {
25
25
  this._maxHistory = 360; // 1 hour at 10s intervals
26
26
  this._dayStart = this._getTodayStart();
27
27
  this._dayStats = this._getDefaultDayStats();
28
+ this._lastCoverageTs = null; // Timestamp of the previous update() call, for incremental coverage tracking
29
+ this._lastGridEnergyTs = null; // Timestamp of the previous update() call, for incremental grid energy integration
30
+ this._lastChargeTs = null; // Timestamp of the previous update() call, for incremental charging time integration
28
31
  }
29
32
 
30
33
  /**
@@ -51,6 +54,10 @@ class StatisticsCalculator {
51
54
  maxSoc: 0,
52
55
  minSoc: 100,
53
56
  chargeStartTime: null,
57
+ batteryCoverageMs: 0, // Accumulated ms today where battery covered house consumption
58
+ gridImportEnergyWh: 0, // Accumulated Wh imported from grid today
59
+ gridExportEnergyWh: 0, // Accumulated Wh exported to grid today
60
+ batteryChargeMs: 0, // Accumulated ms today the battery spent actively charging
54
61
  };
55
62
  }
56
63
 
@@ -92,6 +99,9 @@ class StatisticsCalculator {
92
99
  this._dayStart = todayStart;
93
100
  this._dayStats = this._getDefaultDayStats();
94
101
  this._smoothingBuffer = [];
102
+ this._lastCoverageTs = null;
103
+ this._lastGridEnergyTs = null;
104
+ this._lastChargeTs = null;
95
105
  }
96
106
 
97
107
  if (data.essPower !== undefined) {
@@ -135,6 +145,48 @@ class StatisticsCalculator {
135
145
  }
136
146
  }
137
147
 
148
+ // Track battery coverage time incrementally (avoids relying on the
149
+ // capped _history arrays, which only hold the last _maxHistory entries
150
+ // and therefore do not span a full day).
151
+ if (data.essPower !== undefined && data.gridPower !== undefined) {
152
+ if (this._lastCoverageTs !== null) {
153
+ const dt = now - this._lastCoverageTs;
154
+ if (data.essPower < -0.05 && data.gridPower < 0.02) {
155
+ this._dayStats.batteryCoverageMs += dt;
156
+ }
157
+ }
158
+ this._lastCoverageTs = now;
159
+ }
160
+
161
+ // Track daily grid import/export energy incrementally by integrating
162
+ // power (kW) over elapsed time (h) between polls -> Wh, mirroring the
163
+ // battery coverage tracking above.
164
+ if (data.gridPower !== undefined) {
165
+ if (this._lastGridEnergyTs !== null) {
166
+ const dtHours = (now - this._lastGridEnergyTs) / 3600000;
167
+ const energyWh = data.gridPower * 1000 * dtHours;
168
+ if (energyWh > 0) {
169
+ this._dayStats.gridImportEnergyWh += energyWh;
170
+ } else {
171
+ this._dayStats.gridExportEnergyWh += Math.abs(energyWh);
172
+ }
173
+ }
174
+ this._lastGridEnergyTs = now;
175
+ }
176
+
177
+ // Track cumulative time spent actively charging today. Counts up live
178
+ // while essPower indicates charging, pauses while not, and resumes
179
+ // accumulating if charging starts again later the same day.
180
+ if (data.essPower !== undefined) {
181
+ if (this._lastChargeTs !== null) {
182
+ const dt = now - this._lastChargeTs;
183
+ if (data.essPower > 0.1) {
184
+ this._dayStats.batteryChargeMs += dt;
185
+ }
186
+ }
187
+ this._lastChargeTs = now;
188
+ }
189
+
138
190
  Object.keys(this._history).forEach(key => this._trimHistory(key));
139
191
  }
140
192
 
@@ -149,6 +201,45 @@ class StatisticsCalculator {
149
201
  }
150
202
  }
151
203
 
204
+ /**
205
+ * Restore in-memory "today" statistics from previously persisted ioBroker
206
+ * state values after an adapter restart. Each entry is only applied if it
207
+ * was last written today — otherwise it belongs to a previous day and the
208
+ * freshly initialized defaults (from _getDefaultDayStats()) are already
209
+ * correct as-is. Any entry that is missing, has a non-number val, or is
210
+ * stale is simply left untouched.
211
+ *
212
+ * @param {object} persisted - Previously persisted state values, keyed by
213
+ * the metric name, each as { val: number, ts: number } | undefined:
214
+ * - dayMinSoc, dayMaxSoc: statistics.dayMinSoc / dayMaxSoc (%)
215
+ * - batteryCoverageToday: statistics.batteryCoverageToday (minutes)
216
+ * - gridImportToday, gridExportToday: statistics.gridImportToday / gridExportToday (kWh)
217
+ * - batteryDailyChargeTime: statistics.batteryDailyChargeTime (minutes)
218
+ */
219
+ restoreDayStats(persisted) {
220
+ const isValidToday = entry =>
221
+ entry && typeof entry.val === 'number' && typeof entry.ts === 'number' && entry.ts >= this._dayStart;
222
+
223
+ if (isValidToday(persisted.dayMinSoc) && persisted.dayMinSoc.val >= 0 && persisted.dayMinSoc.val <= 100) {
224
+ this._dayStats.minSoc = persisted.dayMinSoc.val;
225
+ }
226
+ if (isValidToday(persisted.dayMaxSoc) && persisted.dayMaxSoc.val >= 0 && persisted.dayMaxSoc.val <= 100) {
227
+ this._dayStats.maxSoc = persisted.dayMaxSoc.val;
228
+ }
229
+ if (isValidToday(persisted.batteryCoverageToday)) {
230
+ this._dayStats.batteryCoverageMs = persisted.batteryCoverageToday.val * 60000;
231
+ }
232
+ if (isValidToday(persisted.gridImportToday)) {
233
+ this._dayStats.gridImportEnergyWh = persisted.gridImportToday.val * 1000;
234
+ }
235
+ if (isValidToday(persisted.gridExportToday)) {
236
+ this._dayStats.gridExportEnergyWh = persisted.gridExportToday.val * 1000;
237
+ }
238
+ if (isValidToday(persisted.batteryDailyChargeTime)) {
239
+ this._dayStats.batteryChargeMs = persisted.batteryDailyChargeTime.val * 60000;
240
+ }
241
+ }
242
+
152
243
  // --- Battery Estimation Methods ---
153
244
 
154
245
  /**
@@ -187,32 +278,15 @@ class StatisticsCalculator {
187
278
  /**
188
279
  * Calculate minutes today during which battery covered consumption
189
280
  *
281
+ * Uses the incrementally accumulated _dayStats.batteryCoverageMs value
282
+ * (updated on every update() call) instead of reconstructing it from
283
+ * _history, since _history is capped at _maxHistory entries (~1 hour)
284
+ * and does not span a full day.
285
+ *
190
286
  * @returns {number} Coverage minutes
191
287
  */
192
288
  calcBatteryCoverageToday() {
193
- const gridHistory = this._history.gridPower.filter(e => e.ts >= this._dayStart);
194
- const essHistory = this._history.essPower.filter(e => e.ts >= this._dayStart);
195
- if (gridHistory.length < 2) {
196
- return 0;
197
- }
198
-
199
- let coverageMs = 0;
200
- for (let i = 1; i < gridHistory.length; i++) {
201
- const dt = gridHistory[i].ts - gridHistory[i - 1].ts;
202
- const gridVal = gridHistory[i].v;
203
- // Find nearest ESS value
204
- const essEntry = essHistory.reduce(
205
- (prev, curr) =>
206
- Math.abs(curr.ts - gridHistory[i].ts) < Math.abs(prev.ts - gridHistory[i].ts) ? curr : prev,
207
- essHistory[0],
208
- );
209
-
210
- // Covered if battery is discharging and grid import is near zero
211
- if (essEntry && essEntry.v < -0.05 && gridVal < 0.02) {
212
- coverageMs += dt;
213
- }
214
- }
215
- return Math.round(coverageMs / 60000);
289
+ return Math.round(this._dayStats.batteryCoverageMs / 60000);
216
290
  }
217
291
 
218
292
  /**
@@ -235,16 +309,39 @@ class StatisticsCalculator {
235
309
  stats.batteryTimeRemaining = this.calcTimeRemaining(cd.soc, cd.essPower, cd.ratedCapacity, cd.cutoffSoc);
236
310
  }
237
311
 
238
- // Daily Battery Statistics
239
- if (config.calcBatteryDailyFull && this._dayStats.batteryFullTime) {
240
- const start = this._dayStats.chargeStartTime || this._dayStart;
241
- stats.batteryDailyChargeTime = Math.round((this._dayStats.batteryFullTime - start) / 60000);
312
+ // Daily Battery Statistics: cumulative minutes spent charging today.
313
+ // Counts up live while charging, holds while not, resumes on the next
314
+ // charge cycle the same day. Always a number (0 if not charged yet today).
315
+ if (config.calcBatteryDailyFull) {
316
+ stats.batteryDailyChargeTime = Math.round(this._dayStats.batteryChargeMs / 60000);
242
317
  }
243
318
 
244
319
  if (config.calcBatteryCoverageTime) {
245
320
  stats.batteryCoverageToday = this.calcBatteryCoverageToday();
246
321
  }
247
322
 
323
+ // Current battery charge/discharge source power
324
+ if (config.calcBatteryFlowPower) {
325
+ const pv = cd.pvPower || 0;
326
+ const ess = cd.essPower || 0;
327
+
328
+ // Charging: portion of currently generated PV power flowing into the battery.
329
+ // Capped at both the available PV power and the actual charge power, since
330
+ // charging can also be sourced from the grid (e.g. force-charge on a cheap tariff).
331
+ stats.pvToBatteryPower = ess > 0.05 ? Math.round(Math.min(pv, ess) * 100) / 100 : 0;
332
+
333
+ // Discharging: battery power currently covering house consumption.
334
+ // Only non-zero while ess is discharging, which in practice is when PV
335
+ // generation is insufficient (or absent) to cover the load.
336
+ stats.batteryToHousePower = ess < -0.05 ? Math.round(Math.abs(ess) * 100) / 100 : 0;
337
+ }
338
+
339
+ // Daily grid import/export energy
340
+ if (config.calcGridFeedIn) {
341
+ stats.gridImportToday = Math.round((this._dayStats.gridImportEnergyWh / 1000) * 100) / 100;
342
+ stats.gridExportToday = Math.round((this._dayStats.gridExportEnergyWh / 1000) * 100) / 100;
343
+ }
344
+
248
345
  // Efficiency Rates
249
346
  if (config.calcSelfConsumptionRate) {
250
347
  const export_ = cd.gridPower < 0 ? Math.abs(cd.gridPower) : 0;
@@ -261,6 +358,8 @@ class StatisticsCalculator {
261
358
  }
262
359
 
263
360
  stats.housePower = currentHousePower;
361
+ stats.currentSoc = cd.soc;
362
+ stats.currentPvPower = cd.pvPower;
264
363
  stats.dayMaxSoc = this._dayStats.maxSoc;
265
364
  stats.dayMinSoc = this._dayStats.minSoc;
266
365
 
package/main.js CHANGED
@@ -292,6 +292,10 @@ class Sigenergy extends utils.Adapter {
292
292
  return;
293
293
  }
294
294
 
295
+ // Restore today's accumulated statistics from the last persisted state
296
+ // values, so a restart mid-day does not reset them to zero / current.
297
+ await this._restoreDayStats();
298
+
295
299
  // Connect and start polling
296
300
  await this._connectAndPoll();
297
301
 
@@ -1136,6 +1140,31 @@ class Sigenergy extends utils.Adapter {
1136
1140
  }
1137
1141
  }
1138
1142
 
1143
+ /**
1144
+ * Format a minute value as an "H:MMh" string (e.g. 83 -> "1:23h").
1145
+ * Hours are not capped at 24. Distinguishes three cases so the caller's
1146
+ * null-vs-undefined write semantics (see _updateStatistics) are preserved:
1147
+ * - undefined (statistic disabled via config) -> undefined (skip write)
1148
+ * - null / NaN (statistic enabled but currently N/A) -> null (clears stale value)
1149
+ * - number -> formatted "H:MMh" string
1150
+ *
1151
+ * @param {number|null|undefined} totalMinutes - Duration in minutes, or null/undefined per the cases above
1152
+ * @returns {string|null|undefined} Formatted "H:MMh" string, or null/undefined mirroring the input case
1153
+ */
1154
+ _formatMinutesAsHM(totalMinutes) {
1155
+ if (totalMinutes === undefined) {
1156
+ return undefined;
1157
+ }
1158
+ if (typeof totalMinutes !== 'number' || Number.isNaN(totalMinutes)) {
1159
+ return null;
1160
+ }
1161
+ const sign = totalMinutes < 0 ? '-' : '';
1162
+ const abs = Math.round(Math.abs(totalMinutes));
1163
+ const hours = Math.floor(abs / 60);
1164
+ const minutes = abs % 60;
1165
+ return `${sign}${hours}:${String(minutes).padStart(2, '0')}h`;
1166
+ }
1167
+
1139
1168
  /**
1140
1169
  * Update and write statistics states
1141
1170
  */
@@ -1148,12 +1177,22 @@ class Sigenergy extends utils.Adapter {
1148
1177
 
1149
1178
  const mapping = {
1150
1179
  'statistics.batteryTimeToFull': statsValues.batteryTimeToFull,
1180
+ 'statistics.batteryTimeToFullHM': this._formatMinutesAsHM(statsValues.batteryTimeToFull),
1151
1181
  'statistics.batteryTimeRemaining': statsValues.batteryTimeRemaining,
1182
+ 'statistics.batteryTimeRemainingHM': this._formatMinutesAsHM(statsValues.batteryTimeRemaining),
1152
1183
  'statistics.batteryDailyChargeTime': statsValues.batteryDailyChargeTime,
1184
+ 'statistics.batteryDailyChargeTimeHM': this._formatMinutesAsHM(statsValues.batteryDailyChargeTime),
1153
1185
  'statistics.batteryCoverageToday': statsValues.batteryCoverageToday,
1186
+ 'statistics.batteryCoverageTodayHM': this._formatMinutesAsHM(statsValues.batteryCoverageToday),
1187
+ 'statistics.pvToBatteryPower': statsValues.pvToBatteryPower,
1188
+ 'statistics.batteryToHousePower': statsValues.batteryToHousePower,
1189
+ 'statistics.gridImportToday': statsValues.gridImportToday,
1190
+ 'statistics.gridExportToday': statsValues.gridExportToday,
1154
1191
  'statistics.selfConsumptionRate': statsValues.selfConsumptionRate,
1155
1192
  'statistics.autarkyRate': statsValues.autarkyRate,
1156
1193
  'statistics.housePower': statsValues.housePower,
1194
+ 'statistics.currentSoc': statsValues.currentSoc,
1195
+ 'statistics.currentPvPower': statsValues.currentPvPower,
1157
1196
  'statistics.dayMaxSoc': statsValues.dayMaxSoc,
1158
1197
  'statistics.dayMinSoc': statsValues.dayMinSoc,
1159
1198
  };
@@ -1162,7 +1201,13 @@ class Sigenergy extends utils.Adapter {
1162
1201
  if (this._stopped) {
1163
1202
  return;
1164
1203
  }
1165
- if (val !== undefined && val !== null) {
1204
+ // Only skip when the value is `undefined` (the corresponding statistic is
1205
+ // disabled via config, so the key never appears in statsValues at all).
1206
+ // `null` is an intentional result (e.g. battery fully charged -> no time-to-full,
1207
+ // not discharging -> no time-remaining) and must be written to clear any stale
1208
+ // numeric value left over from a previous poll — otherwise e.g. batteryTimeToFull
1209
+ // would keep showing the last computed minutes forever after the battery reaches 100%.
1210
+ if (val !== undefined) {
1166
1211
  await this.setStateAsync(id, { val, ack: true });
1167
1212
  }
1168
1213
  }
@@ -1625,6 +1670,13 @@ class Sigenergy extends utils.Adapter {
1625
1670
  unit: 'min',
1626
1671
  role: 'value',
1627
1672
  },
1673
+ {
1674
+ id: 'statistics.batteryTimeToFullHM',
1675
+ name: 'Time until battery is fully charged (h:mm)',
1676
+ type: 'string',
1677
+ unit: '',
1678
+ role: 'text',
1679
+ },
1628
1680
  {
1629
1681
  id: 'statistics.batteryTimeRemaining',
1630
1682
  name: 'Battery time remaining at current load',
@@ -1632,13 +1684,27 @@ class Sigenergy extends utils.Adapter {
1632
1684
  unit: 'min',
1633
1685
  role: 'value',
1634
1686
  },
1687
+ {
1688
+ id: 'statistics.batteryTimeRemainingHM',
1689
+ name: 'Battery time remaining at current load (h:mm)',
1690
+ type: 'string',
1691
+ unit: '',
1692
+ role: 'text',
1693
+ },
1635
1694
  {
1636
1695
  id: 'statistics.batteryDailyChargeTime',
1637
- name: 'Today: minutes until battery was full',
1696
+ name: 'Today: cumulative minutes spent charging',
1638
1697
  type: 'number',
1639
1698
  unit: 'min',
1640
1699
  role: 'value',
1641
1700
  },
1701
+ {
1702
+ id: 'statistics.batteryDailyChargeTimeHM',
1703
+ name: 'Today: cumulative time spent charging (h:mm)',
1704
+ type: 'string',
1705
+ unit: '',
1706
+ role: 'text',
1707
+ },
1642
1708
  {
1643
1709
  id: 'statistics.batteryCoverageToday',
1644
1710
  name: 'Today: minutes battery covered consumption',
@@ -1646,6 +1712,41 @@ class Sigenergy extends utils.Adapter {
1646
1712
  unit: 'min',
1647
1713
  role: 'value',
1648
1714
  },
1715
+ {
1716
+ id: 'statistics.batteryCoverageTodayHM',
1717
+ name: 'Today: time battery covered consumption (h:mm)',
1718
+ type: 'string',
1719
+ unit: '',
1720
+ role: 'text',
1721
+ },
1722
+ {
1723
+ id: 'statistics.pvToBatteryPower',
1724
+ name: 'PV power currently charging the battery',
1725
+ type: 'number',
1726
+ unit: 'kW',
1727
+ role: 'value.power',
1728
+ },
1729
+ {
1730
+ id: 'statistics.batteryToHousePower',
1731
+ name: 'Battery power currently covering house consumption',
1732
+ type: 'number',
1733
+ unit: 'kW',
1734
+ role: 'value.power',
1735
+ },
1736
+ {
1737
+ id: 'statistics.gridImportToday',
1738
+ name: 'Today: energy imported from grid',
1739
+ type: 'number',
1740
+ unit: 'kWh',
1741
+ role: 'value.energy',
1742
+ },
1743
+ {
1744
+ id: 'statistics.gridExportToday',
1745
+ name: 'Today: energy exported to grid',
1746
+ type: 'number',
1747
+ unit: 'kWh',
1748
+ role: 'value.energy',
1749
+ },
1649
1750
  {
1650
1751
  id: 'statistics.selfConsumptionRate',
1651
1752
  name: 'Self-consumption rate',
@@ -1667,6 +1768,20 @@ class Sigenergy extends utils.Adapter {
1667
1768
  unit: 'kW',
1668
1769
  role: 'value.power',
1669
1770
  },
1771
+ {
1772
+ id: 'statistics.currentSoc',
1773
+ name: 'Current battery SOC (copy for convenience)',
1774
+ type: 'number',
1775
+ unit: '%',
1776
+ role: 'value.battery',
1777
+ },
1778
+ {
1779
+ id: 'statistics.currentPvPower',
1780
+ name: 'Current PV power (copy for convenience)',
1781
+ type: 'number',
1782
+ unit: 'kW',
1783
+ role: 'value.power',
1784
+ },
1670
1785
  {
1671
1786
  id: 'statistics.dayMaxSoc',
1672
1787
  name: 'Today maximum SOC',
@@ -1701,6 +1816,52 @@ class Sigenergy extends utils.Adapter {
1701
1816
  }
1702
1817
  }
1703
1818
 
1819
+ /**
1820
+ * Restore "today" statistics from the last persisted ioBroker state
1821
+ * values after an adapter restart. Several statistics.* values are
1822
+ * accumulated in memory across the day (SOC min/max, battery coverage
1823
+ * time, grid import/export energy, daily charge completion time) and
1824
+ * would otherwise incorrectly reset whenever the adapter restarts
1825
+ * mid-day, instead of retaining the actual values recorded so far today.
1826
+ */
1827
+ async _restoreDayStats() {
1828
+ if (!this._caps || !this._caps.plant) {
1829
+ return;
1830
+ }
1831
+ try {
1832
+ const ids = [
1833
+ 'statistics.dayMinSoc',
1834
+ 'statistics.dayMaxSoc',
1835
+ 'statistics.batteryCoverageToday',
1836
+ 'statistics.gridImportToday',
1837
+ 'statistics.gridExportToday',
1838
+ 'statistics.batteryDailyChargeTime',
1839
+ ];
1840
+ const states = await Promise.all(ids.map(id => this.getStateAsync(id)));
1841
+
1842
+ const persisted = {};
1843
+ const keys = [
1844
+ 'dayMinSoc',
1845
+ 'dayMaxSoc',
1846
+ 'batteryCoverageToday',
1847
+ 'gridImportToday',
1848
+ 'gridExportToday',
1849
+ 'batteryDailyChargeTime',
1850
+ ];
1851
+ keys.forEach((key, i) => {
1852
+ const s = states[i];
1853
+ if (s && typeof s.val === 'number') {
1854
+ persisted[key] = { val: s.val, ts: s.ts || 0 };
1855
+ }
1856
+ });
1857
+
1858
+ this.stats.restoreDayStats(persisted);
1859
+ this.log.debug(`Restored today's statistics from persisted states: ${JSON.stringify(persisted)}`);
1860
+ } catch (err) {
1861
+ this.log.debug(`Could not restore today's statistics from states: ${err.message}`);
1862
+ }
1863
+ }
1864
+
1704
1865
  /**
1705
1866
  * Handle state changes — process commands (ack=false) on RW registers
1706
1867
  *
@@ -2332,7 +2493,7 @@ class Sigenergy extends utils.Adapter {
2332
2493
  /**
2333
2494
  * Returns true when the onOffGridStatus value indicates off-grid operation.
2334
2495
  *
2335
- * @param {number|null|undefined} val - current onOffGridStatus value
2496
+ * @param {ioBroker.StateValue|undefined} val - current onOffGridStatus value
2336
2497
  */
2337
2498
  _emergencyIsOffGrid(val) {
2338
2499
  return val !== 0 && val !== null && val !== undefined;
@@ -2341,7 +2502,7 @@ class Sigenergy extends utils.Adapter {
2341
2502
  /**
2342
2503
  * Human-readable description of an onOffGridStatus value.
2343
2504
  *
2344
- * @param {number|null|undefined} val - current onOffGridStatus value
2505
+ * @param {ioBroker.StateValue|undefined} val - current onOffGridStatus value
2345
2506
  */
2346
2507
  _emergencyModeName(val) {
2347
2508
  switch (val) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.sigenergy",
3
- "version": "3.0.9",
3
+ "version": "3.1.0",
4
4
  "description": "ioBroker adapter for Sigenergy solar energy systems via Modbus TCP/RTU",
5
5
  "author": {
6
6
  "name": "ssbingo",
@@ -23,7 +23,7 @@
23
23
  "url": "https://github.com/ssbingo/ioBroker.sigenergy.git"
24
24
  },
25
25
  "dependencies": {
26
- "@iobroker/adapter-core": "^3.4.1",
26
+ "@iobroker/adapter-core": "^3.4.3",
27
27
  "modbus-serial": "^8.0.25",
28
28
  "serialport": "^13.0.0"
29
29
  },
@@ -35,9 +35,9 @@
35
35
  "@iobroker/adapter-dev": "^1.5.0",
36
36
  "@iobroker/dev-server": "^0.8.0",
37
37
  "@iobroker/eslint-config": "^2.3.4",
38
- "@iobroker/testing": "^5.2.2",
38
+ "@iobroker/testing": "^5.3.0",
39
39
  "@tsconfig/node22": "^22.0.5",
40
- "@types/node": "^22.20.0"
40
+ "@types/node": "^22.20.1"
41
41
  },
42
42
  "main": "main.js",
43
43
  "files": [