Kostal Plenticore Bilanz

Begonnen von ch.eick, 05 April 2020, 10:36:25

Vorheriges Thema - Nächstes Thema

ch.eick

Moin zusammen,

EDIT:
2020.08.27 - Es wurde nun eine Wiki Seite begonnen Kostal Plenticore 10 Plus
2020.08.27 - kleinere Bereinigungen in der Beschreibung aufgrund von Foren Rückmeldungen
2020.08.27 - Der JSON String für die Statistiken von der API scheint varianten zu haben. Das userreading für statistics_clean wurde angepasst
2020.08.25 - Ersetzen des WR Namens im userreading durch ".*" , um mehr Flexibilität zu erhalten, wenn der Plenticore mal umbenannt wird
2020.08.21 - Alle Devices wurden aktualisiert und die Statistik mit Python hinzugefügt
2020.07.06 - Die momentane SelfConsumptionQuote wurde falsch berechnet
2020.07.01 - In der Bilanz hat mich etwas gestört, aber jetzt passt es besser
2020.06.15 - DOIF Ausschnitte für die Bilanz, die Plenticore Statistik und die EVU Datenübertragung ergänzt
2020.06.15 - Bilanz aktualisiert
2020.06.15 - RAW definition aktualisiert von PV_Anlage_1

ich habe mal versucht die Bilanzierung, von den SMA Mitstreitern aus der Wiki, auf einen Kostal Plenticore zu adaptieren.
Der Plenticore liefert über seine eigenen Statistiken bereits die meisten Werte von hause aus, sodass man diese nicht mehr selber errechnen muss. Somit werden im Vergleich zum SMA Original
keinerlei Funktionen zyklisch aufgerufen. Um die Werte zu aktualisieren rufe ich dieses Dummy im gewünschten Zeitraum mit "set Dum.Energy update" auf. Hierbei ist "update" ein frei gewählter
String, der keinerlei Bedeutung hat. Der "set" Aufruf führt nur die userreadings aus.

