Erster Stand der Hintergrundprozesse, die auf der Synology unter /volume1/homes/wagner/SolarManager laufen: der Manager selbst, die Sammler je Geraet, die MQTT-Bruecke, der Wecker und - neu hinzugezogen - der AutoAction-Runner, der als Hintergrundprozess hierher gehoert und nicht ins Web-Verzeichnis. Zugangsdaten stehen nicht mehr im Quelltext, sondern in config.ini, die nicht mit eingecheckt wird. Vorlage ist config.ini.example, gelesen wird sie von konfig.py. Betroffen waren solarManager.py (Datenbank und Wattpilot), zeit.py, gatherWaterData.py, wecker.py und skoda_testdaten.py, das sich das Passwort bisher aus dem Quelltext eines anderen Moduls herausgesucht hat. Die Kia-Anbindung ist mit dem Fahrzeug entfallen: kiaTest.py, gatherCarData.py und hyundai_kia_connect_api sind nicht mehr dabei, ebenso gatherInverterData.py, auf das nur noch eine auskommentierte Zeile zeigte. Die mitgelieferten Bibliotheken bleiben im Repository - die NAS hat kein pip, sie muessen neben den Skripten liegen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
561 lines
27 KiB
Python
561 lines
27 KiB
Python
import asyncio
|
|
import json
|
|
import aiohttp
|
|
import sys
|
|
import logging
|
|
import sunspec2.modbus.client as client
|
|
import datetime
|
|
from typing import List
|
|
from dataclasses import dataclass
|
|
from dataclasses import field
|
|
from operator import attrgetter
|
|
from time import sleep
|
|
import traceback
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
batStat = {
|
|
1: "OFF",
|
|
2: "EMPTY",
|
|
3: "DISCHARGING",
|
|
4: "CHARGING",
|
|
5: "FULL",
|
|
6: "HOLDING",
|
|
7: "TESTING",
|
|
}
|
|
wrStat = {
|
|
1: "OFF",
|
|
2: "SLEEPING",
|
|
3: "STARTING",
|
|
4: "MPPT",
|
|
5: "THROTTLED",
|
|
6: "SHUTTING_DOWN",
|
|
7: "FAULT",
|
|
}
|
|
|
|
@dataclass
|
|
class ModbusRegisters:
|
|
ppv0_reg = ""
|
|
ppv1_reg = ""
|
|
pbat_crg_reg = ""
|
|
pbat_discrg_reg = ""
|
|
ubat_reg = ""
|
|
ibat_crg_reg = ""
|
|
ibat_discrg_reg = ""
|
|
pACinv_reg = ""
|
|
soc_reg = ""
|
|
battStat_reg = ""
|
|
wrStat_reg = ""
|
|
|
|
pACevu_reg = ""
|
|
pL1ACevu_reg = ""
|
|
pL2ACevu_reg = ""
|
|
pL3ACevu_reg = ""
|
|
iL1evu_reg = ""
|
|
iL2evu_reg = ""
|
|
iL3evu_reg = ""
|
|
|
|
pACog_reg = ""
|
|
pL1ACog_reg = ""
|
|
pL2ACog_reg = ""
|
|
pL3ACog_reg = ""
|
|
iL1og_reg = ""
|
|
iL2og_reg = ""
|
|
iL3og_reg = ""
|
|
|
|
limitChrgRate = ""
|
|
setChargeLimits = ""
|
|
|
|
setPowerLimitPercent = ""
|
|
setPowerLimitEN = ""
|
|
|
|
|
|
|
|
@dataclass
|
|
class InverterData:
|
|
p_PV:List[float] = field(default_factory=lambda: [0.0,0.0])
|
|
error:int = 0
|
|
load: float = 0.0
|
|
soc: float = 0.0
|
|
pbat: float = 0.0
|
|
ppv: float = 0.0
|
|
ppv2: float = 0.0
|
|
aut: float = 0.0
|
|
pgrid: float = 0.0
|
|
ibatt: float = 0.0
|
|
ubatt: float = 0.0
|
|
temp: float = 0.0
|
|
p_l1evu: float = 0.0
|
|
p_l2evu: float = 0.0
|
|
p_l3evu: float = 0.0
|
|
p_l1og: float = 0.0
|
|
p_l2og: float = 0.0
|
|
p_l3og: float = 0.0
|
|
i_l1evu: float = 0.0
|
|
i_l2evu: float = 0.0
|
|
i_l3evu: float = 0.0
|
|
i_l1og: float = 0.0
|
|
i_l2og: float = 0.0
|
|
i_l3og : float = 0.0
|
|
p_wr : float = 0.0
|
|
crgMaxPct : float = 0.0
|
|
wr_status : str = ""
|
|
batt_status : str = ""
|
|
pwrMaxPct : float = 0.0
|
|
p_AC : float = 0.0
|
|
|
|
@dataclass
|
|
class estimation:
|
|
estProd = 0.1
|
|
increaseTmr = 0
|
|
|
|
try:
|
|
inv = client.SunSpecModbusClientDeviceTCP(1, "192.168.179.155", 1502)
|
|
meter0 = client.SunSpecModbusClientDeviceTCP(200, "192.168.179.155", 1502)
|
|
meter1 = client.SunSpecModbusClientDeviceTCP(201, "192.168.179.155", 1502)
|
|
regs = ModbusRegisters()
|
|
estimations = estimation()
|
|
except client.SunSpecModbusClientError as e:
|
|
_LOGGER.error('Modbus TCP Error: %s' % e)
|
|
_LOGGER.erorr('trace: %s' % traceback.print_exc())
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
async def connect():
|
|
if inv is not None and meter0 is not None and meter1 is not None:
|
|
print('Scanning: ')
|
|
# print( '\nTimestamp: %s' % (time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())))
|
|
|
|
# read all models in the device
|
|
inv.scan()
|
|
meter0.scan()
|
|
meter1.scan()
|
|
#_LOGGER.debug(inv.get_text())
|
|
if(inv.common[0].Md.value == "Symo GEN24 10.0"):
|
|
regs.ppv0_reg = "inv.mppt[0].module[0].DCW"
|
|
regs.ppv1_reg = "inv.mppt[0].module[1].DCW"
|
|
regs.pbat_crg_reg = "inv.mppt[0].module[2].DCW"
|
|
regs.pbat_discrg_reg = "inv.mppt[0].module[3].DCW"
|
|
regs.ubat_reg = "inv.mppt[0].module[3].DCV"
|
|
regs.ibat_crg_reg = "inv.mppt[0].module[2].DCA"
|
|
regs.ibat_discrg_reg = "inv.mppt[0].module[3].DCA"
|
|
regs.pACinv_reg = "inv.inverter_three_phase[0].W"
|
|
regs.tmpCab_reg = "inv.inverter_three_phase[0].TmpCab"
|
|
regs.soc_reg = "inv.storage_basic[0].ChaState"
|
|
regs.battStat_reg = "inv.storage_basic[0].ChaSt"
|
|
regs.wrStat_reg = "inv.inverter_three_phase[0].St"
|
|
|
|
regs.limitChrgRate = "inv.storage_basic[0].InWRte"
|
|
regs.setChargeLimits = "inv.storage_basic[0].StorCtl_Mod"
|
|
|
|
regs.setPowerLimitPercent = "inv.controls[0].WMaxLimPct"
|
|
regs.setPowerLimitEN = "inv.controls[0].WMaxLim_Ena"
|
|
|
|
regs.pACevu_reg = "meter0.ac_meter_abcn[0].W"
|
|
regs.pL1ACevu_reg = "meter0.ac_meter_abcn[0].WphA"
|
|
regs.pL2ACevu_reg = "meter0.ac_meter_abcn[0].WphB"
|
|
regs.pL3ACevu_reg = "meter0.ac_meter_abcn[0].WphC"
|
|
regs.iL1evu_reg = "meter0.ac_meter_abcn[0].AphA"
|
|
regs.iL2evu_reg = "meter0.ac_meter_abcn[0].AphB"
|
|
regs.iL3evu_reg = "meter0.ac_meter_abcn[0].AphC"
|
|
|
|
regs.pACog_reg = "meter1.ac_meter_abcn[0].W"
|
|
regs.pL1ACog_reg = "meter1.ac_meter_abcn[0].WphA"
|
|
regs.pL2ACog_reg = "meter1.ac_meter_abcn[0].WphB"
|
|
regs.pL3ACog_reg = "meter1.ac_meter_abcn[0].WphC"
|
|
regs.iL1og_reg = "meter1.ac_meter_abcn[0].AphA"
|
|
regs.iL2og_reg = "meter1.ac_meter_abcn[0].AphB"
|
|
regs.iL3og_reg = "meter1.ac_meter_abcn[0].AphC"
|
|
else:
|
|
_LOGGER.error('undefined Inverter, please define inverter registers!')
|
|
sys.exit(1)
|
|
else:
|
|
_LOGGER.error('One of the expected modbus devices was unreachable')
|
|
sys.exit(1)
|
|
#while True:
|
|
|
|
async def get_runtime_data(estProduction, sunset) -> InverterData:
|
|
ret = InverterData()
|
|
try:
|
|
inv.mppt[0].read()
|
|
inv.inverter_three_phase[0].read()
|
|
inv.storage_basic[0].read()
|
|
meter0.ac_meter_abcn[0].read()
|
|
meter1.ac_meter_abcn[0].read()
|
|
#print(inv.controls[0].__dir__())
|
|
ret.p_PV[0] = eval(regs.ppv0_reg).cvalue
|
|
ret.p_PV[1] = eval(regs.ppv1_reg).cvalue
|
|
ret.error = 0
|
|
ret.load = eval(regs.pACevu_reg).cvalue + eval(regs.pbat_discrg_reg).cvalue + eval(regs.ppv0_reg).cvalue + eval(regs.ppv1_reg).cvalue
|
|
ret.soc = eval(regs.soc_reg).cvalue
|
|
ret.pbat = eval(regs.pbat_discrg_reg).cvalue
|
|
if(ret.pbat == 0):
|
|
ret.pbat = -eval(regs.pbat_crg_reg).cvalue
|
|
ret.crgMaxPct = (eval(regs.limitChrgRate).cvalue)*2.04 #references max charge of batt. (20,48kw) instead of INV (10kw)
|
|
ret.pwrMaxPct = eval(regs.setPowerLimitPercent).cvalue #references max charge of batt. (20,48kw) instead of INV (10kw)
|
|
ret.ppv = ret.p_PV[0]
|
|
ret.ppv2 = ret.p_PV[1]
|
|
ret.pgrid = eval(regs.pACevu_reg).cvalue
|
|
if(ret.pgrid < 0):
|
|
ret.aut = 100
|
|
else:
|
|
ret.aut = 100/ret.load * ret.pgrid
|
|
if(ret.aut < 0):
|
|
ret.aut=0
|
|
elif(ret.aut > 100):
|
|
ret.aut = 100
|
|
ret.ibatt = eval(regs.ibat_discrg_reg).cvalue
|
|
if(ret.ibatt == 0):
|
|
ret.ibatt = -eval(regs.ibat_crg_reg).cvalue
|
|
ret.ubatt = eval(regs.ubat_reg).cvalue
|
|
ret.p_l1evu = eval(regs.pL1ACevu_reg).cvalue
|
|
ret.p_l2evu = eval(regs.pL2ACevu_reg).cvalue
|
|
ret.p_l3evu = eval(regs.pL3ACevu_reg).cvalue
|
|
ret.p_l1og = eval(regs.pL1ACog_reg).cvalue
|
|
ret.p_l2og = eval(regs.pL2ACog_reg).cvalue
|
|
ret.p_l3og = eval(regs.pL3ACog_reg).cvalue
|
|
ret.i_l1evu = eval(regs.iL1evu_reg).cvalue
|
|
ret.i_l2evu = eval(regs.iL2evu_reg).cvalue
|
|
ret.i_l3evu = eval(regs.iL3evu_reg).cvalue
|
|
ret.i_l1og = eval(regs.iL1og_reg).cvalue
|
|
ret.i_l2og = eval(regs.iL2og_reg).cvalue
|
|
ret.i_l3og = eval(regs.iL3og_reg).cvalue
|
|
ret.p_AC = eval(regs.pACinv_reg).cvalue
|
|
ret.p_wr = ret.ppv + ret.ppv2 + ret.pbat - ret.p_AC
|
|
ret.temp = 0#no need to read reg, reads always null ... eval(regs.tmpCab_reg).cvalue
|
|
ret.batt_status = batStat[eval(regs.battStat_reg).cvalue]
|
|
ret.wr_status = wrStat[eval(regs.wrStat_reg).cvalue]
|
|
except Exception as error:
|
|
_LOGGER.warning(f"No modbus data received from Inverter: %s",error)
|
|
#_LOGGER.erorr('trace: %s' % traceback.print_exc())
|
|
try:
|
|
inv.connect() #reconnect the modbus client
|
|
meter0.connect() #reconnect the modbus client
|
|
meter1.connect() #reconnect the modbus client
|
|
_LOGGER.warning(f"Tried to reconnect")
|
|
except:
|
|
_LOGGER.warning(f"reconnect failed...")
|
|
|
|
# if(ret.soc > 90 and (ret.i_l1evu > 22 or ret.i_l2evu > 22 or ret.i_l3evu > 22)):
|
|
# eval(regs.setPowerLimitPercent).value = ret.pwrMaxPct*100 - 500; #divide by two because this references 20.5kw max charge of battery instead of 10kw from INV
|
|
# eval(regs.setPowerLimitEN).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
# eval(regs.limitChrgRate).write()
|
|
# eval(regs.setChargeLimits).write()
|
|
# elif (ret.i_l1evu < 18 and ret.i_l2evu < 18 and ret.i_l3evu < 18 and ret.pwrMaxPct < 100):
|
|
# eval(regs.setPowerLimitPercent).value = ret.pwrMaxPct*100 + 500; #divide by two because this references 20.5kw max charge of battery instead of 10kw from INV
|
|
# eval(regs.setPowerLimitEN).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
# eval(regs.limitChrgRate).write()
|
|
# eval(regs.setChargeLimits).write()
|
|
# if datetime.datetime.now().hour == 23 and ret.pwrMaxPct < 99: #reset power limit every night
|
|
# eval(regs.setPowerLimitPercent).value = 10000; #divide by two because this references 20.5kw max charge of battery instead of 10kw from INV
|
|
# eval(regs.setPowerLimitEN).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
# eval(regs.limitChrgRate).write()
|
|
# eval(regs.setChargeLimits).write()
|
|
try:
|
|
if(estProduction != estimations.estProd and datetime.datetime.now().hour < 9):
|
|
estimations.estProd = estProduction
|
|
estimations.increaseTmr = 0
|
|
if(estimations.estProd > 35):
|
|
#_LOGGER.debug("High yeld predicted, reducing battery charge current")
|
|
if ret.soc > 45: #if SOC in the morning is above 45% wait with charging until midday
|
|
eval(regs.limitChrgRate).value = int(500/2.04) #divide by two because this references 20.5kw max charge of battery instead of 10kw from INV
|
|
else: #if less than 45% SOC in the morning charge slow (SOC dependant) until midday
|
|
eval(regs.limitChrgRate).value = int((5000 - ret.soc*100)/2.04) #divide by two because this references 20.5kw max charge of battery instead of 10kw from INV
|
|
eval(regs.setChargeLimits).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
eval(regs.limitChrgRate).write()
|
|
eval(regs.setChargeLimits).write()
|
|
elif ret.crgMaxPct < 70:
|
|
eval(regs.limitChrgRate).value = int(8000/2.04) #set charge rate to 80% if no high yeld is predicted
|
|
eval(regs.setChargeLimits).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
eval(regs.limitChrgRate).write()
|
|
eval(regs.setChargeLimits).write()
|
|
elif datetime.datetime.now().hour == 11 or datetime.datetime.now().hour == 12: #inclease charge rate at midday
|
|
estimations.increaseTmr = estimations.increaseTmr + 1
|
|
if estimations.increaseTmr > 300: #slowdown rate change to 300 * 3sec (15 min.)
|
|
estimations.increaseTmr = 0
|
|
maxMiddDayChrg = 30
|
|
if(int(sunset.strftime('%H')) < 18): #inclrease max charge rate during wintertime, where time to full SOC is less.
|
|
maxMiddDayChrg = 70
|
|
if ret.crgMaxPct < maxMiddDayChrg:
|
|
estimations.increaseTmr = 0
|
|
eval(regs.limitChrgRate).value = int((ret.crgMaxPct*100+500)/2.04) #increase by 5% every 15 min --> reach 30% after 5*15min max
|
|
eval(regs.setChargeLimits).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
eval(regs.limitChrgRate).write()
|
|
eval(regs.setChargeLimits).write()
|
|
_LOGGER.debug("Increasing charge rate to buffer feed peaks to " + str(int((ret.crgMaxPct*100+200)/2.04)) + "%")
|
|
if datetime.datetime.now().hour >= int(sunset.strftime('%H'))-4 and ret.soc < 70 and ret.crgMaxPct < 90:
|
|
eval(regs.limitChrgRate).value = int((10000)/2.04)
|
|
eval(regs.setChargeLimits).value = 1 #set charge rate: bit1 set discharge rate: bit 2
|
|
eval(regs.limitChrgRate).write()
|
|
eval(regs.setChargeLimits).write()
|
|
_LOGGER.debug("Increasing charge rate because of too low SOC " + str(int((10000)/2.04)) + "%")
|
|
return ret
|
|
#print(ret.p_wr)
|
|
#print("-----")
|
|
#sleep(1)
|
|
except Exception as error:
|
|
_LOGGER.warning(f"No modbus data received from Inverter: %s",error)
|
|
|
|
"""
|
|
Model: common (1)
|
|
|
|
ID 1
|
|
L 65
|
|
Mn Fronius
|
|
Md Symo GEN24 10.0
|
|
Opt None
|
|
Vr 1.34.2-1
|
|
SN 33095286
|
|
DA 1
|
|
|
|
Model: inverter_three_phase (103)
|
|
|
|
ID 103
|
|
L 50
|
|
A 22300 A
|
|
AphA 8115 A
|
|
AphB 7527 A
|
|
AphC 6658 A
|
|
A_SF -5
|
|
PPVphAB 4000 V
|
|
PPVphBC 4015 V
|
|
PPVphCA 4033 V
|
|
PhVphA 2310 V
|
|
PhVphB 2317 V
|
|
PhVphC 2328 V
|
|
V_SF -1
|
|
W -5145 W
|
|
W_SF -2
|
|
Hz 4998 Hz
|
|
Hz_SF -2
|
|
VA 5145 VA
|
|
VA_SF -2
|
|
VAr 31275 var
|
|
VAr_SF -5
|
|
PF 1000 Pct
|
|
PF_SF -1
|
|
WH 3939319098 Wh
|
|
WH_SF -2
|
|
DCA None A
|
|
DCA_SF None
|
|
DCV None V
|
|
DCV_SF None
|
|
DCW 25076 W
|
|
DCW_SF -5
|
|
TmpCab 526 C
|
|
TmpSnk None C
|
|
TmpTrns None C
|
|
TmpOt None C
|
|
Tmp_SF -1
|
|
St 4
|
|
StVnd 4
|
|
Evt1 0
|
|
Evt2 0
|
|
EvtVnd1 0
|
|
EvtVnd2 0
|
|
EvtVnd3 None
|
|
EvtVnd4 None
|
|
|
|
Model: nameplate (120)
|
|
|
|
ID 120
|
|
L 26
|
|
DERTyp 82
|
|
WRtg 1000 W
|
|
WRtg_SF 1
|
|
VARtg 1000 VA
|
|
VARtg_SF 1
|
|
VArRtgQ1 714 var
|
|
VArRtgQ2 714 var
|
|
VArRtgQ3 -714 var
|
|
VArRtgQ4 -714 var
|
|
VArRtg_SF 1
|
|
ARtg 1443 A
|
|
ARtg_SF -2
|
|
PFRtgQ1 -700 cos()
|
|
PFRtgQ2 700 cos()
|
|
PFRtgQ3 -700 cos()
|
|
PFRtgQ4 700 cos()
|
|
PFRtg_SF -3
|
|
WHRtg 22118 Wh
|
|
WHRtg_SF 0
|
|
AhrRtg None AH
|
|
AhrRtg_SF None
|
|
MaxChaRte 20480 W
|
|
MaxChaRte_SF 0
|
|
MaxDisChaRte 20480 W
|
|
MaxDisChaRte_SF 0
|
|
Pad 32768
|
|
|
|
Model: settings (121)
|
|
|
|
ID 121
|
|
L 30
|
|
WMax 1000 W
|
|
VRef 231 V
|
|
VRefOfs 0 V
|
|
VMax None V
|
|
VMin None V
|
|
VAMax 1000 VA
|
|
VArMaxQ1 714 var
|
|
VArMaxQ2 714 var
|
|
VArMaxQ3 -714 var
|
|
VArMaxQ4 -714 var
|
|
WGra None % WMax/sec
|
|
PFMinQ1 -700 cos()
|
|
PFMinQ2 700 cos()
|
|
PFMinQ3 -700 cos()
|
|
PFMinQ4 700 cos()
|
|
VArAct None
|
|
ClcTotVA None
|
|
MaxRmpRte None % WGra
|
|
ECPNomHz None Hz
|
|
ConnPh None
|
|
WMax_SF 1
|
|
VRef_SF 0
|
|
VRefOfs_SF 0
|
|
VMinMax_SF None
|
|
VAMax_SF 1
|
|
VArMax_SF 1
|
|
WGra_SF None
|
|
PFMin_SF -3
|
|
MaxRmpRte_SF None
|
|
ECPNomHz_SF None
|
|
|
|
Model: status (122)
|
|
|
|
ID 122
|
|
L 44
|
|
PVConn 7
|
|
StorConn 7
|
|
ECPConn 1
|
|
ActWh 39393190 Wh
|
|
ActVAh None VAh
|
|
ActVArhQ1 None varh
|
|
ActVArhQ2 None varh
|
|
ActVArhQ3 None varh
|
|
ActVArhQ4 None varh
|
|
VArAval None var
|
|
VArAval_SF None
|
|
WAval None var
|
|
WAval_SF None
|
|
StSetLimMsk None
|
|
StActCtl 0
|
|
TmSrc RTC
|
|
Tms 791196551 Secs
|
|
RtSt None
|
|
Ris None ohms
|
|
Ris_SF None
|
|
|
|
Model: controls (123)
|
|
|
|
ID 123
|
|
L 24
|
|
Conn_WinTms 0 Secs
|
|
Conn_RvrtTms 0 Secs
|
|
Conn 1
|
|
WMaxLimPct 10000 % WMax
|
|
WMaxLimPct_WinTms 0 Secs
|
|
WMaxLimPct_RvrtTms 0 Secs
|
|
WMaxLimPct_RmpTms 0 Secs
|
|
WMaxLim_Ena 0
|
|
OutPFSet 1000 cos()
|
|
OutPFSet_WinTms 0 Secs
|
|
OutPFSet_RvrtTms 0 Secs
|
|
OutPFSet_RmpTms 0 Secs
|
|
OutPFSet_Ena 0
|
|
VArWMaxPct None % WMax
|
|
VArMaxPct 100 % VArMax
|
|
VArAvalPct None % VArAval
|
|
VArPct_WinTms 0 Secs
|
|
VArPct_RvrtTms 0 Secs
|
|
VArPct_RmpTms 0 Secs
|
|
VArPct_Mod 2
|
|
VArPct_Ena 0
|
|
WMaxLimPct_SF -2
|
|
OutPFSet_SF -3
|
|
VArPct_SF 0
|
|
|
|
Model: mppt (160)
|
|
|
|
ID 160
|
|
L 88
|
|
DCA_SF -4
|
|
DCV_SF -2
|
|
DCW_SF -1
|
|
DCWH_SF -2
|
|
Evt None
|
|
N 4
|
|
TmsPer None
|
|
01:ID 1
|
|
01:IDStr MPPT 1
|
|
01:DCA 22696 A
|
|
01:DCV 55400 V
|
|
01:DCW 12574 W
|
|
01:DCWH 3156686802 Wh
|
|
01:Tms 791196551 Secs
|
|
01:Tmp None C
|
|
01:DCSt None
|
|
01:DCEvt None
|
|
02:ID 2
|
|
02:IDStr MPPT 2
|
|
02:DCA 15510 A
|
|
02:DCV 32689 V
|
|
02:DCW 5070 W
|
|
02:DCWH 989224180 Wh
|
|
02:Tms 791196551 Secs
|
|
02:Tmp None C
|
|
02:DCSt None
|
|
02:DCEvt None
|
|
03:ID 3
|
|
03:IDStr StCha 3
|
|
03:DCA 42263 A
|
|
03:DCV 41721 V
|
|
03:DCW 17641 W
|
|
03:DCWH 877835025 Wh
|
|
03:Tms 791196551 Secs
|
|
03:Tmp None C
|
|
03:DCSt None
|
|
03:DCEvt None
|
|
04:ID 4
|
|
04:IDStr StDisCha 4
|
|
04:DCA 0 A
|
|
04:DCV 41721 V
|
|
04:DCW 0 W
|
|
04:DCWH 824803735 Wh
|
|
04:Tms 791196551 Secs
|
|
04:Tmp None C
|
|
04:DCSt None
|
|
04:DCEvt None
|
|
|
|
Model: storage_basic (124)
|
|
|
|
ID 124
|
|
L 24
|
|
WChaMax 20480 W
|
|
WChaGra 100 % WChaMax/sec
|
|
WDisChaGra 100 % WChaMax/sec
|
|
StorCtl_Mod 0
|
|
VAChaMax None VA
|
|
MinRsvPct 0 % WChaMax
|
|
ChaState 1240 % AhrRtg
|
|
StorAval None AH
|
|
InBatV None V
|
|
ChaSt 4
|
|
OutWRte 10000 % WDisChaMax
|
|
InWRte 10000 % WChaMax
|
|
InOutWRte_WinTms None Secs
|
|
InOutWRte_RvrtTms 0 Secs
|
|
InOutWRte_RmpTms None Secs
|
|
ChaGriSet 1
|
|
WChaMax_SF 0
|
|
WChaDisChaGra_SF 0
|
|
VAChaMax_SF None
|
|
MinRsvPct_SF -2
|
|
ChaState_SF -2
|
|
StorAval_SF None
|
|
InBatV_SF None
|
|
InOutWRte_SF -2
|
|
""" |