Hallo zusammen,
hat schon wer Erfahrungen mit Akkus dieses Herstellers. Die lassen sich per MQTTT abfragen (sogar der B2500 Saturn), aber im Forum findet meine Suche nix. Angeblich haben die die Besonderheit, das man die regelmäßig abfragen muß.
Da zumindest der B2500 seine Daten nicht von sich aus publizieren, muß man den mit einem MQTT Befehl ,,anstupsen". Dann erhält man alle Daten und muß die dann in ,,lesbare" Daten übersetzen. Hat das hier schonmal jemand versucht und mag mir ein Partisan geben oder seine Integration hier beschreiben? Oder bin ich der erste, der diesen Speicher von Fhem aus überwachen und steuern will?
Alex
Diesen Beitrag hattest du gefunden?
https://forum.fhem.de/index.php?topic=141215.msg1337817;topicseen#msg1337817 (https://forum.fhem.de/index.php?topic=141215.msg1337817;topicseen#msg1337817)
Nein, Marstek wird dort ja nicht erwähnt :-)
Aber ich werde mir das mal zu Gemüte führen und probieren, ob ich damit etwas anfangen kann. Sieht zumindest auf den ersten Blick schon mal zielführend aus um mir was eigenes zusammenzustricken. Inzwischen ist mein Speicher ja auch angekommen, nur fehlt es heute etwas an Sonne, um ihn wieder zu befüllen.
Auf jeden Fall vielen Dank für den Link.
Alex
Hi Alex,
Bist du mit mqtt weiter gekommen?
Überlege mir eine Venus E zu kaufen
Lg
Joachim
Hallo Joachim,
ja, bin ich inzwischen. Ich mag aber noch kein Beispiel posten weil da fehlt einfach noch zuviel und bei dem was da ist, da bin ich auch nicht sicher, ob das alles so elegant ist.
Prinzipiell geht das aber, ich denke, deine Venus kann kommen wenn die deine Wünsche erfüllt :-)
Hallo zusammen,
derzeit hole ich mit dem Attribut periodicCmd 1x pro Minute die Daten vom Speicher ab. Der Aufruf landet aber jedesmal im globalen Logfile und spamt das voll. Gibt es da einen Weg, das zu verhindern.
Leider muß ich die Daten "aktiv" anfordern, der Speicher sendet freiwilig nix an den Server. Das macht er nur, wenn er mit der Cloud verbunden ist und die will ich ja nicht.
Gruß
Alex
verbose 2?
Theoretisch ja, praktisch wird irgendwo empfohlen, verbose 3 zu nutzen. Muß ich mal schauen, ob mir dann andere Infos aus dem Log verlorengehen. Oder kann man verbose einzelne devices setzen?
Erledigt, man kann :-)
So, ich wage mich mal mit einem ersten Versuch aus der Deckung.
Am Ende vom Text gibt 1x das (aktuelle) Device und 1x eine Funktion, mit der ich die Rückgabewerte zerlege und in die Readings stecke. Die kommt in die myUtils. Wer was eleganteres kennt, immer her damit. Andere Verbesserungen sind auch willkommen.
Insbesondere suche ich Beispiele, mit denen ich das "UI" aufpumpen kann. Gerade die Zeitpläne sollte man auch mit Ein/Aus Schalter und Menüs für die Zeiten eingeben können. Da ist also noch viel Erweiterungspotential vorhanden :-)
Das Device:
Internals:
CFGFN
CID HMJ_2_
DEF HMJ_2_
FUUID 6845db47-f33f-0381-cd1f-3c376463aa32835f
IODev MQTT2_FHEM_Server
LASTInputDev MQTT2_FHEM_Server
MQTT2_FHEM_Server_CONN MQTT2_FHEM_Server_172.30.81.226_48446
MQTT2_FHEM_Server_MSGCNT 5979
MQTT2_FHEM_Server_TIME 2025-06-16 13:41:28
MSGCNT 5979
NAME Marstek_B2500D_Sued
NR 2553
STATE <div style="text-align: right;">
in: <b>298 W</b> ∑<b>2.742 kWh</b>,
out: <b>115 W</b>,
Akku: <b>2.217 kWh</b> (<b>99 %</b>),
<font color="black"><b>23 °C</b></font>
</div>
TYPE MQTT2_DEVICE
eventCount 6554
periodicCounter 5240
OLDREADINGS:
READINGS:
2025-06-12 16:08:40 IODev MQTT2_FHEM_Server
2025-06-16 13:41:28 am 0
2025-06-16 13:41:28 batBootloaderVersion 107
2025-06-16 13:41:28 batCapacityExtraBat1 0
2025-06-16 13:41:28 batCapacityExtraBat2 0
2025-06-16 13:41:28 batCapacityHost 99
2025-06-15 09:36:02 batChannelOfCTCH 255
2025-06-16 13:41:28 batChargeMode 0
2025-06-16 13:41:28 batCtHostChannel 255
2025-06-16 13:41:28 batCtHostStatus 0
2025-06-16 13:41:28 batDeviceID 5
2025-06-16 13:41:28 batDischargeMode 0
2025-06-16 13:41:28 batDischargePlan1End 23:56
2025-06-16 13:41:28 batDischargePlan1Start 0:1
2025-06-16 13:41:28 batDischargePlan1State 1
2025-06-16 13:41:28 batDischargePlan1Value 800
2025-06-16 13:41:28 batDischargePlan2End 23:59
2025-06-16 13:41:28 batDischargePlan2Start 0:0
2025-06-16 13:41:28 batDischargePlan2State 0
2025-06-16 13:41:28 batDischargePlan2Value 80
2025-06-16 13:41:28 batDischargePlan3End 23:59
2025-06-16 13:41:28 batDischargePlan3Start 0:0
2025-06-16 13:41:28 batDischargePlan3State 0
2025-06-16 13:41:28 batDischargePlan3Value 80
2025-06-16 13:41:28 batDischargePlan4End 23:59
2025-06-16 13:41:28 batDischargePlan4Start 0:0
2025-06-16 13:41:28 batDischargePlan4State 0
2025-06-16 13:41:28 batDischargePlan4Value 80
2025-06-16 13:41:28 batDischargePlan5End 23:59
2025-06-16 13:41:28 batDischargePlan5Start 0:0
2025-06-16 13:41:28 batDischargePlan5State 0
2025-06-16 13:41:28 batDischargePlan5Value 80
2025-06-16 13:41:28 batDischargeState 0
2025-06-16 13:41:28 batDoD 90
2025-06-15 12:59:07 batEnergyLimitingInOut 0
2025-06-16 13:41:28 batEnergyLimiting_InOut 1
2025-06-15 12:59:07 batEnergyRatedIn 1472
2025-06-15 12:59:07 batEnergyRatedOut 1989
2025-06-16 13:41:28 batEnergyRated_In 297
2025-06-16 13:41:28 batEnergyRated_Out 2010
2025-06-16 13:41:28 batEnergyTotal 1399
2025-06-16 13:41:28 batEnergyTotal_Inverter 2009
2025-06-16 13:41:28 batEnergyTotal_Out 855
2025-06-16 13:41:28 batEnergyTotal_PV 2742
2025-06-16 13:41:28 batEnergy_kWh 2217
2025-06-16 13:41:28 batEnergy_perc 99
2025-06-16 13:41:28 batExtraBatConnected1 0
2025-06-16 13:41:28 batExtraBatConnected2 0
2025-06-15 13:44:08 batFirmware 110.9
2025-06-16 13:41:28 batFirmwareFC4VersionNumber 202310231502
2025-06-16 13:41:28 batFirmwareMain 110
2025-06-16 13:41:28 batFirmwareSub 9
2025-06-13 23:28:19 batLimitingInOut 0
2025-06-16 13:41:28 batOutputThreshold 800
2025-06-16 13:41:28 batPowerOfInverter 115
2025-06-16 13:41:28 batPowerOut 115
2025-06-16 13:41:28 batPowerOut1 25
2025-06-16 13:41:28 batPowerOut2 90
2025-06-16 13:41:28 batPowerPV1 146
2025-06-16 13:41:28 batPowerPV2 152
2025-06-16 13:41:28 batPowerPVin 298
2025-06-16 13:41:28 batPowerTransmitted 0
2025-06-16 13:41:28 batSMAutoPowerSize 80
2025-06-16 13:41:28 batSMClip_1 0
2025-06-16 13:41:28 batSMClip_2 0
2025-06-16 13:41:28 batSMClip_3 0
2025-06-16 13:41:28 batSMConnected 0
2025-06-16 13:41:28 batScene 0
2025-06-09 18:39:30 batSensorConnected 0
2025-06-16 13:41:28 batSignPos_Ex1_Ex2 0
2025-06-16 13:41:28 batSignPos_Host 2
2025-06-16 13:41:28 batStateOut1 1
2025-06-16 13:41:28 batStateOut2 1
2025-06-16 13:41:28 batStatePV1 1
2025-06-16 13:41:28 batStatePV2 1
2025-06-09 08:13:50 batTemp 17
2025-06-16 13:41:28 batTempAlarmCharging 0
2025-06-16 13:41:28 batTempAlarmDischarging 0
2025-06-16 13:41:28 batTempDischarging 0
2025-06-13 22:37:16 batTempError 0
2025-06-16 13:41:28 batTempHigh 24
2025-06-16 13:41:28 batTempLow 23
2025-06-16 13:41:28 bn 0
2025-06-13 23:22:18 c1 0
2025-06-16 13:41:28 ct_t 7
2025-06-16 13:26:01 ctrl cd=01
2025-06-16 13:41:28 sm 0
2025-06-16 13:41:28 state info
2025-06-13 22:37:16 uv 107
Attributes:
IODev MQTT2_FHEM_Server
alias Marstek Süd
devicetopic hame_energy/HMJ-2/App/009c17e02b39/ctrl
event-on-change-reading .*
group Zähler
icon batterie
periodicCmd info:1
readingList HMJ_2_:hame_energy/HMJ-2/device/009c17e02b39/ctrl:.* {splitCD01( $NAME, $EVENT)}
HMJ_2_:hame_energy/HMJ-2/App/009c17e02b39/ctrl:.* ctrl
room 0_Strom,MQTT2_DEVICE
setList info:noArg $DEVICETOPIC cd=01
plan1_400:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=400
plan1_600:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=600
plan1_700:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=700
plan1_800:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=800
batDoD:slider,0,5,100 $DEVICETOPIC cd=05,md=$EVTPART1
planx:slider,0,5,100 $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=$EVTPART1
stateFormat {
my $tempLow = ReadingsNum( "$name","batTempLow","—-");
my $tempHigh = ReadingsNum( "$name","batTempHigh","—-");
my $temp = int( ($tempLow + $tempHigh)/2);
my $tempCol;
if ($tempLow < 7) {$tempCol = "blue"}
elsif ($tempHigh > 28) {$tempCol = "red"}
else {$tempCol = "black"};
sprintf( qq{<div style="text-align: right;">\
in: <b>%.0f W</b> ∑<b>%.3f kWh</b>, \
out: <b>%.0f W</b>, \
Akku: <b>%.3f kWh</b> (<b>%d %%</b>), \
<font color="$tempCol"><b>%.0f °C</b></font>\
</div>}
, ReadingsNum( "$name","batPowerPVin",0)
, ReadingsNum( "$name","batEnergyTotal_PV",0) /1000
, ReadingsNum( "$name","batPowerOut",0)
, ReadingsNum( "$name","batEnergy_kWh",0) /1000
, ReadingsNum( "$name","batEnergy_perc","—-")
, $temp )
}
userReadings batPowerPVin:batPowerPV2.* {
ReadingsVal( $name, "batPowerPV1", 0)
+ ReadingsVal( $name, "batPowerPV2", 0)
},
batPowerOut:batPowerOut2.* {
ReadingsVal( $name, "batPowerOut1", 0)
+ ReadingsVal( $name, "batPowerOut2", 0)
},
batFirmware:batFirmwareMain.* {
sprintf( "%d.%d",
ReadingsVal( $name, "batFirmwareMain", 0),
ReadingsVal( $name, "batFirmwareSub", 0)
)
}
verbose 2
die Funktion:
sub
splitCD01($$)
{
my ($dev, $answer) = @_;
my $ret;
my $i=0;
for my $element (split m{,}x, $answer) {
$i = $i+1;
my ($key, $val) = split m{=}x, $element;
if ($key eq "p1") {fhem("setreading $dev batStatePV1 $val"); next };
if ($key eq "p2") {fhem("setreading $dev batStatePV2 $val"); next };
if ($key eq "o1") {fhem("setreading $dev batStateOut1 $val"); next };
if ($key eq "o2") {fhem("setreading $dev batStateOut2 $val"); next };
if ($key eq "w1") {fhem("setreading $dev batPowerPV1 $val"); next };
if ($key eq "w2") {fhem("setreading $dev batPowerPV2 $val"); next };
if ($key eq "g1") {fhem("setreading $dev batPowerOut1 $val"); next };
if ($key eq "g2") {fhem("setreading $dev batPowerOut2 $val"); next };
if ($key eq "kn") {fhem("setreading $dev batEnergy_kWh $val"); next };
if ($key eq "pe") {fhem("setreading $dev batEnergy_perc $val"); next };
if ($key eq "do") {fhem("setreading $dev batDoD $val"); next };
if ($key eq "cs") {fhem("setreading $dev batChargeMode $val"); next };
if ($key eq "cd") {fhem("setreading $dev batDischargeMode $val"); next };
if ($key eq "md") {fhem("setreading $dev batDischargeState $val"); next };
if ($key eq "d1") {fhem("setreading $dev batDischargePlan1State $val"); next };
if ($key eq "e1") {fhem("setreading $dev batDischargePlan1Start $val"); next };
if ($key eq "f1") {fhem("setreading $dev batDischargePlan1End $val"); next };
if ($key eq "h1") {fhem("setreading $dev batDischargePlan1Value $val"); next };
if ($key eq "d2") {fhem("setreading $dev batDischargePlan2State $val"); next };
if ($key eq "e2") {fhem("setreading $dev batDischargePlan2Start $val"); next };
if ($key eq "f2") {fhem("setreading $dev batDischargePlan2End $val"); next };
if ($key eq "h2") {fhem("setreading $dev batDischargePlan2Value $val"); next };
if ($key eq "d3") {fhem("setreading $dev batDischargePlan3State $val"); next };
if ($key eq "e3") {fhem("setreading $dev batDischargePlan3Start $val"); next };
if ($key eq "f3") {fhem("setreading $dev batDischargePlan3End $val"); next };
if ($key eq "h3") {fhem("setreading $dev batDischargePlan3Value $val") ; next };
if ($key eq "d4") {fhem("setreading $dev batDischargePlan4State $val"); next };
if ($key eq "e4") {fhem("setreading $dev batDischargePlan4Start $val"); next };
if ($key eq "f4") {fhem("setreading $dev batDischargePlan4End $val"); next };
if ($key eq "h4") {fhem("setreading $dev batDischargePlan4Value $val") ; next };
if ($key eq "d5") {fhem("setreading $dev batDischargePlan5State $val"); next };
if ($key eq "e5") {fhem("setreading $dev batDischargePlan5Start $val"); next };
if ($key eq "f5") {fhem("setreading $dev batDischargePlan5End $val"); next };
if ($key eq "h5") {fhem("setreading $dev batDischargePlan5Value $val") ; next };
if ($key eq "vv") {fhem("setreading $dev batFirmwareMain $val"); next };
if ($key eq "sv") {fhem("setreading $dev batFirmwareSub $val"); next };
if ($key eq "fc") {fhem("setreading $dev batFirmwareFC4VersionNumber $val") ; next };
if ($key eq "id") {fhem("setreading $dev batDeviceID $val") ; next };
if ($key eq "uv") {fhem("setreading $dev batBootloaderVersion $val"); next };
if ($key eq "tl") {fhem("setreading $dev batTempLow $val") ; next };
if ($key eq "th") {fhem("setreading $dev batTempHigh $val") ; next };
if ($key eq "a0") {fhem("setreading $dev batCapacityHost $val"); next };
if ($key eq "a1") {fhem("setreading $dev batCapacityExtraBat1 $val") ; next };
if ($key eq "a2") {fhem("setreading $dev batCapacityExtraBat2 $val") ; next };
if ($key eq "b1") {fhem("setreading $dev batExtraBatConnected1 $val"); next };
if ($key eq "b2") {fhem("setreading $dev batExtraBatConnected2 $val"); next };
# readonly ?
if ($key eq "lv") {fhem("setreading $dev batOutputThreshold $val"); next };
# for Smartmeter
if ($key eq "c0") {fhem("setreading $dev batCtHostChannel $val"); next };
if ($key eq "c1") {fhem("setreading $dev batCtHostStatus $val"); next };
if ($key eq "sg") {fhem("setreading $dev batSMConnected $val"); next };
if ($key eq "sp") {fhem("setreading $dev batSMAutoPowerSize $val") ; next };
if ($key eq "st") {fhem("setreading $dev batPowerTransmitted $val") ; next };
if ($key eq "m0") {fhem("setreading $dev batSMClip_1 $val"); next };
if ($key eq "m1") {fhem("setreading $dev batSMClip_2 $val"); next };
if ($key eq "m2") {fhem("setreading $dev batSMClip_3 $val"); next };
if ($key eq "m3") {fhem("setreading $dev batPowerOfInverter $val"); next };
# Temperaturalarm on/off = 0/1
if ($key eq "tc") {fhem("setreading $dev batTempAlarmCharging $val"); next };
if ($key eq "tf") {fhem("setreading $dev batTempAlarmDischarging $val"); next };
if ($key eq "tc_dis") {fhem("setreading $dev batTempDischarging $val"); next };
# Tageswerte
if ($key eq "bc") {fhem("setreading $dev batEnergyTotal $val"); next };
if ($key eq "bs") {fhem("setreading $dev batEnergyTotal_Out $val"); next };
if ($key eq "pt") {fhem("setreading $dev batEnergyTotal_PV $val"); next };
if ($key eq "it") {fhem("setreading $dev batEnergyTotal_Inverter $val"); next };
if ($key eq "lmf") {fhem("setreading $dev batEnergyLimiting_InOut $val"); next };
if ($key eq "lmi") {fhem("setreading $dev batEnergyRated_In $val"); next };
if ($key eq "lmo") {fhem("setreading $dev batEnergyRated_Out $val"); next };
if ($key eq "cj") {fhem("setreading $dev batScene $val"); next };
# Batterie lädt / entlädt
if ($key eq "l0") {fhem("setreading $dev batSignPos_Host $val"); next };
if ($key eq "l1") {fhem("setreading $dev batSignPos_Ex1_Ex2 $val"); next };
# unknown
#if ($key eq "sm") {fhem("setreading $dev batSMConnected $val"); next };
#if ($key eq "ct_t") {fhem("setreading $dev bat $val"); next };
#if ($key eq "am") {fhem("setreading $dev bat $val"); next };
$ret->{$key}=$val;
}
return $ret;
}
Zitat von: AlexMuc am 14 Juni 2025, 18:39:22Hallo Joachim,
ja, bin ich inzwischen. Ich mag aber noch kein Beispiel posten weil da fehlt einfach noch zuviel und bei dem was da ist, da bin ich auch nicht sicher, ob das alles so elegant ist.
Prinzipiell geht das aber, ich denke, deine Venus kann kommen wenn die deine Wünsche erfüllt :-)
Habe gehört, dass die Venus doch kein mqtt hat.
Antwort des Supports
Zitat"...vielen Dank für Ihre Nachricht. Derzeit ist der MQTT-Zugang ausschließlich für B2500-Geräte freigegeben. Für den Venus E steht diese Schnittstelle aktuell nicht zur Verfügung, da wir an der Optimierung unserer Sicherheitsmechanismen arbeiten.
Sollte sich in Zukunft etwas am Funktionsumfang ändern und der MQTT-Zugang für den Venus E freigegeben werden, informieren wir unsere Kunden selbstverständlich umgehend.
Vielen Dank für Ihr Verständnis."
Hallo Joachim,
höre dich doch mal dort https://www.photovoltaikforum.com/board/156-pv-anlage-ohne-eeg-balkonkraftwerke/ um. Ich meine, dort war auch die Venus im bei den MQTT Geschichten dabei.
Offiziell ist MQTT wohl nur beim Jupiter freigegeben. Beim B2500 aka Saturn und baugleichen kann man MQTT über ein Webtool von tomquist einschalten. Der macht auch etliche weitere Tools die sehr nützlich sind :-)
Hallo zusammen,
Kann man eigentlich der Funktion bei der Readinglist auch als 3. Parameter den vorher gesendeten Befehl mitgeben. Anschließend steht ja in State der Befehl aus dem Menü, aber ich brauch den schon bei der Auswertung.
Es sieht nämlich so aus, als ob Marstek bei den Rückgabewerten je nach Befehl die gleichen Kürzel, aber mit unterschiedlicher Bedeutung verwendet.
ZitatKann man eigentlich der Funktion bei der Readinglist auch als 3. Parameter den vorher gesendeten Befehl mitgeben.
set in MQTT2_DEVICE setzt das state Reading, und das kann man mit ReadingsVal($devName,"$state","") abfragen.
Das STATE Internal (das was angezeigt wird) kann man mit Value($devName) abfragen, aber das kann auch was anderes sein, wenn man stateFormat gesetzt hat.
Etwas offtopic: gibt es einen Grund, warum man im obigen Beispiel die Readings einzeln per setreading setzt?
Das ist ziemlich CPU-Intensiv, ich wuerde eher sowas vorschlagen:
sub
splitCD01($$)
{
my ($dev, $answer) = @_;
my $ret = {};
my %map = (
p1=>"batStatePV1",
p2=>"batStatePV2",
o1=>"batStateOut1",
o2=>"batStateOut2",
...
);
for my $element (split m{,}x, $answer) {
my ($key, $val) = split m{=}x, $element;
$ret{$map{$key}} = $val if($map{$key});
}
return $ret;
}
(ungetestet)
Hallo Rudi,
der Grund: als jemand ohne Ahnung war es der einfachste Weg für mich und es funktionierte:-) Ich werde aber deinen Vorschlag übernehmen den der ist garantiert besser als meine ,,hau drauf Lösung".
Aber eine Frage hab ich dazu doch noch. Bei meiner Vorgehensweise hatte noch vor, einige Werte per Funktion zB 0/1 in off/on umzuwandeln. Kann ich dann anstatt
o2=>"batStateOut2",
einfach myFunc( o2,"off","on","Bypass on")=> "batStateOut2"
schreiben wenn $val im Bereich von 0 bis 2 ist?
Hallo Rudi,
du schriebst ungetestet und prompt kommt bei mir der Fehler
Global symbol "%ret" requires explicit package name (did you forget to declare "my %ret"?) at ./FHEM/99_myUtils_B2500.pm line 35.
Damit andere nicht blind in den gleichen Fehler laufen, hier die Korrektur:
Korrekt muß in der Schleife die Zeile
$ret{$map{$key}} = $val if($map{$key});
lauten
$ret[b]->[/b]{ $map{$key}} = $val if ($map{ $key});
Auf jeden Fall ist die Funktion jetzt deutlich übersichtlicher.
Ich bin gespannt, ob ich eine Lösung zu Umschreibung diverser Werte herausbekomme. Meine Perlkentnisse beziehe ich nämlich zu 90% aus google :-)
ZitatIch bin gespannt, ob ich eine Lösung zu Umschreibung diverser Werte herausbekomme. Meine Perlkentnisse beziehe ich nämlich zu 90% aus google :-)
Bei sowas sind die LLMs relativ gut.
Frage ist ob man das Ergebnis im Problemfall fixen kann.
Hier ist dafuer eine moegliche Loesung, ohne LLM erstellt:
sub
splitCD01($$)
{
my ($dev, $answer) = @_;
my %map = (
p1=>"batStatePV1",
p2=>"batStatePV2",
o1=>"batStateOut1",
o2=>{n=>"batStateOut2",v=>["off","on","Bypass on"]}
);
my %ret;
for my $el (split(m/,/, $answer)) {
my ($key, $val) = split(m/=/, $el);
my $m = $map{$key};
if($m) {
if(ref($m) eq "HASH") {
$ret{$m->{n}} = defined($m->{v}[$val]) ? $m->{v}[$val] : $val;
} else {
$ret{$m} = $val;
}
} else {
$ret{$key} = $val;
}
}
return \%ret;
}
Oh weh, ich verstehe nur Bahnhof... :-)
Mal sehen, ob ich das umgesetzt kriege. Das mit den LLMs ist ja so eine Sache, auch da muß man wissen was man fragen soll. Und das möglichst genau. Aber wenn dann was nicht paßt, dann fehlt mir das Wissen um das zu verstehen.
Daher hier meine vorläufige aktuelle Version die zumindest schon mal tut, was sie soll:
# splitCD01($EVENT)
sub
splitCD01($$)
{
my ($dev, $answer) = @_;
my $ret = {};
my $i = 0;
my %map;
my ($key, $val);
my $element;
my $myCmd = ReadingsVal( $dev,"state","");
fhem("setreading $dev myCmd $myCmd");
#Log3( undef, 2,"--->: myCmd: $myCmd ");
if ($myCmd eq "Info") {
# cd = 01
%map = (
p1 => "batStatePV1", p2 => "batStatePV2",
w1 => "batPowerPV1", w2 => "batPowerPV2",
o1 => "batStateOut1", o2 => "batStateOut2",
g1 => "batPowerOut1", g2 => "batPowerOut2",
kn => "batEnergy_kWh",
pe => "batEnergy_perc",
do => "batDoD",
cs => "batChargeMode", # chargeDischargeSimultaneously or chargeThenDischarge
cd => "batDischargeMode",
md => "batDischargeState",
d1 => "batDischargePlan1State", e1 => "batDischargePlan1Start", f1 => "batDischargePlan1End", h1 => "batDischargePlan1Value",
d2 => "batDischargePlan2State", e2 => "batDischargePlan2Start", f2 => "batDischargePlan2End", h2 => "batDischargePlan2Value",
d3 => "batDischargePlan3State", e3 => "batDischargePlan3Start", f3 => "batDischargePlan3End", h3 => "batDischargePlan3Value",
d4 => "batDischargePlan4State", e4 => "batDischargePlan4Start", f4 => "batDischargePlan4End", h4 => "batDischargePlan4Value",
d5 => "batDischargePlan5State", e5 => "batDischargePlan5Start", f5 => "batDischargePlan5End", h5 => "batDischargePlan5Value",
vv => "batFirmwareMain",
sv => "batFirmwareSub",
fc => "batFirmwareFC4VersionNumber",
id => "batDeviceID",
uv => "batBootloaderVersion",
tl => "batTempLow", th => "batTempHigh",
# Temperaturalarm on/off = 0/1
Hallo AlexMuc,
wie hast du deinen Speicher in Fhem angebunden?
Ich habe mit diesem Tool (https://tomquist.github.io/hame-relay/b2500.html) über das Smartphone Bluetooth verbunden und die MQTT Werte eingegeben. In dem Tool wird auch verbunden angezeigt.
Ich dachte, daß dann über den MQTT-Broker automatisch ein Device angelegt wird und die Werte abgerufen werden. Ist aber nicht.
Dann habe ich mir mit hm2mqtt (https://github.com/tomquist/hm2mqtt) mit der manuellen Installation das git laut Beschreibung installiert. Bei "npm run build" gibt es eine Fehlermeldung "sh: 1: tsc: not found".
Ich habe einen RaspiB mit Raspbian. Alle Aktualisierungen habe ich durchgeführt.
Wie hast du das gemacht, daß die MQTT-Werte in Fhem reinkommen?
(hier habe ich ein voriges Fehlerprotokoll gelöscht)
Oder bin ich auf dem Holzweg und die Batterie muß über Bluetooth (https://www.photovoltaikforum.com/thread/232408-b2500-bluepalm-be-cool-marstek-etc-mqtt-aktivierung-und-smarthome-einbindung/?postID=4315693#post4315693) mit dem Fhem-Server verbunden werden? Ich dachte, wenn ich die MQTT-Server Infos eintrage, läuft das über WLAN. In der Fritzbox habe ich den Speicher als WLAN-Gerät eingetragen, allerdings wird es als inaktiv angezeigt.
Ich hab das device komplett ,,zu Fuß" angelegt weil ich kein aus meiner Sicht passendes Template gefunden habe und auch keine wirkliche Ahnung hab.
Inzwischen habe ich dort noch einiges ergänzt aber prinzipiell kannst du ,,einfach" das von mir gepostete Listing als Starter übernehmen. Beim Topic mußt du halt die MAC ergänzen, die dir bei der MQTT Freischaltung angezeigt wurde.
Damit hat es ,,sofort" funktioniert und es wurde die Daten vom Speicher 1x pro Minute abgeholt.
So, hier der 2. Versuch, jetzt mit der kompletten Funktion. Immer noch ohne den letzten Vorschlag von Rudi...
sub
splitCD01($$)
{
my ($dev, $answer) = @_;
my $ret = {};
my $i = 0;
my %map;
my ($key, $val);
my $element;
my $myCmd = ReadingsVal( $dev,"state","");
fhem("setreading $dev myCmd $myCmd");
#Log3( undef, 2,"--->: myCmd: $myCmd ");
if ($myCmd eq "Info") {
# cd = 01
%map = (
p1 => "batStatePV1", p2 => "batStatePV2",
w1 => "batPowerPV1", w2 => "batPowerPV2",
o1 => "batStateOut1", o2 => "batStateOut2",
g1 => "batPowerOut1", g2 => "batPowerOut2",
kn => "batEnergy_kWh",
pe => "batEnergy_perc",
do => "batDoD",
cs => "batChargeMode", # chargeDischargeSimultaneously or chargeThenDischarge
cd => "batDischargeMode",
md => "batDischargeState",
d1 => "batDischargePlan1State", e1 => "batDischargePlan1Start", f1 => "batDischargePlan1End", h1 => "batDischargePlan1Value",
d2 => "batDischargePlan2State", e2 => "batDischargePlan2Start", f2 => "batDischargePlan2End", h2 => "batDischargePlan2Value",
d3 => "batDischargePlan3State", e3 => "batDischargePlan3Start", f3 => "batDischargePlan3End", h3 => "batDischargePlan3Value",
d4 => "batDischargePlan4State", e4 => "batDischargePlan4Start", f4 => "batDischargePlan4End", h4 => "batDischargePlan4Value",
d5 => "batDischargePlan5State", e5 => "batDischargePlan5Start", f5 => "batDischargePlan5End", h5 => "batDischargePlan5Value",
vv => "batFirmwareMain",
sv => "batFirmwareSub",
fc => "batFirmwareFC4VersionNumber",
id => "batDeviceID",
uv => "batBootloaderVersion",
tl => "batTempLow", th => "batTempHigh",
# Temperaturalarm on/off = 0/1
tc => "batTempAlarmCharging",
tf => "batTempAlarmDischarging",
tc_dis => "batTempDischarging",
a0 => "batCapacityHost",
a1 => "batCapacityExtraBat1",
a2 => "batCapacityExtraBat2",
b1 => "batExtraBatConnected1",
b2 => "batExtraBatConnected2",
# readonly bzw nur über Zeitplan?
lv => "batOutputThreshold",
# for Smartmeter
c0 => "batCtHostChannel",
c1 => "batCtHostStatus",
sg => "batSMConnected",
sp => "batSMAutoPowerSize",
st => "batPowerTransmitted",
m0 => "batSMClip_1", m1 => "batSMClip_2", m2 => "batSMClip_3",
m3 => "batPowerOfInverter",
# Tageswerte
bc => "_energy_CurrentDay_Charge", # Summe Batterie Ladung war batEnergyTotal_Charge, batEnergyTotal
bs => "_energy_CurrentDay_Discharge", # Summe Batterie Entladung war batEnergyTotal_Out
pt => "_energy_CurrentDay_PV", # Summe PV-Leistung
it => "_energy_CurrentDay_Inverter", # Summe an Wechselrichter
lmf => "batEnergyLimiting_InOut",
lmi => "batEnergyRated_In", # Summe xxx
lmo => "batEnergyRated_Out", # Summe yyy
cj => "batScene",
# Batterie lädt / entlädt
l0 => "batSignPos_Host",
l1 => "batSignPos_Ex1_Ex2",
# unknown
am => "batX_am",
ct_t => "batX_ct_t",
am => "batX_bn",
sm => "batX_sm"
);
$ret = {};
# kn => "batEnergy_kWh",
# it => "batEnergyTotal_Inverter"
for $element (split m{,}x, $answer) {
($key, $val) = split m{=}x, $element;
if ($key eq "kn") {$val = $val / 1000}
elsif ($key eq "it") {$val = $val / 1000}
elsif ($key eq "bc") {$val = $val / 1000}
elsif ($key eq "bs") {$val = $val / 1000}
elsif ($key eq "pt") {$val = $val / 1000}
elsif ($key eq "lmi") {$val = $val / 1000}
elsif ($key eq "lmo") {$val = $val / 1000}
$ret->{ $map{$key} } = $val if ($map{ $key} );
};
} elsif ($myCmd eq "Info_Voltage_Cells") {
# cd = 13
%map = (
# .e & .f immer 0 ?
a0 => "cellVoltage_a0", a1 => "cellVoltage_a1", a2 => "cellVoltage_a2", a3 => "cellVoltage_a3", a4 => "cellVoltage_a4", a5 => "cellVoltage_a5", a6 => "cellVoltage_a6", a7 => "cellVoltage_a7", a8 => "cellVoltage_a8", a9 => "cellVoltage_a9",
aa => "cellVoltage_aa", ab => "cellVoltage_ab", ac => "cellVoltage_ac", ad => "cellVoltage_ad", ae => "cellVoltage_ae", af => "cellVoltage_af",
b0 => "cellVoltage_b0", b1 => "cellVoltage_b1", b2 => "cellVoltage_b2", b3 => "cellVoltage_b3", b4 => "cellVoltage_b4", b5 => "cellVoltage_b5", b6 => "cellVoltage_b6", b7 => "cellVoltage_b7", b8 => "cellVoltage_b8", b9 => "cellVoltage_b9",
ba => "cellVoltage_ba", bb => "cellVoltage_bb", bc => "cellVoltage_bc", bd => "cellVoltage_bd", be => "cellVoltage_be", bf => "cellVoltage_bf",
c0 => "cellVoltage_c0", c1 => "cellVoltage_c1", c2 => "cellVoltage_c2", c3 => "cellVoltage_c3", c4 => "cellVoltage_c4", c5 => "cellVoltage_c5", c6 => "cellVoltage_c6", c7 => "cellVoltage_c7", c8 => "cellVoltage_c8", c9 => "cellVoltage_c9",
ca => "cellVoltage_ca", cb => "cellVoltage_cb", cc => "cellVoltage_cc", cd => "cellVoltage_cd", ce => "cellVoltage_ce", cf => "cellVoltage_cf"
);
$ret = {};
for $element (split m{,}x, $answer) {
($key, $val) = split m{=}x, $element;
$ret->{ $map{$key} } = $val if ($map{ $key} );
};
} elsif ($myCmd eq "Info_xxx") {
# cd = 14
%map = (
# .e & .f immer 0 ?
ds => "xxx_ds",
ps => "xxx_ps",
ch => "xxx_ch",
as => "xxx_as",
e0 => "xxx_e0",
e1 => "xxx_e1",
op => "xxx_op",
cp => "xxx_cp",
cr => "xxx_cr",
c0 => "xxx_c0",
c1 => "xxx_c1",
c2 => "xxx_c2",
g1 => "xxx_g1",
g2 => "xxx_g2"
);
$ret = {};
for $element (split m{,}x, $answer) {
($key, $val) = split m{=}x, $element;
$ret->{ $map{$key} } = $val if ($map{ $key} );
};
} elsif ($myCmd eq "Info_Voltage_PV") {
# cd = 16
%map = (
# .e & .f immer 0 ?
g1 => "xxx_g1",
g2 => "xxx_g2"
);
$ret = {};
for $element (split m{,}x, $answer) {
($key, $val) = split m{=}x, $element;
$ret->{ $map{$key} } = $val if ($map{ $key} );
};
}
return $ret;
}
Danke für das Teilen der kompletten Funktion.
Hab mal noch eine Stelle etwas optimiert.
Aus:
if ($key eq "kn") {$val = $val / 1000}
elsif ($key eq "it") {$val = $val / 1000}
elsif ($key eq "bc") {$val = $val / 1000}
elsif ($key eq "bs") {$val = $val / 1000}
elsif ($key eq "pt") {$val = $val / 1000}
elsif ($key eq "lmi") {$val = $val / 1000}
elsif ($key eq "lmo") {$val = $val / 1000}
Wurde:
$val = $val/1000 if ($key =~ /^(kn|it|bc|bs|pt|lmi|lmo)$/);
Gruß
Dan
Bei mir scheint sich der Speicher nicht mit dem MQTT-Server zu verbinden.
Auf der Tomquist-Seite wird der Speicher als connected und die MQTT-Daten angezeigt. Im dortigen Monitor ist die version=106.2. Das MQTT-Passwort habe ich nochmals mit einem Shellyplug verifiziert (dachte schon, daß ich das evtl. mal geändert hatte).
Den Event-Monitor im Fhem Device hatte ich zu laufen. Nur die set-Anfrage wird dort aufgeführt.
Daher nochmal die Frage: Speicher und Fhem sollen sich über WLAN per MQTT verbinden? Oder läuft alles über Bluetooth, dh. ich müßte einen BT-Stick an den Raspi anschließen?
In der Fritzbox habe ich die auf der Tomquist-Seite angezeigte MAC-Adresse freigeschaltet. Es wird aber keine zusätzliche IP-Adresse angezeigt.
Hier noch meine Device Definition. Bei MAC steht meine Adresse drin. Als sub habe ich das von heute von dir und Dan gepostete in 99_myutils.pm eingefügt.
defmod MQTT2_DVES_HMJ2 MQTT2_DEVICE HMJ_2
attr MQTT2_DVES_HMJ2 IODev myBroker
attr MQTT2_DVES_HMJ2 comment Eingerichtet nach https://forum.fhem.de/index.php?msg=1343327\
MQTT Aktivierung der Batterie durch https://tomquist.github.io/hame-relay/b2500.html
attr MQTT2_DVES_HMJ2 devicetopic hame_energy/HMJ-2/App/MAC/ctrl
attr MQTT2_DVES_HMJ2 event-on-change-reading .*
attr MQTT2_DVES_HMJ2 icon batterie
attr MQTT2_DVES_HMJ2 periodicCmd info:1
attr MQTT2_DVES_HMJ2 readingList HMJ_2:hame_energy/HMJ-2/device/MAC/ctrl:.* {splitCD01( $NAME, $EVENT)}\
HMJ_2:hame_energy/HMJ-2/App/MAC/ctrl:.* ctrl
attr MQTT2_DVES_HMJ2 room MQTT2_DEVICE
attr MQTT2_DVES_HMJ2 setList info:noArg $DEVICETOPIC cd=01\
plan1_400:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=400\
plan1_600:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=600\
plan1_700:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=700\
plan1_800:noArg $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=800\
batDoD:slider,0,5,100 $DEVICETOPIC cd=05,md=$EVTPART1\
planx:slider,0,5,100 $DEVICETOPIC cd=20,md=0,a1=0,b1=00:01,e1=23:56,v1=$EVTPART1
attr MQTT2_DVES_HMJ2 stateFormat {\
my $tempLow = ReadingsNum( "$name","batTempLow","—-");;\
my $tempHigh = ReadingsNum( "$name","batTempHigh","—-");;\
my $temp = int( ($tempLow + $tempHigh)/2);;\
my $tempCol;;\
if ($tempLow < 7) {$tempCol = "blue"}\
elsif ($tempHigh > 28) {$tempCol = "red"}\
else {$tempCol = "black"};;\
\
sprintf( qq{<div style="text-align: right;;">\\
in: <b>%.0f W</b> ∑<b>%.3f kWh</b>, \\
out: <b>%.0f W</b>, \\
Akku: <b>%.3f kWh</b> (<b>%d %%</b>), \\
<font color="$tempCol"><b>%.0f °C</b></font>\\
</div>}\
, ReadingsNum( "$name","batPowerPVin",0)\
, ReadingsNum( "$name","batEnergyTotal_PV",0) /1000\
, ReadingsNum( "$name","batPowerOut",0)\
, ReadingsNum( "$name","batEnergy_kWh",0) /1000\
, ReadingsNum( "$name","batEnergy_perc","—-")\
, $temp )\
\
}
attr MQTT2_DVES_HMJ2 userReadings batPowerPVin:batPowerPV2.* {\
ReadingsVal( $name, "batPowerPV1", 0)\
+ ReadingsVal( $name, "batPowerPV2", 0)\
},\
batPowerOut:batPowerOut2.* {\
ReadingsVal( $name, "batPowerOut1", 0)\
+ ReadingsVal( $name, "batPowerOut2", 0)\
},\
batFirmware:batFirmwareMain.* {\
sprintf( "%d.%d",\
ReadingsVal( $name, "batFirmwareMain", 0),\
ReadingsVal( $name, "batFirmwareSub", 0)\
)\
}
attr MQTT2_DVES_HMJ2 verbose 2
setstate MQTT2_DVES_HMJ2 <div style="text-align: right;;">\
in: <b>0 W</b> ∑<b>0.000 kWh</b>, \
out: <b>0 W</b>, \
Akku: <b>0.000 kWh</b> (<b>0 %</b>), \
<font color="blue"><b>0 °C</b></font>\
</div>
Ich hab da noch einen _ in der defmod Zeile, also HMJ_2_
Wobei ich keine Ahnung habe, wofür der Parameter da steht ;-)
Danke an DeeSP für die Optimierung.
@AlexMuc: Das bei mir der zweite Unterstrich fehlt, ist mir schon bewußt. An den Stellen, wo das in einer Definition steht (zB. bei readingslist) habe ich es angepaßt. Ich meine, das ist ein frei definierbarer Name, könnte also auch B2500 heißen.
Was meine obige Frage war, ist ob die Batterie über Bluetooth mit dem MQTT-Server kommuniziert oder über WLAN. Meiner Meinung nach ist Bluetooth nur zum Einstellen der MQTT-Daten notwendig, danach müßte es über WLAN laufen. Ich stecke da aber nicht so tief in den Abläufen drin, sondern bin nur Anwender.
Über deine Definition des Devices und Sub habe ich nur gestaunt. Das hätte ich nie zusammenbekommen, zumal mir Programmierkenntnisse fehlen. Respekt und großen Dank dafür.
Ok, wenn da nur ein Name steht, werde ich das bei mir mal mit was anderem testen :-)
Zur Kommunikation: der Speicher wird zu erst mit der App über Bluetooth konfiguriert. wlan nur 2,4GHz, Passwort nicht zu lang, Wlan-Name auch erstmal mit was einfachem testen...
Anschließen sollte der Speicher im Router sichtbar sein und eine IP haben. In der App sollten BT und WLAN grün sein. Die Kommunikation per MQTT aus Fhem findet dann nur noch über WLAN statt.
Ich wollte die App nicht verwenden, um unabhängig davon zu sein. So hatte ich auch die github Seite von tomquist verstanden. Dort ist mit dem Tool (https://tomquist.github.io/hame-relay/b2500.html) der Zugang über BT zur Batterie möglich und man kann die MQTT-Daten eingeben. Diese bleiben auch nach einem Neustart in der Batterie erhalten.
Nur sehe ich dann keine Kommunikation zu meinem MQTT-Server in Fhem. Und im WLAN taucht sie auch nicht auf.
Wahrscheinlich ist dieses Programm (https://github.com/tomquist/hm2mqtt) auch noch notwendig. Ich habe bei der Installation aber einige Auffälligkeiten gehabt, so daß es noch nicht läuft. Und ich hatte gehofft, daß mit deiner MQTT-Anbindung in Fhem ich diesen Schritt übergehen kann.
Hallo fhemfatale,
setze den Speicher mal auf Werkseinstellungen zurück und fang von vorne an. Und bevor du irgendwas mit MQTT machst, konfiguriere ihn mit der App damit er im WLAN ist. Solange du ihn nicht in deinem Router siehst, wird das auch mit hm2mqtt nicht besser bei dir denn auch das geht nur über WLAN. Erst wenn die App dir das WLAN mit dem grünen Sybol anzeigt, solltest du mit dem Toolvon Tomquist MQTT konfigurieren. Und ab dann kannst du den Speicher aus FHEM steuern.
So, es hat jetzt geklappt, daß ich ihn in der App anmelden konnte. Er ist über WLAN im Gastnetz mit einem einfachen Kennwort angemeldet.Die Einbindung in Fhem wird dann irgendwann später erfolgen, wenn ich einige Erfahrung zu den besten Einstellungen für mich gesammelt habe. Da werde ich mich sicherlich nochmal melden, wenn es Fragen gibt.
Nochmal zusammengefaßt, was in meinem Fall ging/nicht ging. Auch wenn das zum eigentlichen Thread-Thema OT ist.
Die Anmeldung in der App ist notwendig. Ein direkter Zugriff über andere Programme ist erst danach möglich.
Die Marstek App konnte keine BT-Verbindung herstellen, nur mit der Power App funktionierte es. Danach sollte auch nur noch diese App verwendet werden, da sonst nicht-konfigurierte Einstellungen aus der Marstek App in den Batteriespeicher geschrieben werden, bzw. vorige überschrieben werden.
Nachdem man den Zugriff über BT hat, muß die WLAN Verbindung eingerichtet werden. Manche Einstellungen in der App sind kurioserweise später wieder nicht da und man muß neu konfigurieren (ging mir beim DOD und Zeitplan so).