Hierbei sind die Devices wie folgt zugeordnet:
- StromZaehler ist der Zähler vom Versorger, ein Wert kleiner 0 bedeutet einspeisen, Da der Zweirichtungszähler leider noch auf sich warten lässt :-(
- Die aktuellen Werte des KSEM werden jetzt über den Plenticore ausgelesen. Ein Lesekopf auf dem EVU Zaehler ist nicht mehr notwendig
- PV_Anlage_1 ist der Plenticore WR
- PV_Anlage_1:Statistic_* sind die ausgelesenen Statistikwerte

Viele Grüsse
     Christian


defmod Dum.Energy dummy
attr Dum.Energy DbLogExclude .*
attr Dum.Energy DbLogInclude Autarky.*,GridFeed.*,PV.*,.*Consumption.*
attr Dum.Energy alias Energiebilanz
attr Dum.Energy comment TotalConsumption,AutarkyQuoteDay,SelfConsumptionQuoteDay,AutarkyQuoteMonth,SelfConsumptionQuoteMonth
attr Dum.Energy event-on-change-reading PV,GridConsumption,GridFeedIn,SelfConsumptionQuote,Autarky.*,GridFeed.*,PV.*,.*Consumption.*
attr Dum.Energy event-on-update-reading TotalConsumption,AutarkyQuoteDay,SelfConsumptionQuoteDay,AutarkyQuoteMonth,SelfConsumptionQuoteMonth
attr Dum.Energy group Energiebilanz
attr Dum.Energy icon measure_power_meter
attr Dum.Energy room Strom->Energie
attr Dum.Energy stateFormat {\
my $pvt   = ReadingsVal("$name","PVTotal", "")." W";;\
my $pvtd  = ReadingsVal("$name","PVTotalDay", "")." kWh";;\
my $pvtm  = ReadingsVal("$name","PVTotalMonth", "")." kWh";;\
my $pvty  = ReadingsVal("$name","PVTotalYear", "")." kWh";;\
\
my $pv  = ReadingsVal("$name","PV", "")." W";;\
my $pvd  = ReadingsVal("$name","PVDay", "")." kWh";;\
my $pvm  = ReadingsVal("$name","PVMonth", "")." kWh";;\
my $pvy  = ReadingsVal("$name","PVYear", "")." kWh";;\
\
my $gfi  = ReadingsVal("$name","GridFeedIn", "")." W";;\
my $gfid = ReadingsVal("$name","GridFeedInDay", "")." kWh";;\
my $gfim = ReadingsVal("$name","GridFeedInMonth", "")." kWh";;\
my $gfiy = ReadingsVal("$name","GridFeedInYear", "")." kWh";;\
my $eb   = ReadingsVal("$name","GridConsumption", "")." W";;\
my $ebd  = ReadingsVal("$name","GridConsumptionDay", "")." kWh";;\
my $ebm  = ReadingsVal("$name","GridConsumptionMonth", "")." kWh";;\
my $eby  = ReadingsVal("$name","GridConsumptionYear", "")." kWh";;\
my $et   = ReadingsVal("$name","TotalConsumption", "")." W";;\
my $etd  = ReadingsVal("$name","TotalConsumptionDay", "")." kWh";;\
my $etm  = ReadingsVal("$name","TotalConsumptionMonth", "")." kWh";;\
my $ety  = ReadingsVal("$name","TotalConsumptionYear", "")." kWh";;\
my $aq   = ReadingsVal("$name","AutarkyQuote", "")." %";;\
my $aqd  = ReadingsVal("$name","AutarkyQuoteDay", "")." %";;\
my $aqm  = ReadingsVal("$name","AutarkyQuoteMonth", "")." %";;\
my $aqy  = ReadingsVal("$name","AutarkyQuoteYear", "")." %";;\
my $sq   = ReadingsVal("$name","SelfConsumptionQuote", "")." %";;\
my $sqd  = ReadingsVal("$name","SelfConsumptionQuoteDay", "")." %";;\
my $sqm  = ReadingsVal("$name","SelfConsumptionQuoteMonth", "")." %";;\
my $sqy  = ReadingsVal("$name","SelfConsumptionQuoteYear", "")." %";;\
my $md   = ReadingsTimestamp("$name", "AutarkyQuote", "");;\
my $cd   = ReadingsTimestamp("PV_Anlage_1", "Statistic_Autarky_Day", "");;\
my $cm   = ReadingsTimestamp("PV_Anlage_1", "Statistic_Autarky_Month", "");;\
my $cy   = ReadingsTimestamp("PV_Anlage_1", "Statistic_Autarky_Year", "");;\
"<html><table border=2 bordercolor='darkgreen' cellspacing=0>\
<tr><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'> </td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>aktueller Wert</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>Heute</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>dieser Monat</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>dieses Jahr</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Erzeugung-Total</td><td style='padding-right:5px;;padding-left:5px'>".$pvt."</td><td style='padding-right:5px;;padding-left:5px'>".$pvtd."</td><td style='padding-right:5px;;padding-left:5px'>".$pvtm."</td><td style='padding-right:5px;;padding-left:5px'>".$pvty."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Einspeisung</td><td style='padding-right:5px;;padding-left:5px'>".$gfi."</td><td style='padding-right:5px;;padding-left:5px'>".$gfid."</td><td style='padding-right:5px;;padding-left:5px'>".$gfim."</td><td style='padding-right:5px;;padding-left:5px'>".$gfiy."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Netz-Bezug</td><td style='padding-right:5px;;padding-left:5px'>".$eb."</td><td style='padding-right:5px;;padding-left:5px'>".$ebd."</td><td style='padding-right:5px;;padding-left:5px'>".$ebm."</td><td style='padding-right:5px;;padding-left:5px'>".$eby."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Bezug</td><td style='padding-right:5px;;padding-left:5px'>".$pv."</td><td style='padding-right:5px;;padding-left:5px'>".$pvd."</td><td style='padding-right:5px;;padding-left:5px'>".$pvm."</td><td style='padding-right:5px;;padding-left:5px'>".$pvy."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Energieverbrauch</td><td style='padding-right:5px;;padding-left:5px'>".$et."</td><td style='padding-right:5px;;padding-left:5px'>".$etd."</td><td style='padding-right:5px;;padding-left:5px'>".$etm."</td><td style='padding-right:5px;;padding-left:5px'>".$ety."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Autarkiequote</td><td style='padding-right:5px;;padding-left:5px'>".$aq."</td><td style='padding-right:5px;;padding-left:5px'>".$aqd."</td><td style='padding-right:5px;;padding-left:5px'>".$aqm."</td><td style='padding-right:5px;;padding-left:5px'>".$aqy."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Eigenverbrauchsquote</td><td style='padding-right:5px;;padding-left:5px'>".$sq."</td><td style='padding-right:5px;;padding-left:5px'>".$sqd."</td><td style='padding-right:5px;;padding-left:5px'>".$sqm."</td><td style='padding-right:5px;;padding-left:5px'>".$sqy."</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Berechnung am</td><td style='padding-right:5px;;padding-left:5px'>".$md."</td><td style='padding-right:5px;;padding-left:5px'>".$cd."</td><td style='padding-right:5px;;padding-left:5px'>".$cm."</td><td style='padding-right:5px;;padding-left:5px'>".$cy."</td></tr>\
</table></html>"\
}
attr Dum.Energy userReadings PVTotal {round(ReadingsVal("PV_Anlage_1","Total_AC_active_power",""),0)},\
PVTotalDay {round( ReadingsVal("PV_Anlage_1","Statistic_Yield_Day", "")/1000 ,2)},\
PVTotalMonth {round( ReadingsVal("PV_Anlage_1","Statistic_Yield_Month", "")/1000 ,2)},\
PVTotalYear {round( ReadingsVal("PV_Anlage_1","Statistic_Yield_Year", "")/1000 ,2)},\
\
PV {round( ReadingsVal("PV_Anlage_1","Home_own_consumption_from_battery", "")+ReadingsVal("PV_Anlage_1","Home_own_consumption_from_PV", "") ,0)},\
PVDay {round( (ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Day", "")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Day", ""))/1000 ,2)},\
PVMonth {round( (ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Month", "")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Month", ""))/1000 ,2)},\
PVYear {round( (ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Year", "")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Year", ""))/1000 ,2)},\
\
GridFeedIn { ReadingsVal("PV_Anlage_1","Total_active_power_(powermeter)",0)<=0 ? abs(round(ReadingsVal("PV_Anlage_1","Total_active_power_(powermeter)",0),0)) : 0  },\
GridFeedInDay {round((ReadingsVal("PV_Anlage_1","Statistic_Yield_Day", "")-ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Day", "")-ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Day", ""))/1000,2)},\
GridFeedInMonth {round((ReadingsVal("PV_Anlage_1","Statistic_Yield_Month", "")-ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Month", "")-ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Month", ""))/1000,2)},\
GridFeedInYear {round((ReadingsVal("PV_Anlage_1","Statistic_Yield_Year", "")-ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Year", "")-ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Year", ""))/1000,2)},\
\
GridConsumption { ReadingsVal("PV_Anlage_1","Total_active_power_(powermeter)",0)>=0 ? round(ReadingsVal("PV_Anlage_1","Total_active_power_(powermeter)",0),0) : 0  },\
GridConsumptionDay {round(abs(ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeGrid_Day",""))/1000 ,2)},\
GridConsumptionMonth {round(ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeGrid_Month","")/1000 ,2)},\
GridConsumptionYear {round(ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeGrid_Year","")/1000 ,2)},\
\
TotalConsumption {round((ReadingsVal("PV_Anlage_1","Home_own_consumption_from_PV","")+ReadingsVal("PV_Anlage_1","Home_own_consumption_from_battery","")+ReadingsVal("PV_Anlage_1","Home_own_consumption_from_grid","")),0)},\
\
TotalConsumptionDay {round( (ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Day","")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Day","")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeGrid_Day","") )/1000 ,2)},\
TotalConsumptionMonth {round( (ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Month","")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Month","")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeGrid_Month","") )/1000 ,2)},\
TotalConsumptionYear {round( (ReadingsVal("PV_Anlage_1","Statistic_EnergyHomePv_Year","")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeBat_Year","")+ReadingsVal("PV_Anlage_1","Statistic_EnergyHomeGrid_Year","") )/1000,2)},\
\
AutarkyQuote {my $valA = (ReadingsVal("PV_Anlage_1", "Total_AC_active_power","")*1000)-ReadingsVal("PV_Anlage_1", "Home_own_consumption_from_grid","");;;;\
my $calcVal = round($valA / ($valA + ReadingsVal("PV_Anlage_1", "Home_own_consumption_from_grid",""))*100 ,0)},\
\
AutarkyQuoteDay {round(ReadingsVal("PV_Anlage_1","Statistic_Autarky_Day", ""),0)},\
AutarkyQuoteMonth {round(ReadingsVal("PV_Anlage_1","Statistic_Autarky_Month", ""),0)},\
AutarkyQuoteYear {round(ReadingsVal("PV_Anlage_1","Statistic_Autarky_Year", ""),0)},\
\
SelfConsumptionQuote {my $x = round((ReadingsVal("PV_Anlage_1","Home_own_consumption_from_PV", "") + ReadingsVal("PV_Anlage_1","Home_own_consumption_from_battery","")) / ReadingsVal("PV_Anlage_1","Total_AC_active_power", "") * 100 ,0) ;;;; $x > 100 ?  $x = 100:$x = $x ;;;; $x },\
SelfConsumptionQuoteDay {round(ReadingsVal("PV_Anlage_1","Statistic_OwnConsumptionRate_Day", ""),0)},\
SelfConsumptionQuoteMonth {round(ReadingsVal("PV_Anlage_1","Statistic_OwnConsumptionRate_Month", ""),0)},\
SelfConsumptionQuoteYear {round(ReadingsVal("PV_Anlage_1","Statistic_OwnConsumptionRate_Year", ""),0)}

setstate Dum.Energy <html><table border=2 bordercolor='darkgreen' cellspacing=0>\
<tr><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'> </td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>aktueller Wert</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>Heute</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>dieser Monat</td><td style='padding-right:5px;;padding-left:5px;;font-weight:bold'>dieses Jahr</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Erzeugung-Total</td><td style='padding-right:5px;;padding-left:5px'>619 W</td><td style='padding-right:5px;;padding-left:5px'>23.22 kWh</td><td style='padding-right:5px;;padding-left:5px'>841.89 kWh</td><td style='padding-right:5px;;padding-left:5px'>7921.09 kWh</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Einspeisung</td><td style='padding-right:5px;;padding-left:5px'>28 W</td><td style='padding-right:5px;;padding-left:5px'>16.19 kWh</td><td style='padding-right:5px;;padding-left:5px'>535.02 kWh</td><td style='padding-right:5px;;padding-left:5px'>4476.75 kWh</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Netz-Bezug</td><td style='padding-right:5px;;padding-left:5px'>0 W</td><td style='padding-right:5px;;padding-left:5px'>0.02 kWh</td><td style='padding-right:5px;;padding-left:5px'>0.79 kWh</td><td style='padding-right:5px;;padding-left:5px'>1025.50 kWh</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>PV-Bezug</td><td style='padding-right:5px;;padding-left:5px'>536 W</td><td style='padding-right:5px;;padding-left:5px'>7.03 kWh</td><td style='padding-right:5px;;padding-left:5px'>306.87 kWh</td><td style='padding-right:5px;;padding-left:5px'>3444.34 kWh</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Energieverbrauch</td><td style='padding-right:5px;;padding-left:5px'>536 W</td><td style='padding-right:5px;;padding-left:5px'>7.05 kWh</td><td style='padding-right:5px;;padding-left:5px'>307.65 kWh</td><td style='padding-right:5px;;padding-left:5px'>4469.84 kWh</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Autarkiequote</td><td style='padding-right:5px;;padding-left:5px'>100 %</td><td style='padding-right:5px;;padding-left:5px'>100 %</td><td style='padding-right:5px;;padding-left:5px'>100 %</td><td style='padding-right:5px;;padding-left:5px'>77 %</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Eigenverbrauchsquote</td><td style='padding-right:5px;;padding-left:5px'>87 %</td><td style='padding-right:5px;;padding-left:5px'>30 %</td><td style='padding-right:5px;;padding-left:5px'>36 %</td><td style='padding-right:5px;;padding-left:5px'>43 %</td></tr>\
<tr><td style='padding-right:5px;;padding-left:5px;;text-align:left;;font-weight:bold'>Berechnung am</td><td style='padding-right:5px;;padding-left:5px'>2020-08-21 14:30:00</td><td style='padding-right:5px;;padding-left:5px'>2020-08-21 13:57:01</td><td style='padding-right:5px;;padding-left:5px'>2020-08-21 13:57:01</td><td style='padding-right:5px;;padding-left:5px'>2020-08-21 13:57:01</td></tr>\
</table></html>


Hier noch das Listing von PV_Anlage_1, etwas bereinigt

defmod PV_Anlage_1 ModbusAttr 71 60 192.168.178.18:1502 TCP

attr PV_Anlage_1 alias PV_Einspeisung
attr PV_Anlage_1 comment Kostal Plenticore 10 Plus mit BYD Speicher
attr PV_Anlage_1 dev-h-defFormat %.2f
attr PV_Anlage_1 dev-h-defLen 2
attr PV_Anlage_1 dev-h-defPoll 1
attr PV_Anlage_1 dev-h-defRevRegs 1
attr PV_Anlage_1 dev-h-defUnpack f>
attr PV_Anlage_1 dev-type-STR-format %s
attr PV_Anlage_1 dev-type-STR-len 8
attr PV_Anlage_1 dev-type-STR-revRegs 0
attr PV_Anlage_1 dev-type-STR-unpack a*
attr PV_Anlage_1 event-on-change-reading statistics_.*,Statistic_.*,Act_state_of_charge,Actual_battery_charge_.*,Battery_temperature,Home_own_consumption_from_.*,Inverter_state,Power_DC1,Power_DC2,Power_DC_Sum,Total_DC_Power,Total_DC_Power_Max,Total_PV_Power_reserve,Voltage_DC1,Voltage_DC2,.*_yield,Solar_.*
attr PV_Anlage_1 group PV Eigenverbrauch
attr PV_Anlage_1 icon sani_solar
attr PV_Anlage_1 obj-h100-reading Total_DC_Power
attr PV_Anlage_1 obj-h104-format %s
attr PV_Anlage_1 obj-h104-reading State_of_energy_manager
attr PV_Anlage_1 obj-h104-revRegs 0
attr PV_Anlage_1 obj-h104-unpack N
attr PV_Anlage_1 obj-h106-reading Home_own_consumption_from_battery
attr PV_Anlage_1 obj-h108-reading Home_own_consumption_from_grid
attr PV_Anlage_1 obj-h110-reading Total_home_consumption_Battery
attr PV_Anlage_1 obj-h112-reading Total_home_consumption_Grid
attr PV_Anlage_1 obj-h114-reading Total_home_consumption_PV
attr PV_Anlage_1 obj-h116-reading Home_own_consumption_from_PV
attr PV_Anlage_1 obj-h118-reading Total_home_consumption
attr PV_Anlage_1 obj-h120-reading Isolation_resistance
attr PV_Anlage_1 obj-h122-reading Power_limit_from_EVU
attr PV_Anlage_1 obj-h124-reading Total_home_consumption_rate
attr PV_Anlage_1 obj-h14-reading Inverter_serial_number
attr PV_Anlage_1 obj-h14-type STR
attr PV_Anlage_1 obj-h144-reading Worktime
attr PV_Anlage_1 obj-h150-reading Actual_cos_phi
attr PV_Anlage_1 obj-h152-reading Grid_frequency
attr PV_Anlage_1 obj-h154-reading Current_Phase_1
attr PV_Anlage_1 obj-h156-reading Active_power_Phase_1
attr PV_Anlage_1 obj-h158-reading Voltage_Phase_1
attr PV_Anlage_1 obj-h160-reading Current_Phase_2
attr PV_Anlage_1 obj-h162-reading Active_power_Phase_2
attr PV_Anlage_1 obj-h164-reading Voltage_Phase_2
attr PV_Anlage_1 obj-h166-reading Current_Phase_3
attr PV_Anlage_1 obj-h168-reading Active_power_Phase_3
attr PV_Anlage_1 obj-h170-reading Voltage_Phase_3
attr PV_Anlage_1 obj-h172-reading Total_AC_active_power
attr PV_Anlage_1 obj-h174-reading Total_AC_reactive_power
attr PV_Anlage_1 obj-h178-reading Total_AC_apparent_power
attr PV_Anlage_1 obj-h190-reading Battery_charge_current
attr PV_Anlage_1 obj-h194-format %.0f
attr PV_Anlage_1 obj-h194-reading Number_of_battery_cycles
attr PV_Anlage_1 obj-h200-reading Actual_battery_charge_-minus_or_discharge_-plus_current
attr PV_Anlage_1 obj-h202-reading PSSB_fuse_state
attr PV_Anlage_1 obj-h208-format %.0f
attr PV_Anlage_1 obj-h208-reading Battery_ready_flag
attr PV_Anlage_1 obj-h210-reading Act_state_of_charge
attr PV_Anlage_1 obj-h212-reading Battery_state
attr PV_Anlage_1 obj-h214-reading Battery_temperature
attr PV_Anlage_1 obj-h216-reading Battery_voltage
attr PV_Anlage_1 obj-h218-reading Cos_phi_(powermeter)
attr PV_Anlage_1 obj-h220-reading Frequency_(powermeter)
attr PV_Anlage_1 obj-h222-reading Current_phase_1_(powermeter)
attr PV_Anlage_1 obj-h224-reading Active_power_phase_1_(powermeter)
attr PV_Anlage_1 obj-h226-reading Reactive_power_phase_1_(powermeter)
attr PV_Anlage_1 obj-h228-reading Apparent_power_phase_1_(powermeter)
attr PV_Anlage_1 obj-h230-reading Voltage_phase_1_(powermeter)
attr PV_Anlage_1 obj-h232-reading Current_phase_2_(powermeter)
attr PV_Anlage_1 obj-h234-reading Active_power_phase_2_(powermeter)
attr PV_Anlage_1 obj-h236-reading Reactive_power_phase_2_(powermeter)
attr PV_Anlage_1 obj-h238-reading Apparent_power_phase_2_(powermeter)
attr PV_Anlage_1 obj-h240-reading Voltage_phase_2_(powermeter)
attr PV_Anlage_1 obj-h242-reading Current_phase_3_(powermeter)
attr PV_Anlage_1 obj-h244-reading Active_power_phase_3_(powermeter)
attr PV_Anlage_1 obj-h246-reading Reactive_power_phase_3_(powermeter)
attr PV_Anlage_1 obj-h248-reading Apparent_power_phase_3_(powermeter)
attr PV_Anlage_1 obj-h250-reading Voltage_phase_3_(powermeter)
attr PV_Anlage_1 obj-h252-reading Total_active_power_(powermeter)
attr PV_Anlage_1 obj-h254-reading Total_reactive_power_(powermeter)
attr PV_Anlage_1 obj-h256-reading Total_apparent_power_(powermeter)
attr PV_Anlage_1 obj-h258-reading Current_DC1
attr PV_Anlage_1 obj-h260-reading Power_DC1
attr PV_Anlage_1 obj-h266-reading Voltage_DC1
attr PV_Anlage_1 obj-h268-reading Current_DC2
attr PV_Anlage_1 obj-h270-reading Power_DC2
attr PV_Anlage_1 obj-h276-reading Voltage_DC2
attr PV_Anlage_1 obj-h278-reading Current_DC3
attr PV_Anlage_1 obj-h280-reading Power_DC3
attr PV_Anlage_1 obj-h286-reading Voltage_DC3
attr PV_Anlage_1 obj-h320-reading Total_yield
attr PV_Anlage_1 obj-h322-reading Daily_yield
attr PV_Anlage_1 obj-h324-reading Yearly_yield
attr PV_Anlage_1 obj-h326-reading Monthly_yield
attr PV_Anlage_1 obj-h38-reading Software-Version_Maincontroller_(MC)
attr PV_Anlage_1 obj-h38-type STR
attr PV_Anlage_1 obj-h384-len 16
attr PV_Anlage_1 obj-h384-reading Inverter_network_name
attr PV_Anlage_1 obj-h384-type STR
attr PV_Anlage_1 obj-h420-reading IP-address
attr PV_Anlage_1 obj-h420-type STR
attr PV_Anlage_1 obj-h428-reading IP-subnetmask
attr PV_Anlage_1 obj-h428-type STR
attr PV_Anlage_1 obj-h436-reading IP-gateway
attr PV_Anlage_1 obj-h436-type STR
attr PV_Anlage_1 obj-h446-reading IP-DNS1
attr PV_Anlage_1 obj-h446-type STR
attr PV_Anlage_1 obj-h454-reading IP-DNS2
attr PV_Anlage_1 obj-h454-type STR
attr PV_Anlage_1 obj-h46-reading Software-Version_IO-Controller_(IOC)
attr PV_Anlage_1 obj-h46-type STR
attr PV_Anlage_1 obj-h514-len 1
attr PV_Anlage_1 obj-h514-reading Battery_actual_SOC
attr PV_Anlage_1 obj-h517-reading Battery_Manufacturer
attr PV_Anlage_1 obj-h517-type STR
attr PV_Anlage_1 obj-h525-format %c
attr PV_Anlage_1 obj-h525-reading Battery_Model_ID
attr PV_Anlage_1 obj-h525-unpack N
attr PV_Anlage_1 obj-h527-format %c
attr PV_Anlage_1 obj-h527-reading Battery_Serial_Number
attr PV_Anlage_1 obj-h529-len 4
attr PV_Anlage_1 obj-h529-reading Work_Capacity
attr PV_Anlage_1 obj-h529-unpack N
attr PV_Anlage_1 obj-h531-format %.0f
attr PV_Anlage_1 obj-h531-reading Inverter_Max_Power
attr PV_Anlage_1 obj-h531-unpack N
attr PV_Anlage_1 obj-h535-revRegs 0
attr PV_Anlage_1 obj-h535-unpack n
attr PV_Anlage_1 obj-h551-revRegs 0
attr PV_Anlage_1 obj-h559-revRegs 0
attr PV_Anlage_1 obj-h56-format %.0f
attr PV_Anlage_1 obj-h56-reading Inverter_state
attr PV_Anlage_1 obj-h56-unpack N
attr PV_Anlage_1 obj-h575-len 1
attr PV_Anlage_1 obj-h575-reading Inverter_Generation_Power_(actual)
attr PV_Anlage_1 obj-h577-len 2
attr PV_Anlage_1 obj-h577-reading Generation_Energy
attr PV_Anlage_1 obj-h577-unpack N
attr PV_Anlage_1 obj-h578-reading Total_energy
attr PV_Anlage_1 obj-h582-reading Actual_battery_charge-discharge_power
attr PV_Anlage_1 obj-h586-format %s
attr PV_Anlage_1 obj-h586-reading Battery_Firmware
attr PV_Anlage_1 obj-h586-unpack N
attr PV_Anlage_1 obj-h588-format %s
attr PV_Anlage_1 obj-h588-len 1
attr PV_Anlage_1 obj-h588-reading Battery_Type
attr PV_Anlage_1 obj-h588-unpack N
attr PV_Anlage_1 obj-h6-reading Inverter_article_number
attr PV_Anlage_1 obj-h6-type STR
attr PV_Anlage_1 obj-h768-len 32
attr PV_Anlage_1 obj-h768-reading Productname
attr PV_Anlage_1 obj-h768-type STR
attr PV_Anlage_1 obj-h800-len 32
attr PV_Anlage_1 obj-h800-reading Power_class
attr PV_Anlage_1 obj-h800-type STR
attr PV_Anlage_1 room Strom->Photovoltaik
attr PV_Anlage_1 sortby 01
attr PV_Anlage_1 stateFormat {sprintf("\
<TABLE>\
\
<TR>\
  <TH ALIGN=\"MIDDLE\" WIDTH=\"20\">Batterie %s</TH>\
  <TH ALIGN=\"MIDDLE\" WIDTH=\"20\">aktuell</TH>\
  <TH ALIGN=\"RIGHT\" WIDTH=\"20\">Hausverbrauch</TH>\
  <TH ALIGN=\"MIDDLE\" WIDTH=\"20\">Erträge</TH>\
</TR>\
\
<TR>\
  <TD ALIGN=\"MIDDLE\" WIDTH=\"20\">\
    Leistung:  %04d W<br>\
    Temp.: %02.1f °C<br>\
    Ladung total: %2d %%<br>\
    Ladung Res.: %04d Wh\
  </TD>\
\
  <TD ALIGN=\"RIGHT\" WIDTH=\"20\">\
    DC total: %05d W<br>\
    <br>\
    <br>\
    PV reserve: %05d W\
  </TD>\
\
  <TD ALIGN=\"RIGHT\" WIDTH=\"20\">\
    von PV: %05d W <br>\
    von Batterie: %05d W<br>\
    vom Netz: %05d W<br>\
    ins Haus: %05d W<br>\
    Netz: %05d W\
  </TD>\
\
  <TD ALIGN=\"RIGHT\" WIDTH=\"20\">\
    Tag: %05d KWh <br>\
    Monat: %05d KWh<br>\
    Jahr: %05d KWh<br>\
    Total: %05d KWh\
  </TD>\
</TR>\
\
</TABLE>\
" , \
(ReadingsVal($name,"Actual_battery_charge_-minus_or_discharge_-plus_Power",0) lt 0) ? "<span style='color:#00FF00'>Laden</span>":"<span style='color:#FF0000'>Entladen</span>" ,\
\
ReadingsVal($name,"Actual_battery_charge_-minus_or_discharge_-plus_Power",0),\
ReadingsVal($name,"Battery_temperature",0) ,\
ReadingsVal($name,"Act_state_of_charge",0) ,\
ReadingsVal($name,"Actual_battery_charge_usable_Power",0) ,\
\
ReadingsVal($name,"Power_DC_Sum","0"),\
ReadingsVal($name,"Total_PV_Power_reserve","0"),\
\
ReadingsVal($name,"Home_own_consumption_from_PV",0) ,\
ReadingsVal($name,"Home_own_consumption_from_battery",0) ,\
ReadingsVal($name,"Home_own_consumption_from_grid",0),\
ReadingsVal($name,"Home_own_consumption_from_PV",0) +ReadingsVal($name,"Home_own_consumption_from_battery",0)+ReadingsVal($name,"Home_own_consumption_from_grid",0),\
ReadingsVal($name,"Total_active_power_(powermeter)",0),\
\
round(ReadingsVal($name,"Daily_yield",0)/1000 ,0),\
round(ReadingsVal($name,"Monthly_yield",0)/1000 ,0) ,\
round(ReadingsVal($name,"Yearly_yield",0)/1000 ,0) ,\
round(ReadingsVal($name,"Total_yield",0)/1000 ,0)\
)}
attr PV_Anlage_1 userReadings Power_DC_Sum:Total_DC_Power.* { ReadingsVal($NAME,"Power_DC1","0")+ReadingsVal($NAME,"Power_DC2","0") },\
\
Total_PV_Power_reserve:Total_DC_Power.* {my $reserve = ReadingsVal($NAME,"Power_DC_Sum","0") * 0.90 - ReadingsVal($NAME,"Home_own_consumption_from_PV","0");;;; ($reserve lt 0)?0:round($reserve,3)  },\
\
Total_DC_Power_Max:Total_DC_Power.* { my $Bat_out = (ReadingsVal($NAME,"Actual_battery_charge_-minus_or_discharge_-plus_current","0")*ReadingsVal($NAME,"Battery_voltage","0"));;;; ($Bat_out gt 0)?ReadingsVal($NAME,"Power_DC_Sum","0") + $Bat_out :ReadingsVal($NAME,"Power_DC_Sum","0") },\
\
Actual_battery_charge_-minus_or_discharge_-plus_Power:Actual_battery_charge_-minus_or_discharge_-plus_current.* {round((ReadingsVal($NAME,"Actual_battery_charge_-minus_or_discharge_-plus_current","0")*ReadingsVal($NAME,"Battery_voltage","0")),0)},\
\
Actual_battery_charge_usable_Power:Act_state_of_charge.* {my $x = (8960*(ReadingsVal($NAME,"Act_state_of_charge","0")-10)/100);;;; ($x lt 0)?0:round($x,0) },\
\
Solar_SolarRadiation:Total_DC_Power.* { my $x1 = POSIX::strftime("%Y-%m-%d_%H_00_Rad1wh",localtime(time-60*60)) ;;;; my $x2 = POSIX::strftime("%Y-%m-%d_%H_00_Rad1wh",localtime()) ;;;; my $x_avg = round((ReadingsVal("DWD_Prognose",$x1,0)+ReadingsVal("DWD_Prognose",$x2,0))/2 , 0) ;;;; my $time = POSIX::strftime("%M",localtime()) ;;;; ($time < 30)?ReadingsVal("DWD_Prognose",$x1,0):$x_avg },\
\
statistics_clean:statistics_output.* { my $x =  ReadingsVal($NAME,"statistics_output",0);; $x =~ s/"moduleid": "scb:statistic:EnergyFlow", |, "moduleid": "scb:statistic:EnergyFlow"|"processdata": \[//g;; $x =~ s/id": "|, "unit": "", "value"|^\[|\]\}\]$//g;; $x =~ s/moduleid/statistics_00_moduleid/g;; $x =~ s/processdata/statistics/g;; $x =~ s/\}\, \{/\, /g;; $x =~ s/\{\{/\{/g;; return $x }
attr PV_Anlage_1 verbose 0


Für die Plenticore Statistiken wird noch ein expandJSON benötigt.

defmod Plenticore_Statistics expandJSON PV_Anlage_1:statistics_clean:.\{.*}
attr Plenticore_Statistics DbLogExclude .*
attr Plenticore_Statistics alias Plenticore_Statistics
attr Plenticore_Statistics comment Das Device wird über ein Python Skript im reading output befüllt.\
deletereading Plenticore_Status [A|C|EXT|RANGE|WS].*\

attr Plenticore_Statistics room Strom->Photovoltaik


Der Ablauf für die Statistiken ist dann wie folgt:

1) Einmalig müssen einige Parameter als readings im Device PV_Anlage_1 gesetzt werden

setreading PV_Anlage_1 IP-Address_Plenticore
setreading PV_Anlage_1 IP-Address_FHEM


2) Das Skript /opt/fhem/python/bin/plenticore_statistic.py wird einmal pro Stunde aus dem DOIF mit allen Parametern aufgerufen
3) Dann wird von dem Skript in PV_Anlage_1 das reading statistics_output befüllt. Dieses JSON kann so leider nicht direkt verwendet werden.
4) Ein userreading in PV_Anlage_1 wandelt das JSON aus Schritt 3) um und schreibt es in statistics_clean
5) Das Device Plenticore_Statistics wandelt nun das JSON in einzelne readings in PV_Anlage_1 um. Nun sollten alle statistic_* readings vorhanden sein.

6) Die Statistiken werden von meinem Bilanz Device gelesen, was ebenfalls in diesem DOIF mit "set Dum.Energy update" stündlich aktualisiert wird.

7) Der Forecast über den DWD und Proplanta läuft auch bereits, aber würde diesen rahmen sprengen.




Aktualisierung der Bilanz durch einen zyklischen Aufruf aus einem DOIF
hier wird alle 5 Minuten zwischen 8:00 und 20:00 Uhr das Dummy aktiviert um die Bilanz aufzustellen. Das geht natürlich auch mit einem AT, jedoch ist dies nur ein erster Ausschnitt vom DOIF.
Im Orginial gibt es noch einige weitere Einträge, die die PV_Anlage_ 1 betreffen. Das findet sich dann später im Wiki.

defmod PV_Schedule DOIF ################################################################################################################\
## 2 Plenticore Status aktualisieren\
##\
([:57])\
   (\
    {system("/usr/bin/python3 /opt/fhem/python/bin/plenticore_statistic.py ".ReadingsVal("PV_Anlage_1","IP-Address_Plenticore","?")." ".ReadingsVal("PV_Anlage_1","IP-Address_FHEM","?")." &")}\
   set Dum.Energy update\
\
   )\

attr PV_Schedule DbLogExclude .*
attr PV_Schedule alias PV_Schedule
attr PV_Schedule cmdState BYD Status|Plenticore Status
attr PV_Schedule do always
attr PV_Schedule room Strom->System
attr PV_Schedule sortby 11
attr PV_Schedule wait 0:0:0:10:0:0


Die folgenden Python Skripte sind inhaltlich nicht vollständig von mir. Verwendung auf eigene Gefahr.
Momentan bin ich dabei die ersten Versuche zu machen, die Kommunikation auf Fhem HTTPMOD umzustellen, was bereits teilweise funktioniert.
Für mich ist die Python Lösung nur ein zwischen Schritt, der nicht auf dauer so bleiben soll. Trotzdem läuft es mit dieser Konfiguration bereits ca. 6 Monate fehlerfrei.

Eventuell müssen noch Python Module nachinstalliert werden:
## pip3 install pycryptodome
## pip3 install -U fhem

Die Pfadnamen können geändert werden, dann aber auch  bitte überall ;-)

/opt/fhem/python/bin/plenticore_statistic.py

#####
##
## https://stackoverflow.com/questions/59053539/api-call-portation-from-java-to-python-kostal-plenticore-inverter?answertab=active#tab-top
##

import random
import string
import base64
import json
import requests
import hashlib
import os
import hmac
from Crypto.Cipher import AES
import binascii

import fhem
import asyncio

import sys
plenticore = sys.argv[1]
web = sys.argv[2]
request = '/processdata/scb:statistic:EnergyFlow'

try:
    with open('/opt/fhem/python/pwd_plenticore.json', 'r') as f:
        credentials=json.load(f)
except Exception as e:
    print('Something went wrong: {}'.format(e))

USER_TYPE = credentials["username"]
PASSWD = credentials["password"]
BASE_URL = "http://" + plenticore + "/api/v1"
AUTH_START = "/auth/start"
AUTH_FINISH = "/auth/finish"
AUTH_CREATE_SESSION = "/auth/create_session"
ME = "/auth/me"

def randomString(stringLength):
    letters = string.ascii_letters
    return ''.join(random.choice(letters) for i in range(stringLength))

u = randomString(12)
u = base64.b64encode(u.encode('utf-8')).decode('utf-8')

step1 = {
  "username": USER_TYPE,
  "nonce": u
}
step1 = json.dumps(step1)

url = BASE_URL + AUTH_START
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
response = requests.post(url, data=step1, headers=headers)
response = json.loads(response.text)
i = response['nonce']
e = response['transactionId']
o = response['rounds']
a = response['salt']
bitSalt = base64.b64decode(a)

def getPBKDF2Hash(password, bytedSalt, rounds):
    return hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), bytedSalt, rounds)

r = getPBKDF2Hash(PASSWD,bitSalt,o)
s = hmac.new(r, "Client Key".encode('utf-8'), hashlib.sha256).digest()
c = hmac.new(r, "Server Key".encode('utf-8'), hashlib.sha256).digest()
_ = hashlib.sha256(s).digest()
d = "n=user,r="+u+",r="+i+",s="+a+",i="+str(o)+",c=biws,r="+i
g = hmac.new(_, d.encode('utf-8'), hashlib.sha256).digest()
p = hmac.new(c, d.encode('utf-8'), hashlib.sha256).digest()
f = bytes(a ^ b for (a, b) in zip(s, g))
proof = base64.b64encode(f).decode('utf-8')

step2 = {
  "transactionId": e,
  "proof": proof
}
step2 = json.dumps(step2)

url = BASE_URL + AUTH_FINISH
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
response = requests.post(url, data=step2, headers=headers)
response = json.loads(response.text)
token = response['token']
signature = response['signature']

y = hmac.new(_, "Session Key".encode('utf-8'), hashlib.sha256)
y.update(d.encode('utf-8'))
y.update(s)
P = y.digest()
protocol_key = P
t = os.urandom(16)

e2 = AES.new(protocol_key,AES.MODE_GCM,t)
e2, authtag = e2.encrypt_and_digest(token.encode('utf-8'))

step3 = {
  "transactionId": e,
  "iv": base64.b64encode(t).decode('utf-8'),
  "tag": base64.b64encode(authtag).decode("utf-8"),
  "payload": base64.b64encode(e2).decode('utf-8')
}
step3 = json.dumps(step3)

headers = { 'Content-type': 'application/json', 'Accept': 'application/json' }
url = BASE_URL + AUTH_CREATE_SESSION
response = requests.post(url, data=step3, headers=headers)
response = json.loads(response.text)
sessionId = response['sessionId']

#create a new header with the new Session-ID for all further requests
headers = { 'Content-type': 'application/json', 'Accept': 'application/json', 'authorization': "Session " + sessionId }
url = BASE_URL + ME
response = requests.get(url = url, headers = headers)
response = json.loads(response.text)
authOK = response['authenticated']
if not authOK:
    print("authorization NOT OK")
    sys.exit()

url = BASE_URL + "/info/version"
response = requests.get(url = url, headers = headers)
response = json.loads(response.text)
swversion = response['sw_version']
apiversion = response['api_version']
hostname = response['hostname']
name = response['name']
print("Connected to the inverter " + name + "/" + hostname + " with SW-Version " + swversion + " and API-Version " + apiversion)

# Auth OK, now send your desired requests

url = BASE_URL + request

response = requests.get(url = url, headers = headers)
response = json.loads(response.text)

message  = json.dumps(response)

#print(json.dumps(response, indent=4, sort_keys=True))
#print(message)


async def run():

    try:
        with open('/opt/fhem/python/pwd_fhem.json', 'r') as f:
            credentials=json.load(f)
    except Exception as e:
        print('Something went wrong: {}'.format(e))

    fh = fhem.Fhem(web, protocol="http", port=8083, username=credentials["username"], password=credentials["password"])

    fh.send_cmd("setreading PV_Anlage_1 statistics_output " + message)

asyncio.get_event_loop().run_until_complete(run())


Für das obige Skript sind die Passworte im Filesystem hinterlegt.

/opt/fhem/python/
-rw-r----- 1 fhem fhem   53 Aug 19 10:52 pwd_fhem.json

{
    "username": "<Dein user Name>",
    "password": "<Dein Passwort>"
}


-rw-r----- 1 fhem fhem   59 Mär 26 11:57 pwd_plenticore.json
Hier ist der username fest vom Plenticore vorgegeben, das Passwort findet sich auf einem Gehäuseaufkleber am WR.

{
    "username": "user",
    "password": "<Dein Passwort>"
}

RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

KölnSolar

wenn ich nur auf die Zahlen gucke ist
ZitatPV-Erzeugung incl. Speicher
der Eigenverbrauch(egal ob Speicher od. direkt).  :-\
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

ch.eick

Okay,

PV-Erzeugung   {round((ReadingsVal("PV_Anlage_1","Total_AC_active_power", ""),0)}

Der Eigenverbrauch laeuft hier unter
TotalConsumption
          {round((ReadingsVal("PV_Anlage_1","Home_own_consumption_from_PV", "") +
                       ReadingsVal("PV_Anlage_1","Home_own_consumption_from_battery",0) +
                       ReadingsVal("PV_Anlage_1","Home_own_consumption_from_grid",0))     <<<< zaehlte der Netzverbrauch auch dazu?
                    ,0)}

Gruss
     Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

#3
Moin,
im ersten Post gab es einen Update...

und den ersten Monats Plot hier Bilanz Plot aus DBLog
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Der Fehlerteufel hat sich eingeschlichen.

das userreading fuer SelfConsumptionQuote war nicht korrekt. Die Definition ist im ersten Post aktualisiert.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

#5
Hallo zusammen,
ich habe da mal eine schoene externe Seite gefunden, um Autarkie und Eigenverbrauch abzuschaetzen.
Unabhängigkeitsrechner
Wie immer, keine Haftung fuer externe Seiten und alles andere was man noch so ausschliessen muss :-)
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Der erste Post wurde mit Stand heute wieder aktualisiert...
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Mumpitz

Hallo Christian

Ich habe heute Abend versucht die Bilanz zu implementieren. Leider habe ich das Problem, dass in PV_Anlage_1 die Statistik Einträge nicht erstellt werden:

\
statistics_clean:statistics_output.* { my $x =  ReadingsVal($NAME,"statistics_output",0);;;; $x =~ s/\{"moduleid": "scb:statistic:EnergyFlow", "processdata": \[|id": "|, "unit": "", "value"|^\[|\]\}\]$//g;;;; $x =~ s/moduleid/statistics_00_moduleid/g;;;; $x =~ s/processdata/statistics/g;;;; $x =~ s/\}\, \{/\, /g;;;; return $x }


ich vermute fast das ich hier noch ein paar Sachen anpassen muss.

Nur was? und mit welchen Werten?

danke für deine Hilfe


ch.eick

Zitat von: Mumpitz am 23 August 2020, 20:11:01
Hallo Christian

Ich habe heute Abend versucht die Bilanz zu implementieren. Leider habe ich das Problem, dass in PV_Anlage_1 die Statistik Einträge nicht erstellt werden:

\
statistics_clean:statistics_output.* { my $x =  ReadingsVal($NAME,"statistics_output",0);;;; $x =~ s/\{"moduleid": "scb:statistic:EnergyFlow", "processdata": \[|id": "|, "unit": "", "value"|^\[|\]\}\]$//g;;;; $x =~ s/moduleid/statistics_00_moduleid/g;;;; $x =~ s/processdata/statistics/g;;;; $x =~ s/\}\, \{/\, /g;;;; return $x }


ich vermute fast das ich hier noch ein paar Sachen anpassen muss.

Nur was? und mit welchen Werten?

danke für deine Hilfe
Dafür musst Du das Python Skript implementieren, das diese Werte aus dem Plenticore ausliest.
Gruß Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Zitat von: Mumpitz am 23 August 2020, 20:11:01
Hallo Christian

Ich habe heute Abend versucht die Bilanz zu implementieren. Leider habe ich das Problem, dass in PV_Anlage_1 die Statistik Einträge nicht erstellt werden:

\
statistics_clean:statistics_output.* { my $x =  ReadingsVal($NAME,"statistics_output",0);;;; $x =~ s/\{"moduleid": "scb:statistic:EnergyFlow", "processdata": \[|id": "|, "unit": "", "value"|^\[|\]\}\]$//g;;;; $x =~ s/moduleid/statistics_00_moduleid/g;;;; $x =~ s/processdata/statistics/g;;;; $x =~ s/\}\, \{/\, /g;;;; return $x }


ich vermute fast das ich hier noch ein paar Sachen anpassen muss.

Nur was? und mit welchen Werten?

danke für deine Hilfe
Dafür musst Du das Python Skript implementieren, das diese Werte aus dem Plenticore ausliest.
Gruß Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Mumpitz

Zitat von: ch.eick am 24 August 2020, 08:57:16
Dafür musst Du das Python Skript implementieren, das diese Werte aus dem Plenticore ausliest.
Gruß Christian

Das habe ich natürlich gemacht! Es erscheint der folgende Fehler im Logfile von fhem:

KeyError: 'nonce'
    i = response['nonce']
  File "/opt/fhem/python/bin/plenticore_statistic.py", line 56, in <module>
Traceback (most recent call last):


Hast du eine Idee?

ch.eick

#11
Zitat von: Mumpitz am 24 August 2020, 10:04:38
KeyError: 'nonce'
    i = response['nonce']
  File "/opt/fhem/python/bin/plenticore_statistic.py", line 56, in <module>
Traceback (most recent call last):

Da stimmt schon etwas mit dem ersten HTTP Aufruf nicht.

Verwendest Du das Python Version 3?
Werden alle importe gemacht?

Hast Du das Passwort File angelegt?

Ich baue mir dann immer folgendes ein, damit man nicht so blind suchen muss

print("Login : ", USER_TYPE)
print("PWD : ", PASSWD)

print("Meldung : ",response )

print ("header : ",response.request.headers)
print ("body    : ",response.request.body)


Du kannst es ja auch direkt auf der Kommandozeile aufrufen

/usr/bin/python3 /opt/fhem/python/bin/plenticore_statistic.py >IP-Adresse des Plenticore> <IP-Adresse des Fhem Telnet>


Gruß
    Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Mumpitz

#12
Zitat von: ch.eick am 24 August 2020, 10:44:15
Da stimmt schon etwas mit dem ersten HTTP Aufruf nicht.

Verwendest Du das Python Version 3?
Werden alle importe gemacht?

Hast Du das Passwort File angelegt?

Ich baue mir dann immer folgendes ein, damit man nicht so blind suchen muss

print("Login : ", USER_TYPE)
print("PWD : ", PASSWD)

print("Meldung : ",response )

print ("header : ",response.request.headers)
print ("body    : ",response.request.body)


Du kannst es ja auch direkt auf der Kommandozeile aufrufen

/usr/bin/python3 /opt/fhem/python/bin/plenticore_statistic.py >IP-Adresse des Plenticore> <IP-Adresse des Fhem Telnet>


Gruß
    Christian

Das Passwort File ist angelegt. Die Frage stellt sich allerdings auch noch, was für ein Passwort da rein kommt?
Also über die IP Adresse komme ich auf den lokalen Webserver. Dort gibt es jedoch keinen Benutzer, sondern Anlagenbetreiber zur Auswahl. Passwort ist klar.

Wenn ich auf per http auf das api zugreife kommt keine Passwortabfrage sondern eine komische Seite mit POST befehlen.


root@FHEM:/opt/fhem/python/bin# /opt/fhem/python/bin/plenticore_statistic.py 192.168.17.30 192.168.17.5
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
from: can't read /var/mail/Crypto.Cipher
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/360.
/opt/fhem/python/bin/plenticore_statistic.py: line 21: plenticore: command not found
/opt/fhem/python/bin/plenticore_statistic.py: line 22: web: command not found
/opt/fhem/python/bin/plenticore_statistic.py: line 23: request: command not found
/opt/fhem/python/bin/plenticore_statistic.py: line 25: try:: command not found
/opt/fhem/python/bin/plenticore_statistic.py: line 26: syntax error near unexpected token `('
/opt/fhem/python/bin/plenticore_statistic.py: line 26: `    with open('/opt/fhem/python/pwd_plenticore.json', 'r') as f:'



Hmm,?

ch.eick

Zitat von: Mumpitz am 24 August 2020, 17:44:37
Das Passwort File ist angelegt. Die Frage stellt sich allerdings auch noch, was für ein Passwort da rein kommt?
Also über die IP Adresse komme ich auf den lokalen Webserver. Dort gibt es jedoch keinen Benutzer, sondern Anlagenbetreiber zur Auswahl. Passwort ist klar.

Wenn ich auf per http auf das api zugreife kommt keine Passwortabfrage sondern eine komische Seite mit POST befehlen.

Im Passwort file steht

{
    "username": "user",
    "password": "Das Passwort steht auf dem Gehäuse"
}

"user" ist hierbei vorgegeben und entspricht dem Betreiber.


Das ist die nicht dokumentierte API Oberfläche, da sieht man aber was so alles gehen soll

http://<IP-Adresse>/api/vi



Dieser Aufruf ist schon mal falsch!

root@FHEM:/opt/fhem/python/bin# /opt/fhem/python/bin/plenticore_statistic.py 192.168.17.30 192.168.17.5


er sollte so lauten, den /usr/bin/python3 ist der Interpreter, der das Programm abarbeitet.

fhem@raspberrypi:~/python/bin$ /usr/bin/python3 plenticore_statistic.py 192.168.178.18 192.168.178.40

###### Hier noch etwas über Deine Python installation
fhem@raspberrypi:~/python/bin$ which python3
/usr/bin/python3

fhem@raspberrypi:~/python/bin$ python3 --version
Python 3.7.3

RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Mumpitz

Zitat von: ch.eick am 24 August 2020, 20:21:46
Im Passwort file steht

{
    "username": "user",
    "password": "Das Passwort steht auf dem Gehäuse"
}


OK, nun bin ich einen Schritt weiter!

Nun erhalten ich auf der Konsole wie auch in fhem bereits eine Antwort:


Connected to the inverter PUCK RESTful API/Hermet with SW-Version 01.15.04581 and API-Version 0.2.0
CSRF token not available!
CSRF token requested for server that doesn't know CSRF
CSRF token requested for server that doesn't know CSRF
2020.08.25 07:33:24 3: eval: {round( (ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Year","")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Year","")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomeGrid_Year","") )/1000,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in addition (+) at (eval 2101105) line 1.
2020.08.25 07:33:24 3: eval: {round( (ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Month","")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Month","")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomeGrid_Month","") )/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in addition (+) at (eval 2101104) line 1.
2020.08.25 07:33:24 3: eval: {round( (ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Day","")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Day","")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomeGrid_Day","") )/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in addition (+) at (eval 2101103) line 1.
2020.08.25 07:33:24 3: eval: {round(ReadingsVal("WR_Plenticore","Statistic_EnergyHomeGrid_Year","")/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in division (/) at (eval 2101101) line 1.
2020.08.25 07:33:24 3: eval: {round(ReadingsVal("WR_Plenticore","Statistic_EnergyHomeGrid_Month","")/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in division (/) at (eval 2101100) line 1.
2020.08.25 07:33:24 3: eval: {round(abs(ReadingsVal("WR_Plenticore","Statistic_EnergyHomeGrid_Day",""))/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in abs at (eval 2101099) line 1.
2020.08.25 07:33:24 3: eval: {round((ReadingsVal("WR_Plenticore","Statistic_Yield_Year", "")-ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Year", "")-ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Year", ""))/1000,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in subtraction (-) at (eval 2101097) line 1.
2020.08.25 07:33:24 3: eval: {round((ReadingsVal("WR_Plenticore","Statistic_Yield_Month", "")-ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Month", "")-ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Month", ""))/1000,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in subtraction (-) at (eval 2101096) line 1.
2020.08.25 07:33:24 3: eval: {round((ReadingsVal("WR_Plenticore","Statistic_Yield_Day", "")-ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Day", "")-ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Day", ""))/1000,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in subtraction (-) at (eval 2101095) line 1.
2020.08.25 07:33:24 3: eval: {round( (ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Year", "")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Year", ""))/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in addition (+) at (eval 2101093) line 1.
2020.08.25 07:33:24 3: eval: {round( (ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Month", "")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Month", ""))/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in addition (+) at (eval 2101092) line 1.
2020.08.25 07:33:24 3: eval: {round( (ReadingsVal("WR_Plenticore","Statistic_EnergyHomeBat_Day", "")+ReadingsVal("WR_Plenticore","Statistic_EnergyHomePv_Day", ""))/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in addition (+) at (eval 2101091) line 1.
2020.08.25 07:33:24 3: eval: {round( ReadingsVal("WR_Plenticore","Statistic_Yield_Year", "")/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in division (/) at (eval 2101089) line 1.
2020.08.25 07:33:24 3: eval: {round( ReadingsVal("WR_Plenticore","Statistic_Yield_Month", "")/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in division (/) at (eval 2101088) line 1.
2020.08.25 07:33:24 3: eval: {round( ReadingsVal("WR_Plenticore","Statistic_Yield_Day", "")/1000 ,2)}
2020.08.25 07:33:24 1: PERL WARNING: Argument "" isn't numeric in division (/) at (eval 2101087) line 1.
2020.08.25 07:33:24 2: PV_Schedule: {system("/usr/bin/python3 /opt/fhem/python/bin/plenticore_statistic.py ".ReadingsVal("WR_Plenticore","IP-Address_Plenticore","?")." ".ReadingsVal("WR_Plenticore","IP-Address_FHEM","?")." &")}: -1


Im Device des Wechselrichter, bei mir WR_Plenticore, habe ich auch 2 neue Readings erhalten. Allerdings mit komischen Inhalt:


statistics_clean {"statistics": [], "modulehermet:statistic:EnergyFlow"}]
statistics_output [{"processdata": [], "moduleid": "hermet:statistic:EnergyFlow"}]