Zendure Solarflow in Fhem via MQTT einbinden

Begonnen von Reinhart, 15 Februar 2024, 17:29:53

Vorheriges Thema - Nächstes Thema

Reinhart

Ich habe vor wenigen Tagen meinen Zendure Solarflow Akkuspeicher bekommen und mir einmal die Sache mit dem externen MQTT Server von Zendure angesehen.
In den letzten 2-3 Tagen habe ich dazu etwas näher befasst und teilweise mit Try und Error mich an die richtige Vorgangsweise heran getastet, aber diese Definition erschien mir am einfachsten.

Damit man hier an die erforderlichen Readings des "Zendure Broker" ran kommt, sind folgende Daten zur Abfrage in der Clientdefinition notwendig:
appkey = Username
secret = Password
clientID = Seriennummer Hub
subscriptions = topic/#


Topic = Username

wie man ganz schnell an die Keys kommt ist hier beschrieben. Voraussetzung natürlich das ihr bereits die App von Zendure eingerichtet habt. 

Also App auf "Global" stellen und unter Windows (Cmd) folgenden Befehl absetzen.
curl -i -v --json "{'snNumber': 'EureHubSeriennummer', 'account': 'EureEmailadresse'}" https://app.zendure.tech/v2/developer/api/apply

Nachdem ihr die Keys erhalten habt, empfiehlt es sich einen MQTT-Explorer (Windows) zu installieren (obiger Link) und man kann die gewonnen Zugangsdaten sofort überprüfen und seht auch gleich Readings die da ankommen.
Nun steht nichts mehr im Wege und es kann ein MQTT2-Client nach folgendem Muster angelegt werden. Ersetzt die beiden Platzhalter <appKey> und <Ser.Nr.Hub>
mit euren Daten. Anschließend bitte mit "set ZendureCloud password" (links oben in der Befehlszeile) den "secret" eingeben (nicht eurer Password das ihr in der App angelegt habt).


MQTT2 Client definieren

define ZendureCloud MQTT2_CLIENT mqtt.zen-iot.com:1883
attr ZendureCloud autocreate complex
attr ZendureCloud clientId <Ser.Nr.Hub>
attr ZendureCloud rawEvents .*
attr ZendureCloud room zendure
attr ZendureCloud username <appKey>
attr ZendureCloud verbose 5

Der Client sollte nun unter STATE "opened" anzeigen, Wenn nicht, ist irgendwas mit den Zugangsdaten falsch gelaufen.
Wurde der MQTT2 Client auf "autocreate complex" gestellt sollte innerhalb weniger Sekunden die ersten Readings auftauchen. Wenn keine Änderungen am HUB sind (Abendstunden)
kann das durchaus länger dauern. Einfach dazu parallel im MQTT-Explorer vergleichen.

Wenn alles geklappt hat sollte folgender Define automatisch durch Autocreate angelegt.

define MQTT2_ZendureHub MQTT2_DEVICE <Ser.Nr.Hub>
attr MQTT2_ZendureHub icon mqtt_bridge_2
attr MQTT2_ZendureHub readingList <Ser.Nr.Hub>:<appKey>/<Client Topic>/state:.* { json2nameValue($EVENT) }\
attr MQTT2_ZendureHub room MQTT2_DEVICE,zendure
attr MQTT2_ZendureHub stateFormat Speicher-AB2000: electricLevel

und hier noch die grafische Auswertung einiger Readings so wie ich sie einmal definiert habe.

define Zendure_Akku DOIF ##
attr Zendure_Akku room zendure
attr Zendure_Akku uiTable {package ui_Table}\
cylinder(" ",0,100,"%",100,110,140,0,[MQTT2_ZendureHub:electricLevel],80,undef)|\
card([MQTT2_ZendureHub:electricLevel:col8],"AB2000 1/2","sani_solar\@colorVal1",0,400,180,0,"%",undef,0,180)\
\
card([MQTT2_ZendureHub:solarPower1:col8],"Panel-1/2","sani_solar\@colorVal1",0,400,180,0,"Watt",undef,0,180)|\
card([MQTT2_ZendureHub:solarPower2:col8],"Panel-3","sani_solar\@colorVal1",0,400,180,0,"Watt",undef,0,180)\
\
card([MQTT2_ZendureHub:outputPackPower:col8],"Ausgang Akku","sani_solar\@colorVal1",0,400,180,0,"Watt",undef,0,180)|\
card([MQTT2_ZendureHub:outputHomePower:col8],"Wechselrichter","sani_solar\@colorVal1",0,400,180,0,"Watt",undef,0,180)|\

Viel Erfolg mit dem Solarflow!

edit 08.03: Topic unter subscriptions hinzugefügt.


FHEM auf Raspy4 mit Bullseye + SSD, Homematic, ESP8266, ESP32, Sonoff, eBus, NanoCUL, MapleCUL, , MQTT2, Alexa

Reinhart

ich habe mich nun noch mit dem Schreiben von Werten via MQTT eingelesen, aber so wie es derzeit ausschaut ist die User API von Zendure "readonly". Zendure schreibt ja im Github dies unter Futures Plans.

ZitatSupport data downlink and device control.
.

Eigentlich wollte ich auch die Entnahme des Akkuspeichers selbst über Fhem steuern können, um zB. bei schlechter Sonneneinstrahlung des nächsten Tages (Wettervorschau Proplanta) den Akku nicht ganz zu entleeren. Meine Situation ist ja so, dass ich eine sehr hohe Grundlast habe und der 4Kw Akku ohnehin nicht für die Nacht ausreicht. Ob ich hier nochmals mit Kapazität aufstocken kann muss sich in den nächsten Monaten zeigen ob der Sonnenertrag ausreicht um mehr als 4 Kw am Tag zu laden. Der neue HUB von Zendure sollte das ja können, aber da war ich mit dem Kauf zu schnell. Habe aber jetzt schon zwei Panels über Dioden zusammen geschalten und so insgesamt 3 Panels mit je 415 Watt alleine zum Speichern zur Verfügung.
Zendure ist aber eh sehr zackig und erweitert seine Firmware ständig, also noch etwas warten und dann klappt auch das Senden zu ihrem MQTT Server.

Dafür habe ich heute noch schnell meinen Floorplan um die gewonnen Daten ergänzt.
FHEM auf Raspy4 mit Bullseye + SSD, Homematic, ESP8266, ESP32, Sonoff, eBus, NanoCUL, MapleCUL, , MQTT2, Alexa

mkriegl

Hallo Reinhard,

danke schon mal für die Devines, allerdings habe ich so meine Probleme Informationen zu empfangen. Er connected, aber ich bekomme gar nichts zurück,  obwohl heute die Sonne schien.
In Home Assistant hat es bei mir einwandfrei funktioniert, ich bekomme aber weder in FHEM noch in MQTT Explorer Informationen.

Im Vergleich zu deiner Beschreibung musste ich EU statt V2 abfragen, da es mir einen Fehler liefert.
curl -i -v --json "{'snNumber': 'EureHubSeriennummer', 'account': 'EureEmailadresse'}" https://app.zendure.tech/eu/developer/api/apply
In HASS, MQTT Explorer und FHEM sind Server, Port, username, Passwort alle eins zu ein (plus clientId bei FHEM)
Das einzige was ich mir jetzt noch vorstellen kann ist, das nur ein Gerät verbunden sein kann. Ansonsten kann ich mir es nicht erklären

Gruß .. Max

Reinhart

was ich gelesen habe funktioniert es nur mit "global" Einstellung. Ich habe auch gleich bei der Einrichtung der App auf Global gestellt. Wenn du umstellst, ist die History aber weg!

Hast du denn den App Key mit der EU Einstellung und den Secerect mit "curl" bekommen?
FHEM auf Raspy4 mit Bullseye + SSD, Homematic, ESP8266, ESP32, Sonoff, eBus, NanoCUL, MapleCUL, , MQTT2, Alexa

Fhemotto

Hallo zusammen,
habe heute mein erstes Gerät mit MQTT eingebunden, ohne wirklich zu verstehen was da passiert.
Möchte nur kurz auf mein anfängliches Problem hinweisen.

In dem Link den du oben aufgeführt hast mit der Beschreibung steht unter anderen:

,,Unter Advanced (Button) müsst ihr dann noch euren appKey als Topic abonnieren, also als neue Subscription hinzufügen --> appKey/#."

Somit klappts bei mir auch im MQTT Explorer.

Da in FHEM aber trotz ,,STATE "opened" nichts ankam, habe ich alle möglichen Attribute mir angeschaut und hier das Attribut  ,,subscriptions" gefunden und auf appKey/# gesetzt
und sofort kamen Unmengen an Daten im Logfile sowie wurde auch das neue Device mit autocreate angelegt.

Übrigens habe ich die Abfrage mit  "EU"
curl -i -v --json "{'snNumber': 'EureHubSeriennummer', 'account': 'EureEmailadresse'}" https://app.zendure.tech/eu/developer/api/applygemacht

Eventuell solltest du diesen Hinweis oben mit angeben, damit andere nicht auch darüber stolpern,
wenn nichts ankommt.

Vielen Dank für die Beschreibung.




mkriegl

@Reinhard: Ja, genau, wie auch Fhemotto beschrieben hat
@Fhemotto: danke für den Tipp. Hätte ich doch mal genauer lesen sollen. Jetzt kommen bei mir auch Daten rein.

Meine defines habe ich zwar noch nicht gefunden, aber muss ich heute abend mal in Ruhe schauen. Danke

Reinhart

#6
Danke für den Hinweis, habe euch das in der Beschreibung einfach unterschlagen, habe den bei mir auch gesetzt gehabt.
Aber schön zu wissen, das auch in der Einstellung "EU" alles klappt.
Es gab ja vor wenigen Tagen ein Update, aber schade das noch nix gesendet werden kann.

Übrigens  ich habe für die Wintermonate vorgebaut und mir über einen Y-Adapter und 2 Dioden zur Entkopplung ein Netzteil mit 400 Watt angeschlossen das ich über Tasmota schalten kann. So kann ich bei Bedarf vor einer Tiefentladung nun Einspeisen und so bequem den Akku wieder zwischen 10-20% bringen.

Da ich ja insgesamt 4 Balkonkraftwerke mit je 4 Panele habe und eine Anlage mit drei Panele fix für den Akkubetrieb zum Laden verwende, kann ich nun bei schwachem Sonnenschein auch mit der überschüssigen Energie der 3 anderen Anlagen den Akku laden. Mit dieser Methode bin ich selbst im März ständig auf 80-96%. Bei Sonnenschein ist der 4KW Akku ohnehin schon um 13:00 Uhr voll. Das Netzteil ist regelbar, somit läßt sich die Leistung auch drosseln.
Zuviel Einspeisen kann man ja nicht, da der Solarflow bei mir die Leistung pro Eingang auf etwa 390 Watt begrenzt. siehe Bild2.
FHEM auf Raspy4 mit Bullseye + SSD, Homematic, ESP8266, ESP32, Sonoff, eBus, NanoCUL, MapleCUL, , MQTT2, Alexa

Olaf A

Moin zusammen ich habe das bei mir auch eingestellt und lief bis Sonntag Abend klasse. Seit 23 Uhr kommen jetzt keine Daten mehr habt ihr das auch beobachtet?
FHEM auf CubieTruck:
Max mit Cube, HMLAN; MAX-Thermostaten; Homematic-Komponenten, SIS PM Schalter, JeeLink.

mkriegl

Bei mir kamen seit gestern 17.6. 4h keine Daten mehr rein. Jetzt seit etwa 8h tröpfelt wieder was rein

Olaf A

FHEM auf CubieTruck:
Max mit Cube, HMLAN; MAX-Thermostaten; Homematic-Komponenten, SIS PM Schalter, JeeLink.

Blackcat

Hi,

hier ein Tipp für alle die offline Daten nutzen wollen.
Ich habe meine AIO ganz neu (seit diesem Wochenende) und über BT und folgendem Skript als MQTT Client eingebunden
https://github.com/reinhard-brandstaedter/solarflow-bt-manager

Die Daten kann man super auch loggen und anzeigen.
Aktuell stelle ich die Einspeisung noch manuell im Ahoy ein, soll aber noch automatisch erfolgen.

Eine schöne Fluss Grafik habe ich noch keine, aber da wollte ich mal das SolarForecast Module testen
Viele Grüße Sandra - FHEM Style Entwicklerin iOS6+12
-----
ZBox nano, Homematic, Homebridge, Hue + Mi Light, ZWave, Dyson, etc.
https://www.foodcat.de
https://www.youtube.com/c/FoodCat (hier gibt es auch immer mehr Hausautomatisierungsvideos)

RalfP

Hallo,

vielen Dank für die Informationen. Sie haben mir geholfen auf das MQTT von Zendure zuzugreifen.

Jetzt aber mal eine Frage: Habt ihr das Setzen des OutputLimit schon mal per publish via Zendure Cloud MMQTT hinbekommen? Laut der Daten, klingt es ja danach, das das möglich wäre.

config_command_topic
xxxxxxxx/xxxxxxxx/dcOutputPower/set

config_value_template
{{ value_json.dcOutputPower}}

Vielen Dank
grüße Ralf

RalfP

Hallo,

...also, das geht nicht. MQTT publish ist nicht von Zendure umgesetz, maximal ist es vorbereitet. Sofern hier nichts neues beschrieben wird, wird es nicht funktionieren.

Um trotzdem eine Regelung hinzubekommen, habe ich den Bypass auf immer aus gestellt, Grenzen entsprechend dem Umrichter gesetzt und regele jetzt die Leistungsbegrenzung des Umrichters. Der Zendure reagiert auch darauf und schiebt die überschüssige Energie in den Speicher.

Grüße
Ralf

dombar

Hallo,
Ich weiß nicht ob es nur bei mir so ist aber seit Samstag oder Sonntag wurden keine Werte mehr geliefert.
Es scheint als wenn Zendure den Servernamen geändert hat. Diese Adresse sollte funktionieren: mqtt-eu.zen-iot.com:1883
Gruß
Dominik
1x FB7490, 2x FBDECT200, 1x RPI als Öltankanzeige mit TEK603, 1x Synology NAS, 1xCUL FS20, 2x CCU3, 1xFS20DWT , 1x FS20 DI22-4, 1x FS20IR, 3x FS20ST, 1 x KS300, 3x HM-LC-Sw1PBU-FM, 6x HM-ES-PMSw1-Pl,  Siemens S7 CPU 315 für Stromzähler auf S0 Basis uvm.

mkriegl

Danke. Ich hatte schon länger Probleme mit aktuellen Daten. Unter deinem Link scheint das wesentlich besser zu sein.

Shadow3561

Moin,

ich versuche gerade meinen Hyper2000 ein zu binden.
Es klappt alles nur bekomme ich keine readings.

was muss ich bei
Zitat<Ser.Nr.Hub>:<appKey>/<Client Topic>/state:.* { json2nameValue($EVENT) }

<Client Topic>
einfügen?

Mit freundlichen Grüßen

Shadow3561

#16
Dann antworte ich mir mal selbst und stelle die Lösung hier rein, falls andere das gleiche Problem haben.
als erstes die erforderliche Daten besorgen

in OSX ein Terminal öffnen und folgendes eingeben


curl -H "Content-Type: application/json" -X POST -d '{"snNumber":"<Serial vom Hub oder Inverter>","account": "Username/email von der Zendure App>"}' https://app.zendure.tech/eu/developer/api/applymit Enter bestätigen,

Jetzt solltet ihr folgende Meldung bekommen
{"code":200,"success":true,"data":{"appKey":"xxxxxxxxxx","secret":"xxxxxxxxxxxx","mqttUrl":"mqtt-eu.zen-iot.com","port":1883},"msg":"Successful operation"}%
appKey und secret abspeichern, die benötigen wir noch.




MQTT2 Client definieren


defmod ZendureCloud MQTT2_CLIENT mqtt-eu.zen-iot.com:1883
attr ZendureCloud autocreate complex
attr ZendureCloud clientId <appKey>
attr ZendureCloud rawEvents .*
attr ZendureCloud room Zendure
attr ZendureCloud subscriptions <appKey>/#
attr ZendureCloud username <appKey>

danach ein
set ZendureCloud password <secret>
jetzt noch
set ZendureCloud connect
Nun sollte der state "opened" angezeigt werden.

jetzt ein neues Device anlegen

defmod MQTT2_ZendureHyper2000 MQTT2_DEVICE eCXh0pnS
attr MQTT2_ZendureHyper2000 icon mqtt_bridge_2
attr MQTT2_ZendureHyper2000 readingList <Serial vom Hub oder Inverter>:<appKey>/<appKey>/.* { json2nameValue($EVENT) }
attr MQTT2_ZendureHyper2000 room Zendure

Jetzt abwarten bis die readings erscheinen.

Hier noch ein paar Änderungen für stateFormat und userReading die ich vorgenommen habe.

attr MQTT2_ZendureHyper2000 stateFormat Akkustand: <span style='color:{(ReadingsNum("$name",'state_packData_1_socLevel','')>=50 ? "green":"orange")}'>[$name:state_packData_1_socLevel] %</span> <span style='color:{(ReadingsVal("$name",'Akku-be-endladen','on') eq "entlädt" ? "red":"green")}'>[$name:Akku-be-endladen] </span><br/>\
Akku-Restzeit: <span style='color:{(ReadingsNum("$name",'akku-remaining','')>=50 ? "green":"orange")}'>[$name:akku-remaining] </span><br/>\
PV-in: <span style='color:{(ReadingsNum("$name",'state_solarInputPower','')<=0 ? "red":"green")}'>[$name:state_solarInputPower] W</span>\

attr MQTT2_ZendureHyper2000 userReadings Akku-be-endladen {if(ReadingsVal($NAME,"state_packState","") eq "1") {return "lädt"} elsif (ReadingsVal($NAME,"state_packState","") eq "0") {return "standby"} elsif (ReadingsVal($NAME,"state_packState","") eq "2") {return "entlädt"} else {"prüfen"}},\
akku-remaining {if(ReadingsVal($NAME,"state_remainOutTime","") eq "59940") {return "∞"} elsif (ReadingsVal($NAME,"state_packState","") ne "59940") {return ( strftime('%T', gmtime(ReadingsNum($NAME, "state_remainOutTime", 0))) )}}
attr MQTT2_ZendureHyper2000 verbose 0

Mit freundlichen Grüßen


RalfP

Hallo,

habe mir mal verschiedene Lösungen angeschaut und den ersten Schritt für Fhem umgesetzt - Login und Token für einen MQTT Client

https://github.com/RP-Develop/Zendure

Ist noch nicht perfekt, hilft aber einen MQTT Client so zu konfigurieren, das er im Prinzip die Funktion der Zendure App übernimmt. Läuft seit einigen Tagen, ohne das ich den Token erneuern musste als Mosquitto Bridge. Output setzen funktioniert!

Bin am überlegen, ob ich einen eigenen MQTT Client integriere, um ein Token-Refresh besser hinzubekommen. Liegt aber noch in weiter Ferne. Mal sehen was ihr sagt.

Testen - natürlich auf eigene Gefahr und möglichst erst in einer Testinstanz von Fhem.

Achtung! Wenn jemand Logs oder Konfigurationen posten möchte, bitte Nutzernamen, Passwörter und deviceId's unkenntlich machen. Das Ganze ist ein POC und an mancher Stelle noch nicht ganz sicher.

Grüße Ralf

Shadow3561

#18
Moin,
Weil ich auf eine schnellere Aktualisierung der readings hoffe habe ich es mal probiert und bekomme leider keinen Login hin.

es sieht so aus:
define <name> MQTT2_CLIENT mqtteu.zen-iot.com:1883
set <name> password oK#*********
attr <name> username zenApp
attr <name> clientId *****:*******-***-****-***-*******
attr <name> autocreate no
attr <name> subscriptions

FHEM meckert bei "attr <name> subscriptions" weil kein Eintrag gemacht wird, also habe ich es erst mal weg gelassen.

Jedoch bekomme ich keinen connect hin.
Im Log steht
Connection refused, bad user name or password
Mit freundlichen Grüßen


RalfP

Hallo Shadow,

ja, das liegt daran, das du dich am EU Server in deiner App angemeldet hast. Der hat ein anderes Password. Es gab mal die Aussage, das der EU Server nicht richtig funktioniert, was ich damals auch in meiner App merkte. Darum hatte ich schon frühzeitig auf Global gewechselt. Und wie es so ist, habe ich alles darauf ausgelegt, sorry. Wenn du wechseln würdest, gehen dir alle bisherigen Daten verloren, so meine Kenntnis.

Bitte sei noch etwas geduldig. Habe gerade eine Lösung mit einer Anmeldung im MQTT Client am entwickeln. Ich versuche die unterschiedlichen Server gleich mit zu beachten.

Grüße Ralf

RalfP

Hallo,

hatte einen guten Tipp von Rudi bekommen, wie man das Attr connectFn im MQTT2_CLIENT benutzen kann, um den Client mit einem Login zu versehen. Schaut mal bei https://github.com/RP-Develop/Zendure vorbei.

Theoretisch hab ich alles beschrieben. Bei Fragen bitte melden.

@Shadow: Da ich nicht wieder auf einen EU Server wechseln kann, hätte ich natürlich gern ein Feedback, ob die eine, wie die andere, Variante mit dem EU Server überhaupt arbeitet. Vielen Dank

Interessant wären auch, ob mehr als ein Gerät angelegt wird, wenn jemand >1 Geräte in seiner App hat. Habe selbst nur ein HUB 2000.

Grüße Ralf

Shadow3561

Moin Ralf,
Ich bin auch auf den globalen Server gewechselt. Daher kann ich es mit der EU-Variante nicht probieren.

Dein Modul funktioniert wunderbar und die readings kommen schnell(schneller als bei der Variante ohne Modul) und zuverlässig.

Bei mir erscheint bei einem "get DeviceList" nur der Hyper2000. Der Schelly pro 3EM taucht nicht in der Liste auf.

Danke für deine tolle Arbeit.

Mit freundlichen Grüßen

RalfP

Hallo Shadow,

hört sich gut an, vielen Dank.

Einen Stromzähler Pro 3EM hab ich auch. Den habe ich aber lokal auf meinem Mosquitto MQTT eingebunden. Der sendet in keine Cloud (hätte ich mir für Zendure auch gewünscht). Auch wenn du ihn mit der Cloud verbunden hast und den CT-Mode (glaube so nannte sich das) arbeitest, hätte ich mich gewundert, wenn Zendure die Daten auf ihrem Server präsentiert.

Diese Regelung mache ich lokal bei mir mit Fhem. Hauptsächlich steuere ich derzeit den Umrichter je nach Verbrauch (Daten vom 3EM), um keine Energie ins Netz zu verschenken, sondern in die Batterie zu speichern. Mit den jetzigen Steuermöglichkeiten kann ich dan Ganze bestimmt nochmals optimieren und vor allem den HUB auf meine Einstellungen wieder setzen, wenn er mal aus war.

PS: lass mal hören, wie lange der Token bei dir gültig ist. Einen habe ich schon über eine Woche aktiv. Mir geht es darum, ob man ihn mal refreshen muss.

Grüße Ralf 

Shadow3561

Der Token sollte solange gültig sein bis sich ein anderes Gerät mit dem selben einloggt.
Wie steuerst du den Hyper 2000 mit FHEM?
Das würde mich brennend interessieren da die CT_Mode Steuerung nicht wirklich zuverlässig funktioniert.
Meine PV speist teilweise über Stunden ins Netz ein bevor der Hyper anfängt aus der Steckdose zu laden.
Genauso speist er den Überschüssigen Strom aus den angeschlossenen PV nicht ins Netz ein obwohl der Akku voll ist. Dann geht PV einfach auf 0 obwohl "ins Netz einspeisen" auf zugelassen steht.

Wenn du also deinen Code oder deine DEF zur Steuerung des Hyper bereitstellen würdest wäre ich dir sehr dankbar.

BTW
Was bewirken die Bypass und autoRecover Einstellungen in deinem Modul?

Mit freundlichen Grüßen

RalfP

#24
Hallo Shadow,

Bypass - ist unter den Einstellungen deines HUB in der Zendure App zu finden.

Bypass auto - der HUB regelt es selbst. Er soll erkennen wann die Batterie voll ist und dann alles weitere an Energie an den Umrichter geben. Mein Hoymiles (über AHOYDTU - MQTT angesteuert) hat in dieser Situation komplett auf gemacht und sämtliche Energie ins Netz geliefert. Das Ganze hat sich aber nicht wieder zurückgestellt und hat selbst Batterieenergie ins Netz gespeist. War für mich somit keine Option.
Bypass immer an - Die ganze Energie wird an den Umrichter geliefert.
Bypass immer aus - Wenn die Batterie voll ist und nichts abgenommen wird, werden die Eingänge der Paneele zu gemacht. Diese Funktion nutze ich.

Du darfst diesen Dateianhang nicht ansehen.

Standart ist auto, was sich leider auch nach einem ausgeschalteten HUB wieder setzt.

autoRecover ist der Schalter unter Bypass Schalter, der auf Bypass ein oder aus reagiert und den nächsten Tag den Bypass wieder auf auto schalten würde.

Da ich aber Bypass AUS und den autoRecover auch immer auf AUS haben möchte, hab ich Beides zum Steuern definiert.

Jetzt zu deiner anderen Frage, welche nicht mit wenig Erklärung zu erläutern ist.

Man kann im Allgemeinen dem Umrichter sagen, wieviel Energie er vom HUB abfordern soll oder man setzt den Output des HUB. Beides ist möglich. Wenn nur 100W gefordert werden (Umrichter auf 100W begrenzt oder Output HUB auf 100W gesetzt) aber die PV's 200W gerade liefert, gehen 100W in die Batterie. Bedeutet, wenn dein Haushalt gerade nur 100W verbraucht (ermitteln über Pro 3EM) musst du den Umrichter oder den HUB so einstellen, das er nur 90W oder 80W liefert, um nicht unter 0 zu kommen und etwas verschenkt wird. Der Rest geht automatisch in die Batterie.

Das Ganze habe ich in einem zyklisch ablaufenden Script behandelt. Das wird aller 2min aufgerufen. Dabei wird geprüft, welche Leistung gerade mein Haushalt benötigt. Ich regele nicht genau auf 0, das würde das System evtl. zu schnell machen und zum Überschwingen neigen. Darum lasse ich immer nur feste Schrittweiten zu (30W). Als unterer Grenze habe ich 20W festgelegt. Liege ich im Verbrauch über einem Bereich von 20W + 30W erhöhe ich den Umrichter um 30W, um wieder in Richtung 20W zu kommen. Nach 2min wird wieder nachgeschaut, liege ich immer noch höher, wird die Leistung am Umrichter um weitere 30W erhöht. Das ganze auch wieder anders herum, nur mit doppelter Schrittweite.

Das Ganze hat den Vorteil, das es nicht zu einem übermäßigen Überschwingen ins Negative kommt, wenn Verbraucher (z.B. Wasserkocher) eingeschaltet werden, die nur für kurze Zeit hohe Energie ziehen.

Du darfst diesen Dateianhang nicht ansehen.
Du darfst diesen Dateianhang nicht ansehen. 

Ich kann hier zwar mein Script dazu posten, es wird aber maximal nur als Anregung dienen, da du es nicht 1:1 verwenden kannst.

Derzeit steuere ich meinen Umrichter. Wenn du aber keine Schnittstelle zu deinem Umrichter hast, hättest du jetzt die Möglichkeit mit Zendure Fhem den Output vom HUB zu steuern und damit die Regelung aufzubauen.

...habe es eigentlich gut kommentiert, sonst würde ich selbst nicht mehr wissen, was ich da programmiert hab  ;)


+*00:02:00 {
    # ToDo
    #

    # Verbrauch
    my $total_act_power = ReadingsVal("WG.Energie","total_act_power",0);
   
    # Ausgangsleistung Inverter
    # Wenn Bypass an ist bzw. die Batterie voll und Schaltung auf Bypass auto steht,
    # wird die Limitierung des Inverters übergangen und alles von den Paneelen wird geliefert.
    # ToDo: Limit auf 100% dann...???
    my $P_AC = ReadingsVal("WG.Balkonkraftwerk","P_AC",0);
   
    # Batterie Status
    # 0    standbyBat
    # 1    loadBat (Laden)
    # 2 unloadBat (Enladen)   
    my $packState = ReadingsVal("WG.Balkonkraftwerk.HUB","packState",0);
    my $electricLevel = ReadingsVal("WG.Balkonkraftwerk.HUB","electricLevel",0);
    my $socSet = ReadingsVal("WG.Balkonkraftwerk.HUB","socSet",0) / 10;
    my $inverseMaxPower = ReadingsVal("WG.Balkonkraftwerk.HUB","inverseMaxPower",0);
   
    # Output Limit vom HUB
    my $outputLimit = ReadingsVal("WG.Balkonkraftwerk.HUB","outputLimit",0);
   
    # Reading Inverter available
    # 0    not available and not producing
    # 1    available but not producing
    # 2    available and producing
    # 3    available and was producing
    # 4    was available
    my $available = ReadingsVal("WG.Balkonkraftwerk.Inverter","available",0);

    # aktuelles Limit
    my $limit_act = ReadingsVal("WG.Balkonkraftwerk.Inverter","limit",0);
   
    # Default
    my $default = ReadingsVal("WG.Balkonkraftwerk.control","default",0);
   
    # Control
    my $controlLevel = ReadingsVal("WG.Balkonkraftwerk.control","controlLevel",20);
    my $controlStep = ReadingsVal("WG.Balkonkraftwerk.control","controlStep",50);
    my $controlFirstStart = ReadingsVal("WG.Balkonkraftwerk.control","controlFirstStart",0);
    my $controlBatteryLevel = ReadingsVal("WG.Balkonkraftwerk.control","controlBatteryLevel",20);
    my $controlBatteryLevelReached = ReadingsVal("WG.Balkonkraftwerk.control","controlBatteryLevelReached",20);
   

    # State
    # 0 keine Regelung
    # 1 in Regelung
    # 2 in Regelung, aber Begrenzung auf default, wegen Batterie unter 20%
    # 3 Inverter nicht verfügbar
    # 4 Limit noch nicht verarbeitet, Abbruch
    # 5 Sonderbetrieb weil Batterie voll oder Bypass geschaltet   
    my $controlState = ReadingsVal("WG.Balkonkraftwerk.control","controlState",0);
   
    # Regelung an, wenn Batterie voll ist == 1
    my $controlBatteryFull = ReadingsVal("WG.Balkonkraftwerk.control","controlBatteryFull",0);

    # Überwachung "set limit", derzeit nur Test und Log
    my $controlSetCount = ReadingsVal("WG.Balkonkraftwerk.control","controlSetCount",0);
   
    # Prüfung, ob Bypass auf "immer aus" steht, sonst setzen. Nach Reboot vom Hub ist sonst Automatik eingeschaltet
    my $controlBypass = ReadingsNum("WG.Balkonkraftwerk.control","controlBypass",0);
    my $passMode = ReadingsNum("WG.Balkonkraftwerk.HUB.global","report_properties_passMode",0);
    my $autoRecover = ReadingsNum("WG.Balkonkraftwerk.HUB.global","report_properties_autoRecover",0);
    if($controlBypass == 1){
        fhem("set WG.Balkonkraftwerk.HUB.global Bypass 1") if($passMode != 1);
        fhem("set WG.Balkonkraftwerk.HUB.global autoRecover 0") if($autoRecover != 0);
    }
   
    if($available == 2){

        # Abbruch, wenn das letzte Limmit noch verarbeitet wird
        unless($limit_act =~ m/set limit/){
            # Wenn letztes Limit verarbeitet wurde...
           
            # Zähler zurück auf 0
            fhem("set WG.Balkonkraftwerk.control controlSetCount 0");
           
            # Begrenzung bis Batterie Level einmal erreicht
            if(($electricLevel >= $controlBatteryLevel) && ($controlBatteryLevelReached == 0)){
                fhem("set WG.Balkonkraftwerk.control controlBatteryLevelReached 1");
                $controlBatteryLevelReached = 1;
            }
           
            # Umrechnung in Watt
            my $limit_watt = int(($limit_act * 600) / 100);


            # Grundzustand herstellen???
            # Inverter auf NULL ???
            # Nein, Wechselrichter startet mit 100% und wird dann runtergeregelt
           
            # Erster Start Limit wird auf default gesetzt

            if(($electricLevel < $socSet) || ($controlBatteryFull == 1)){
                # Wenn Batterie nicht voll ist, dann...

                if((ReadingsVal("WG.Balkonkraftwerk.control","state","off") eq "on") && ($controlFirstStart == 1)){
                    # wenn Regelung eingeschaltet und Inverter in Produktion, dann...

                    # Status setzen
                    $controlState = 1;

                    if($total_act_power > $controlLevel){
                        # sind es mehr als Step die ausgeregelt werden können?
                        if(($total_act_power - $controlLevel) > $controlStep){
                            # neuer Wert
                            $limit_watt = $limit_watt + $controlStep;

                            # Grenzen prüfen
                            ($limit_watt = $outputLimit)if($limit_watt > $outputLimit);

                            # Batterie unter Level und noch nicht drüber gewesen, dann begrenzen auf Default
                            if(($limit_watt > $default) && ($controlBatteryLevelReached == 0)){
                                $limit_watt = $default;
                               
                                # Status setzen
                                $controlState = 2;
                               
                            }
                        }

                        # nichts tun, ist gut eingestellt

                    }
                    else{
                        # neuer Wert, *2 um schneller wieder herunterzukommen, um nicht zu stark ins Minus zu kommen
                        $limit_watt = $limit_watt - ($controlStep * 2);

                        # Grenzen prüfen
                        ($limit_watt = 0)if($limit_watt < 0);
                    }
                }
                else{
                    # Wenn keine Regelung, dann Defaultwert aus Dummy
                    $limit_watt = $default;
                   
                    # Erster Start setzen
                    fhem("set WG.Balkonkraftwerk.control controlFirstStart 1") if($controlFirstStart == 0);

                    # Status setzen
                    $controlState = 0;
                }
            }
            else{
                # Wenn Batterie in Standby und voll, dann Limit auf 100% (max Inverterleistung im HUB)
                $limit_watt = $inverseMaxPower;  

                # Status setzen
                $controlState = 5;
            }

            # Umrechnung in Prozent
            my $limit_pct = int(($limit_watt * 100) / 600);

            # Wert setzen, wenn er ungleich zum Aktuellen ist und beim ersten Start
            if(($limit_act != $limit_pct) || ($controlFirstStart == 0)){
                fhem("set WG.Balkonkraftwerk.Inverter limit $limit_pct");
            }
        }
        else{
            # Wenn Limit noch verarbeitet wird nichts weiter tun
           
            # Zähler zu Kontrolle erhöhen
            $controlSetCount++;
            fhem("set WG.Balkonkraftwerk.control controlSetCount $controlSetCount");
            Log3 undef, 1, "Regelung: set limit count = ".$controlSetCount;
           
            # Status setzen
            $controlState = 4;
        }
    }
    else{
        # Wenn der Inverter nicht verfügbar ist nichts weiter tun
       
        # Batterie Level erreicht zurücksetzen
        fhem("set WG.Balkonkraftwerk.control controlBatteryLevelReached 0") if($controlBatteryLevelReached == 1);

        # Erster Start rücksetzen
        fhem("set WG.Balkonkraftwerk.control controlFirstStart 0") if($controlFirstStart == 1);
       
        # Status setzen
        $controlState = 3;
    }
   
    # Status setzen
    fhem("set WG.Balkonkraftwerk.control controlState $controlState");
   
}

Grüße Ralf

rudolfkoenig

Woher weiss das Programm, welche der 3 Phasen belastet wurde?
Tut mir leid, falls mein Unwissen auf dem Gebiet hier zu offensichtlich wird.

schwatter

Der Zähler ist saldierend. Daher kann immer mit der Gesamtsumme gerechnet werden.

Gruß schwatter

RalfP

Hallo Rudolf,

vielen Dank hier auf diesem Wege nochmals, mit dem Tipp betreffs connectFn beim MQTT_CLIENT. Wie du siehst hab ich es erfolgreich umgesetzt, wie die ersten Tests zeigen.

Der Shelly Pro 3EM ist ein 3 Phasen Zähler, den man zentral in seinen Sicherungskasten einbauen muss. Er saldiert die 3 Phasen. Die Abrechnung des Versorgers unterscheidet auch nicht zwischen den Phasen. Der Gesamtwert kommt über 'total_act_power' per MQTT vom Shelly Pro 3EM rein.

Ich erkläre es immer so: Akzeptiere immer die Anzeige deines Stomzählers. Er berechnet dir gerade, was aus deinem Haushalt rausgeht, oder auch reingeht, immer über alle 3 Phasen. Das bezahlst du auch nur an den Versorger. Damit ist es für den Haushalt egal, ob gerade über eine Phase eingespeist wird und über eine andere gerade Strom gezogen wird. Die Summe macht es.

Ist die Summe negativ, schenkt man dem Versorger Energie. Darum mein Versuch die Regelung so zu optimieren, das ich überschüssige Energie im Akku speichere und später nutze.

Hier noch eine Erklärung im Netz dazu:
https://solarblitz.blogspot.com/2018/08/einspeisung-auf-einer-oder-3-phasen.html

Grüße Ralf

blofield

Steuert einer von euch mit RalfP's Modul einen Hyper2000?

Ich vermute ich verstehe es noch nicht ganz oder mache etwas falsch, aber ob ich outputLimit setze oder nicht, da passiert nix.
Fehlermeldungen im Log habe ich keine. Bin auf dem EU Server. Habe das ConfigProposal angenommen...

Grüße
blofield

Shadow3561

#29
Moin,
Ich steuere einen Hyper2000.

Das Output-Limit kann man nur setzen wenn die Energiepläne wie Smart-CT oder Zeitsteuerung ausgeschaltet sind.

Mfg

RalfP

Hallo blofield,

sofern Shadow's Tipp nicht hilft, ist es für mich irgendwie wieder ein Zeichen, dass das Publishing auf den EU Server nicht funktioniert. Habe ich leider nie testen können.

Verstehen würde ich es aber nicht, da die App auch nur über MQTT sendet. Die funktioniert ja, oder?

Sofern du deine App auf einem Mac installiert hättest (geht bei macOS  :D ) und gleichzeitig Wireshark mit Filter mqtt lauschen lässt, müsstest du die Kommunikation theoretisch sehen können, wenn du in der App den Output veränderst. Wäre interessant, was da übermittelt wird.

Du darfst diesen Dateianhang nicht ansehen.

Grüße Ralf

RalfP

Hallo blofield,

noch etwas:

Ich nehme an, du hast einen MQTT2_CLIENT in Fhem mit meinem Vorschlag konfiguriert (76_Zendure.pm), wie auch ein Login und damit den AccessToken generiert. Bekommst du Daten in deine Readings geschrieben?

In der App darfst du den zweiten Zendure Account, welchen du auch nun in Fhem benutzt, nicht wieder anmelden! Der Token in Fhem wird damit ungültig. Sollte dies passieren, musst du einen neuen Token erzeugen, bzw. im MQTT2_Client mit connectFn Konfiguration (ZendureUtils.pm) einmal disconnecten und, nach 10s Warten, wieder connecten. Ein Token wird dann neu erzeugt.

Ich hatte festgestellt, das wenn man nach dem Login und connect des MQTT2_Client, die App wieder (mit gleichem Account) startet. Der MQTT2_Client zwar immer noch Daten empfängt, aber das Publish nicht funktioniert.

Andersherum ist es ganz cool, beobachte mit dem automatisch konfigurierten MQTT2_Client über connectFn, dass nach erfolgreichem Connect der Nutzer in der App abgemeldet wird.


Übrigens: Wenn du mit deinem Hauptaccount in der Zendure App den Output veränderst, sollte dies auch in den iot Topics sichtbar werden. So ungefähr:

Du darfst diesen Dateianhang nicht ansehen.

Ich gehe mal davon aus, das beim Hyper2000 der Wert sich auch 'outputLimit' nennt.

Grüße Ralf

blofield

Hallo Shadow3561 & RalfP,

erstmal vielen Dank für die schnelle Unterstützung!
Es lag an dem von Shadow3561 angesprochenen, eingstellten Modi in der App.
Ich habe in der App alle Modi ausgeschaltet, dann hat es sofort funktioniert, auch über den EU Server.

Den Hyper 2000 kann ich jetzt über inputLimit & outputLimit steuern, ich ergänze jeweils mit dem passenden acMode 1 || 2.

Hatte gestern leider Probleme mit meinem Hostsystem, nach dem Neustart hat aber leider nichts mehr funktioniert.
Ich musste mir einen neuen Access-Token erstellen, damit es wieder steuerbar war.
Meine Vermutung war allerdings, dass der Token ja noch Gültigkeit haben müsste, da ich mich nicht in der APP angemeldet hatte.
@RalfP ist das Setup rebootfähig?

Grüße
blofield

RalfP

Hallo blofield,

ja, ich selbst habe mir einen Token für meine Mosquitto Bridge config vor langer Zeit erzeugt und er funktioniert immer noch. Auch nach mehrerem Neustarts von Mosquitto.

Auch wenn du einen eigenen MQTT2_CLIENT angelegt hast, klappte es.

Wenn du mit connectFn (ZentureUtils.pm) im MQTT2_ClIENT arbeitest, wird mit jedem Connect ein neuer Token erzeugt. Da währest du auf der sicheren Seite.

Grüße Ralf

Reinhart

Danke das hier so ein tolles und funktionales Modul entwickelt wurde!
Ich habe das jetzt alles so nachgebaut und es funktioniert alles genauso wie beschrieben. Ich bin notgedrungen am EU Server und auch da klappt alles, speziell die Befehlsausgabe und somit das MQTT Write. EU Server ist deshalb für mich so wichtig, weil ich einen ACE1500 mit dynamischen Stromtarif nutze. Hier ist es zwingend notwendig in der App im Profil das Land exakt einzustellen, sonst werden falsche Börsenpreise geladen. Jedes Land hat seine eigenen Börsentarife wegen der unterschiedlichen Anteile von Nachfrage, Wind, PV und Wasser!
Da ich zur Zeit alles mit dem nachgeschaltenen Hoymiles Wechselrichter steuere habe ich zur Zeit kein Einsatzgebiet für diesen MQTT Write Zugang des Zendure Solarflow, aber wer weiß was mir noch alles einfällt.

Im Augenblick habe ich meine Anlage so verschaltet mit zusätzlicher Möglichkeit über ein externes Netzteil den Akku zu laden. Letzteres kann jetzt fast wegen dem ACE 1500 entfallen weil der das auch kann.
Mit diesem Modul ergeben sich natürlich völlig neue Möglichkeiten, vor allem weil die dynamischen Börsendaten nicht immer deckungsgleich von meinem Anbieter aWATTar sind. Da der ACE 1500 jedoch noch keine MQTT Daten liefert muss man wohl noch etwas auf eine Zendure Unterstützung warten.
FHEM auf Raspy4 mit Bullseye + SSD, Homematic, ESP8266, ESP32, Sonoff, eBus, NanoCUL, MapleCUL, , MQTT2, Alexa

RalfP

@Reinhard: Das ist mal eine echt umfangreiche Installation  :)

Habe mal noch eine Frage an die Nutzer, die einen Energieplan eingestellt haben: Steht bei euch etwas in den Werten "smartMode" und "smartPower". Verändert sich "smartPower" und wenn, wie und in welcher Abhängigkeit (wenn erkennbar)?

Vielen Dank
Ralf

Shadow3561

Moin,
ich versuche nun schon das ganze Wochenende die Energiepläne übers Modul zu setzen, bekomme es aber nicht hin.
Eigentlich sollte es über "autoModel" funktionieren.

autoModel:7,9,10 iot/<productKey>/<deviceKey>/properties/write {"properties":{"autoModel":$EVTPART1}}vielleicht mag es mal jemand probieren der ein anderes Zendure Gerät hat.

Beim rumprobieren habe ich noch hinbekommen die Entladegrenze zu setzen. Hier ist ganz interessant, dass man den minSoc bis 99% sehen kann.

min_Soc:990,900,800,700,600,500,400,300,200 iot/<productKey>/<deviceKey>/properties/write {"properties":{"minSoc":$EVTPART1}}
Mit freundlichen Grüßen

RalfP

Hallo,

leider hab ich dies nie probiert. Hab ein produktives System mit eigener Regelung. Ich könnte mir vorstellen, das es etwas mit der Abfrage "Speichern?" zu tun hat. Versuche doch mal verbose 5 im MQTT2 Client und schneide den kompletten Traffic mal mit, während du in der Zendure App den Energieplan änderst und speicherst. Vielleicht ist etwas zu sehen.

Grüße
Ralf

rabehd

Hallo,
ich habe Hyper 2000 (aktuell ein Speicher, 2. Speicherist im Zulauf). Ich habe zum Test beide Wege zur Integration in FHEM ausprobiert.

Zum einen wie in Eingangspost beschrieben. Im MQTT2_DEVICE vermisse ich Werte wie bisher erzeugte Energie und im Akku befindliche Energie. Werden diese Werte nicht übermittelt.

Zum anderen per 76_Zendure.pm. Im MQTT2_DEVICE gibt es eine Menge Readings, die aber alle nicht mit mir sprechen. Gibt es hier eine Liste als Beschreibung? Was kann ich mit den Set-Befehlen tun?

Danke


Auch funktionierende Lösungen kann man hinterfragen.

RalfP

ZendureUtils

Die Werte betreffs erzeugter Energie und Akku werden leider nicht per MQTT übermittelt. Die werden über https:// per POST abgefragt, natürlich nur mit den entsprechenden Credenciales. Als Antwort kommt ein riesiges JSON, mit den ganzen Tagesdaten. Leider hatte ich bisher keine Zeit das einzubinden.

76_Zendure

Dient nur zur Erzeugung des Accesstokens und einiger Login Daten für einen eigenen MQTT Client oder für eine Bridge Konfiguration in Mosquitto o.ä. Über GET ConfigProposal bekommst du entsprechende Beispiele angezeigt.

PS: Der Token ist immer nur ca. 30 Tage gültig.

Grüße
Ralf

rabehd

Selbstverständlich habe ich einen eigenen MQTT Client und ein MQTT2_DEVICE.
Deshalb ja ich meine Frage zu den vielen Readungs, die für mich nicht selbsterklärends sind.

Zitat von: rabehd am 13 April 2025, 17:16:44Gibt es hier eine Liste als Beschreibung? Was kann ich mit den Set-Befehlen tun?
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Ich nehme an, du sprichst über die Daten, die das MQTT Device liefert. Bitte schau unter https://github.com/RP-Develop/Zendure in die Quellenangaben. Unter https://github.com/Zendure/developer-device-data-report wird man bei Zendure fündig. Die Erläuterungen beziehen sich zwar auf die Zendure Developer API, trifft aber zu großen Teilen auch auf die Daten zu, die über den MQTT Zugang, wie hier genutzt, kommen. Mit dem Zugangsdaten im Fhem Modul wird ein App Zugang simuliert. Deshalb ist es auch möglich Einstellungen zu schreiben, was mit dem Zendure Developer MQTT (derzeit) nicht möglich ist.

Zu den SET's (definiert in setList):
Output: Setzt den Wert der Ausgangsleistung. In der App unter Netzein- & Ausgangseinstellungen. 
Update: Aktualisiert alle Daten.
Bypass: 0,1,2 setzt die Bypasseinstellung. 0 = Auto. Wert in passMode zu lesen.
autoRecover: 0,1 ist der Schalter, um den Bypass am nächsten Tag wieder auf Auto zu schalten.
Buzzer: 0,1 schaltet "Sounds" ein/aus
minSoc: Akkueinstellung, lässt sich im Bereich von 10% (=100) bis 50% (=500) einstellen.

Erläuterungen sind jetzt auch in der Wiki unter https://github.com/RP-Develop/Zendure

Grüße
Ralf

rabehd

Danke für die Erklärungen.
Das bedeutet, dass 76_Zendure.pm die "bessere" Lösung ist.

Zitat von: RalfP am 13 April 2025, 18:35:52Als Antwort kommt ein riesiges JSON, mit den ganzen Tagesdaten. Leider hatte ich bisher keine Zeit das einzubinden.
Das verfügbar zu haben wäre toll. Kann ich da unterstützen?
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Nun ja, das 76_Zendure.pm hatte ich ursprünglich als Erstes fertig, da ich in meinen Mosquitto eine Bridge konfiguriert hatte und ich nur den Token benötigte. Mir war es aber leid, jeden Monat den Token dort händisch zu ersetzen. Darum habe ich dann den Zusatz für das MQTT2_CLIENT Modul geschrieben. Rudi gab mir den Tipp mit connectFn. Mit SET connect, wird automatisch immer ein neuer Token erzeugt und als MQTT ClientID eingesetzt.

Derzeit lasse ich immer Montags mit einem at eine neue Verbindung aufbauen:
*05:00:00 { if ($wday == 1) { fhem ("set Zendure.MQTT disconnect; sleep 40; set Zendure.MQTT connect") } }

Grüße
Ralf

Shadow3561

Zitat von: RalfP am 14 April 2025, 15:08:16Die Werte betreffs erzeugter Energie und Akku werden leider nicht per MQTT übermittelt. Die werden über https:// per POST abgefragt, natürlich nur mit den entsprechenden Credenciales. Als Antwort kommt ein riesiges JSON, mit den ganzen Tagesdaten. Leider hatte ich bisher keine Zeit das einzubinden.

Mich würde auch interessieren wie man an die Daten kommt.
Das ist das einzige was mir noch fehlt.
hast du evtl. einen Hinweis oder sogar ein Beispiel?

Mit freundlichen Grüßen

RalfP

Ihr könnt das hier beigefügte 76_Zendure mal testen. Bitte nicht auf eurem Produktivsystem. Da ich nur einen Hub 2000 habe, wäre ein Test mit einem anderen oder mehreren Geräten interessant.
Derzeit habe ich es nur im 76_Zendure umgesetzt. ZentureUtils folgt nach erfolgreichem Test.
SET Update lädt die Device Liste und anschließend die Daten (Electric & Energy). Vorheriges Login ist notwendig (ich empfehle für die Tests einen separaten Account). Nicht alles enthält einen Wert. Vergleicht die Werte mit denen in eurer App, um die Bedeutung zu erkennen. Die Daten für die Plots werte ich nicht aus.
Die Readings sind jetzt mit der ID des Device versehen.
Über ATTR UpdateInterval kann man das Update auch zyklisch abrufen. Ich empfehle so aller 300s oder länger.

Lasst mal hören...

Grüße
Ralf

Shadow3561

Ich bekomme immer ein error beim login.


defmod Zendure Zendure xxxx@web.de password
attr Zendure expert 1
attr Zendure room Zendure

setstate Zendure error
setstate Zendure 2025-03-18 12:20:46 Device_1_deviceKey xxxxx
setstate Zendure 2025-03-18 12:20:46 Device_1_name Hyper 2000
setstate Zendure 2025-03-18 12:20:46 Device_1_productKey gxxxx
setstate Zendure 2025-03-18 12:20:46 Device_1_productName Hyper 2000
setstate Zendure 2025-03-18 12:20:46 Device_1_snNumber xxxxxxxxx
setstate Zendure 2025-03-18 12:20:46 Device_1_subscriptions /xxxx/yyyyy/# iot/xxxxx/yyyy/#
setstate Zendure 2025-03-18 12:20:46 MQTT_accessToken xxxx:yyyyy-zzz-usw
setstate Zendure 2025-03-18 12:20:46 MQTT_iotPassword oK#abcdef
setstate Zendure 2025-03-18 12:20:46 MQTT_iotUrl mq.zen-iot.com:1883
setstate Zendure 2025-03-18 12:20:46 MQTT_iotUserName zenApp
setstate Zendure 2025-03-18 12:20:46 MQTT_userId 656565
setstate Zendure 2025-04-15 17:16:56 state error

RalfP

#47
define <name> Zendure <username> <password> <server>

Username und Password sind die vom zweiten Zendure Account. Werden anschließend verschlüsselt im DEF angezeigt.

Parameter "server" - bezieht sich auf den Zendure Server. Es gibt einen 'Global' und einen 'EU'. Als Parameterwert kann ' global | Global | v2 ' für den Globalen und ' eu | EU ' für den EU Server verwendet werden. Welcher Server benutzt wird, wird bei der Erstanmeldung festgelegt. Beachte: Ein Wechsel löscht alle gespeicherten Daten.

attr expert hat noch keine Funktion

Evtl. noch "deletereading Zendure Device_1_.*" dann noch durchführen, um die alten Readings wegzubekommen.

Shadow3561

#48
Danke,
der Hinweis mit dem ' global | Global | v2 ' hat mir gefehlt.
Login klappt und Daten sind da.
Perfekt.
thx

Gibt es evtl. auch irgendwo die Daten für die gesamte Laufzeit des Systems?

Was mir noch aufgefallen ist:
energy_batteryInput
energy_batteryOutput
sind vertauscht

RalfP

Eine Gesamtlaufzeit mit Totalwerten gibt es. Kann man in der App abrufen, also muss ich nachschauen, wie die Abfrage ist. Derzeit werden nur aktuelle Daten von heute abgerufen.

Die Bedeutung von energy_batteryInput & energy_batteryOutput ist mir auch etwas unverständlich. Es sind aber die Daten die ich bekomme, da ist nichts verdreht, da ich die selben Datenbezeichnungen genommen habe. Es ist aber möglich, das Zendure da etwas anders denkt z.B. batteryOutput = zur Batterie hin, was an der Batterie der Eingang wäre o.s.ä.  ::)

PS: freut mich erst einmal, das es auch mit einem Hyper 2000 funktioniert. So kann ich weitermachen.

Grüße
Ralf

RalfP

Hallo Shadow,

kannst du mal schauen über GET showData DeviceList welche 'productType' => X bei deinem Hyper 2000 angezeigt wird?

Ich würde versuchen die Readings zu reduzieren und abhängig vom Typ (sofern dies möglich ist) erzeugen. Leere (Wert 0 und nicht in App sichtbar) würde ich nicht anzeigen, diese nur wenn ein noch unbekannter Type kommen würde. 

Für die Gesamtlaufzeit und -werte muss ich eigene neue Namen wählen, da die Daten über die selben Keys kommen, wie bei der Tagesabfrage. Mal sehen, wie ich es gestallte.

Grüße
Ralf

rabehd

#51
Ich habe eine Hyper 2000.
Irgendwie komme ich damit nicht klar.
Der gestrige Versuch machte Probleme, heute ohne sichtbare Fehler.

setstate ZendureBridge [b]Electric data successful loaded![/b]
etstate ZendureBridge 2025-04-15 16:26:36 Device__electric_bindDeviceInput 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__electric_fromSolar 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__electric_outputToBindDevice 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__electric_toHome 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_acOutputTotal 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_batteryInput 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_batteryOutput 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_bindDeviceInput 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_dcOutputTotal 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_gridDirectTotal 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_gridInputTotal 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_home 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_outputToBindDevice 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_outputToInverse 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_socketOutputTotal 0
setstate ZendureBridge 2025-04-15 16:26:36 Device__energy_solar 0
setstate ZendureBridge 2025-04-15 16:26:35 Device__subscriptions ///# iot///#
setstate ZendureBridge 2025-04-16 10:22:01 MQTT_iotUrl mqtteu.zen-iot.com:1883
setstate ZendureBridge 2025-04-16 10:22:02 state Electric data successful loaded!

Das sind Werte von gestern, wo sind die von heute hin? Die App hat Werte größer 0.

Dafür erscheint dieses Devive.
defmod Zendure_MQTT_76573 MQTT2_DEVICE <xxx>
attr Zendure_MQTT_76573 IODev Zendure_MQTT
attr Zendure_MQTT_76573 alias Server <xxx>
attr Zendure_MQTT_76573 autocreate no
attr Zendure_MQTT_76573 readingList .*/server/app/<xxx>/loginOut/force:.* force
attr Zendure_MQTT_76573 room Zendure_MQTT
attr Zendure_MQTT_76573 stateFormat &nbsp

setstate Zendure_MQTT_76573 &nbsp
setstate Zendure_MQTT_76573 2025-04-16 10:15:20 IODev Zendure_MQTT
setstate Zendure_MQTT_76573 2025-04-16 10:22:01 force <gelöscht fürs Forum>

Ein "GET showData Energie" führt zu stored data:
DeviceId: <xxx>
{
          'data' => {},
          'code' => 401,
          'msg' => 'Die Anfrage ist nicht autorisiert',
          'success' => 0
        };

Auch funktionierende Lösungen kann man hinterfragen.

Shadow3561


rabehd

Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Hallo rabehd,

bitte nicht 76_Zendure, hier aus dem Forum, mit dem ZendureUtils (MQTT) gleichzeitig mit identischen Logindaten verwenden. Die Beiden nehmen sich jeweils die Credenciales weg, wenn du beide mit den selben Logindaten verwendest. Für's Testen evtl. einen 3. Account anlegen bei Zendure. Geht über Gerätefreigabe, man benötigt unterschiedliche Email Adressen.

PS: ZendureUtils habe ich noch nicht mit den Statistikwerten erweitert, da bitte ich noch um etwas Geduld. Dann wäre 76_Zendure nicht mehr notwendig.

Grüße
Ralf

RalfP


'productType' => 17,
Alles klar, damit kann ich etwas anfangen. Könnt ihr mal noch kurz mitteilen, welche Werte wirklich einen Wert beinhalten, der auch in der App ersichtlich ist?

Für den HUB 2000 ('productType' => 8 ) habe ich nur folgendes, was relevant wäre:
'solar' => '435.17',
'home' => '82.59',
'batteryInput' => '0',
'batteryOutput' => '335.57',

Wird bei euch mehr angezeigt?

rabehd

Ich habe es jetzt mit einem neuen Account auf einer anderen Instanz versucht, nur 76_Zendure.
"Electric data successful loaded!"


'Die Anfrage ist nicht autorisiert'
wenn ich get showdate Energy (oder andere Optionen) ausführe.
Irgendwelche Readings mit energy erscheinen nicht.
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Hast du einen neuen aktualisierten Token (MQTT_accessToken) erhalten, wenn du SET Login machst?

Du darfst auch nicht zwischendurch mit deiner App und dem gleichen Login etwas nachschauen, das würde die Credenciales wieder zurücknehmen.


rabehd

Zitat von: RalfP am 16 April 2025, 12:12:34Hast du einen neuen aktualisierten Token (MQTT_accessToken) erhalten, wenn du SET Login machst?
ja

Zitat von: RalfP am 16 April 2025, 12:12:34Du darfst auch nicht zwischendurch mit deiner App und dem gleichen Login etwas nachschauen,
Der Account ist nur für diesen Test. In der App ist der erste, in FHEM-Prod der zweite.

Auch funktionierende Lösungen kann man hinterfragen.

RalfP

verbose = 5

Im Log lasse ich für jeden https Aufruf (token, deviceList, energy , electric) die Adresse, wie auch den Header,Body und die Antwort loggen. Sieht ungefähr so aus:
Zendure: <Request> URL:https://app.zendure.tech/v2.... send:
## Header ############

## Body ##############

...

Zendure: <parseRequestAnswer> URL:https://app.zendure.tech/v2... returned data:
## HTTP-Statuscode ###
200
## Data ##############

## Header ############
HTTP/1.1 200 OK

Evtl. ist da etwas zu erkennen. Bitte aber nicht das Log hier senden, höchstens Teile daraus, da Daten enthalten sein könnten.

rabehd

Login, Daten verändert

2025.04.16 13:05:45.518 5: ZendureBridge: <Get> called for ZendureBridge : msg = ?
2025.04.16 13:05:49.638 5: ZendureBridge: <Request> URL:https://app.zendure.tech/eu/auth/app/token send:
## Header ############
$VAR1 = {
          'Accept-Language' => 'de-DE',
          'Content-Type' => 'application/json',
          'Accept' => '*/*',
          'appVersion' => '4.3.1',
          'Authorization' => 'Basic YmVja2VycmFsZkBxxxxxxxxxxxxxxdDIwMjU=',
          'User-Agent' => 'Zendure/4.3.1 (iPhone; iOS 14.4.2; Scale/3.00)',
          'Blade-Auth' => 'bearer (null)'
        };

## Body ##############
{"password":"Passwort","tenantId":"","account":"mailadr@x.com","appId":"121c83f761305d6cf7b","grantType":"password","appType":"iOS"}

2025.04.16 13:05:49.711 5: ZendureBridge: <Get> called for ZendureBridge : msg = ?
2025.04.16 13:05:50.207 5: ZendureBridge: <parseRequestAnswer> URL:https://app.zendure.tech/eu/auth/app/token returned data:
## HTTP-Statuscode ###
200
## Data ##############
{"code":200,"success":true,"data":{"userType":"21","accessToken":"TOKENTOCKEN","userId":"ID123","tenantId":"","oauthId":"","avatar":"https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png","authority":"","userName":"","account":"","countryCode":"DE","serverNode":"eu","iotUrl":"mqtteu.zen-iot.com","iotUserName":"zenApp","iotPassword":"h+jwZvTlDg2e7g0lyMIkUlP5VraxLJtPgIUZohDg4SeR2n2eJrtoM+lFU4lrbBdaif4JpsA7vfhxAC3RLrrt0KUOhdiZUX1SsiYFESxz21K8M0nRHUkHn65uBYThA8SxGf84mvNesKyabW/rDrXnTyn1v6motJm/Am1bLA2WDh4=","serverNodeUrl":"https://app.zendure.tech/eu","serverH5Url":"https://app.zendure.tech","mallSwitch":1,"isNew":1,"whitelist":0,"hemsFlag":false,"zone":"Europe/Berlin"},"msg":"Vorgang erfolgreich"}
## Header ############
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Connection: close
Date: Wed, 16 Apr 2025 11:05:50 GMT
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Accept-Encoding,Host,Connection,Content-Length,User-Agent,Origin, X-Requested-With, Content-Type, Accept,blade-auth,authorization,Accept-Language,appVersion,captcha-code,captcha-key
Access-Control-Allow-Credentials: true
X-Cache: Miss from cloudfront
Via: 1.1 62be04c57195b92a15c9e33c0bb32906.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: MUC50-P5
X-Amz-Cf-Id: iczy7PXpHWxC3hAJnNfTnOreZFjlIu3LbJFHkYQRUgyukJMZkuzJgA==

2025.04.16 13:05:50.211 5: ZendureBridge: <Request> URL:https://app.zendure.tech/eu/productModule/device/queryDeviceListByConsumerId send:
## Header ############
$VAR1 = {
          'User-Agent' => 'Zendure/4.3.1 (iPhone; iOS 14.4.2; Scale/3.00)',
          'Authorization' => 'Basic Q29uc3VtZXJBcHA6NX4qUmRuTnJATWg0WjEyMw==',
          'Blade-Auth' => 'bearer TOKENTOCKEN',
          'Accept-Language' => 'de-DE',
          'Content-Type' => 'application/json',
          'Accept' => '*/*',
          'appVersion' => '4.3.1'
        };

## Body ##############
{}

2025.04.16 13:05:50.410 5: ZendureBridge: <parseRequestAnswer> URL:https://app.zendure.tech/eu/productModule/device/queryDeviceListByConsumerId returned data:
## HTTP-Statuscode ###
200
## Data ##############
{"code":200,"success":true,"data":[{"id":ID234,"deviceKey":"keydev","snNumber":"SNNR","name":"WER","productId":68,"productKey":"gDa3tb","onlineFlag":"00601","productName":"Hyper 2000","wifiStatus":true,"blueState":false,"fourGStatus":false,"isShareFlag":"00601","input":false,"output":false,"electricity":89,"hasPack":true,"restState":0,"upsMode":false,"upgradeStatusDes":"","productType":17,"deviceType":0,"upgradeStatus":{},"bindId":0,"bindStatus":0,"batteryCode":"","packList":[],"inputPower":0,"outputPower":0,"slowChargePower":0,"temperature":0,"temperatureUnit":0,"remainOutTime":0,"bindType":0,"seriesMode":0,"parallelMode":0,"networkType":0,"standard":"E","isSwitch":false,"url":"","remainOil":0,"genMode":0,"shortCode":"E1","phaseCheck":0,"pass":0,"clusterList":[],"clusterNotice":false,"nodeStatus":0,"clusterId":null,"phase":null,"reverseState":0,"meterId":0,"hemsId":0}],"msg":"Vorgang erfolgreich"}
## Header ############
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Connection: close
Date: Wed, 16 Apr 2025 11:05:50 GMT
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Accept-Encoding,Host,Connection,Content-Length,User-Agent,Origin, X-Requested-With, Content-Type, Accept,blade-auth,authorization,Accept-Language,appVersion,captcha-code,captcha-key
Access-Control-Allow-Credentials: true
X-Cache: Miss from cloudfront
Via: 1.1 3e8fb1cae95e63b7f329b9330db0c47a.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: MUC50-P5
X-Amz-Cf-Id: H5Z7GVvcq8bUyhpEHynJeM6p9-sL-Wje5A4IWr8EOkDbXQlsWpAqtA==

2025.04.16 13:05:50.412 5: ZendureBridge: <Request> URL:https://app.zendure.tech/as/tdengine/device/solarFlow/electric send:
## Header ############
$VAR1 = {
          'Accept' => '*/*',
          'appVersion' => '4.3.1',
          'Accept-Language' => 'de-DE',
          'Content-Type' => 'application/json',
          'User-Agent' => 'Zendure/4.3.1 (iPhone; iOS 14.4.2; Scale/3.00)',
          'Blade-Auth' => 'bearer TOKENTOCKEN'
        };

## Body ##############
{"deviceId":ID234,"beginDate":"2025-04-16","zone":"Europe/Berlin","type":0,"aceId":"","endDate":"2025-04-16"}

2025.04.16 13:05:50.413 5: ZendureBridge: <Request> URL:https://app.zendure.tech/as/tdengine/device/solarFlow/energy send:
## Header ############
$VAR1 = {
          'Accept' => '*/*',
          'appVersion' => '4.3.1',
          'Accept-Language' => 'de-DE',
          'Content-Type' => 'application/json',
          'User-Agent' => 'Zendure/4.3.1 (iPhone; iOS 14.4.2; Scale/3.00)',
          'Blade-Auth' => 'bearer TOKENTOCKEN'
        };

## Body ##############
{"beginDate":"2025-04-16","deviceId":ID234,"endDate":"2025-04-16","type":0,"zone":"Europe/Berlin","aceId":""}

2025.04.16 13:05:50.971 5: ZendureBridge: <parseRequestAnswer> URL:https://app.zendure.tech/as/tdengine/device/solarFlow/electric returned data:
## HTTP-Statuscode ###
200
## Data ##############
{"code":401,"success":false,"data":null,"msg":"Die Anfrage ist nicht autorisiert"}
## Header ############
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 82
Connection: close
Date: Wed, 16 Apr 2025 11:05:50 GMT
Access-Control-Allow-Headers: Accept-Encoding,Host,Connection,Content-Length,User-Agent,Origin, X-Requested-With, Content-Type, Accept,blade-auth,authorization,Accept-Language,appVersion,captcha-code,captcha-key
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT
Access-Control-Max-Age: 3600
X-Cache: Miss from cloudfront
Via: 1.1 3909cd34f904454f54cf78c975b2c198.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: MUC50-P5
X-Amz-Cf-Id: 7azEWUOO3ymBT2ekQzo_n9AS4llT_O0h4N3O2gRvsQeuQjX6D8o4Uw==

2025.04.16 13:05:50.977 5: ZendureBridge: <parseRequestAnswer> URL:https://app.zendure.tech/as/tdengine/device/solarFlow/energy returned data:
## HTTP-Statuscode ###
200
## Data ##############
{"code":401,"success":false,"data":null,"msg":"Die Anfrage ist nicht autorisiert"}
## Header ############
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 82
Connection: close
Date: Wed, 16 Apr 2025 11:05:50 GMT
Access-Control-Allow-Headers: Accept-Encoding,Host,Connection,Content-Length,User-Agent,Origin, X-Requested-With, Content-Type, Accept,blade-auth,authorization,Accept-Language,appVersion,captcha-code,captcha-key
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT
Access-Control-Max-Age: 3600
X-Cache: Miss from cloudfront
Via: 1.1 653de2a3596d1ebffe452d8daf65c9ea.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: MUC50-P5
X-Amz-Cf-Id: 4HWjfs5uvdTpPWjhMM8_11hZSenyOj-UgCbxClixKLMPKdCF6OJydw==

Auch funktionierende Lösungen kann man hinterfragen.

rabehd

get showdata enery und devicelist
2025.04.16 13:15:25.132 5: ZendureBridge: <Get> called for ZendureBridge : msg = ?
2025.04.16 13:16:40.809 5: ZendureBridge: <Get> called for ZendureBridge : msg = showData
2025.04.16 13:17:29.554 5: ZendureBridge: <Get> called for ZendureBridge : msg = ?
2025.04.16 13:17:35.588 5: ZendureBridge: <Get> called for ZendureBridge : msg = showData
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

oh, sollte das wieder eine Thematik des Servers sein?
ZendureBridge: <Request> URL:https://app.zendure.tech/eu/auth/app/tokenDu bist auf dem eu Server. Shadow scheint auf dem v2 (global) zu sein. Bei ihm hat es ja funktioniert. Es war immer mal wieder Thema, das es mit dem eu Server manches Problem gab.
Wenn es daran liegen sollte, wird es schwierig, da ich nicht ohne Weiteres auf den eu Server umschalten kann ohne Daten (und evtl. Funktionalität meines Produktivsystems) zu verlieren. Könnte auch an den URL's liegen, die bei einem Token von einem eu Server woanders hingehen müssten.

Ich schaue jetzt mal in die Glaskugel: Sofern du im Code eine Änderung mal durchführen kannst, ändere doch mal den Link
my $url = "https://app.zendure.tech/as/tdengine/device/solarFlow/electric";

in

my $url = "https://app.zendure.tech/eu/tdengine/device/solarFlow/electric";

rabehd

Erfolgreich, danke

Zitat'msg' => 'Erfolgreiche Operation',

Device_xx_energy_batteryInput 75.23 2025-04-16 15:12:01
Device_xx_energy_batteryOutput 1885.49 2025-04-16 15:12:01
Device_xx_energy_bindDeviceInput 0 2025-04-16 15:12:01
Device_xx_energy_dcOutputTotal 0 2025-04-16 15:12:01
Device_xx_energy_gridDirectTotal 0 2025-04-16 15:12:01
Device_xx_energy_gridInputTotal 0 2025-04-16 15:12:01
Device_xx_energy_home 4058.56 2025-04-16 15:12:01
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

...darauf muss man kommen  ::)

OK, werde es mit einbauen.

PS: war auch 'solar' dabei?

rabehd

Bezeichner in der App

energy_home = Heimgebrauch
energy_batteryOutput = Eingang (Akku); in der App in kWh
energy_batteryInput = Ausgang (Akku)
energy_solar = Energie erzeugt (Solar); in der App in kWh


Auch funktionierende Lösungen kann man hinterfragen.

rabehd

Zitat von: RalfP am 16 April 2025, 15:21:47...darauf muss man kommen  ::)

OK, werde es mit einbauen.

PS: war auch 'solar' dabei?
DU bist draufgekommen!

Ist doch gut, so hast Du einen Tester mit global und einen mit EU

Zitat von: RalfP am 16 April 2025, 15:21:47PS: war auch 'solar' dabei?
energy_solar = Energie erzeugt (Solar); in der App in kWh
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Hallo rabehd,

kannst du mir mal diese Werte aus GET showData Account zeigen? Würde vermuten, das beim eu Server es etwas anders aussieht.
'serverNode' => 'as',
'zone' => 'Asia/Shanghai',
'serverNodeUrl' => 'https://app.zendure.tech/as'
Grüße
Ralf

RalfP

Ich hab mal etwas Neues zum Testen.
Nur die Produkttypen 8 & 17 zeigen jetzt nur die relevanten, wie auch die totalen Werte an. Mit expert 1 oder einem anderem Produkttyp, werden wieder alle Daten gezeigt, aber keine totalen Werte.
Den richtigen Server nehme ich jetzt aus den Accountinfos, in der Hoffnung für den eu Server wird dort die richtige serverNodeUrl angezeigt.

Grüße
Ralf

rabehd

Hallo Ralf,

danke für Deinen Einsatz.
Ist damit die Aufgabe für mich aus #67 hinfällig?

Viele Grüße
Ralf
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

...das ist meine Hoffnung. Die serverNodeUrl lasse ich jetzt auch in den Internals anzeigen.

rabehd

Version aus #68 funktioniert, danke Dir.
Jetzt warte ich auf die Sonne.


          'success' => 1,
          'data' => {
                      'userName' => '',
                      'authority' => '',
                      'userType' => '21',
                      'serverNodeUrl' => 'https://app.zendure.tech/eu',
                      'iotUrl' => 'mqtteu.zen-iot.com',
                      'hemsFlag' => 0,
                      'tenantId' => '',
                      'account' => '',
                      'isNew' => 1,
                      'zone' => 'Europe/Berlin',
                      'whitelist' => 0,
                      'iotUserName' => 'zenApp',
                      'serverH5Url' => 'https://app.zendure.tech',
                      'countryCode' => 'DE',
                      'serverNode' => 'eu',
                      'mallSwitch' => 1
                    },
          'code' => 200

Kann es sein, dass nach einem Neustart das Login manuell ausgeführt werden muss?
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Zitat von: rabehd am 17 April 2025, 06:51:19Kann es sein, dass nach einem Neustart das Login manuell ausgeführt werden muss?
Ja, das Login muss nach Neustart wieder ausgeführt werden, damit die Daten wieder in den Speicher geholt werden können.

Könnte mir auch noch ein Autologin vorstellen, wie auch einen Re-Login nach einer gewissen Zeit. Die max Gültigkeit eines Token ist 30 Tage.
Als nächstes werde ich erst einmal ZendureUtils nachziehen mit den neuen Funktionen.

PS: bei mir ist es sehr trüb, es scheint, das die Sonne sich heute nicht viel zeigen wird  :(

rabehd

Da ist ein Wert, der zu prüfen wäre.
'data' => {'gridInputTotal' => '9188.9'     },
'today' => {'gridInputTotal' => 0,          },
'success' => 1,
'msg' => 'Erfolgreiche Operation',
'code' => 200,
'total' => { 'gridInputTotal' => '9188.9', }
        };

Ich finde diesen Wert aber nicht in der App.

Auch funktionierende Lösungen kann man hinterfragen.

RalfP

ah, das wird dein Bezug von Energie aus dem Netz sein.
ZitatZendure: Die bidirektionale 1.200-Watt-Leistung kann nicht nur zur Stromversorgung Ihres Hauses, sondern auch zur Speicherung von Strom aus dem Netz verwendet werden.
Werde beim Hyper 2000 diesen Wert mit anzeigen lassen.

rabehd

Total ist da etwas verwirrend. Total-today und Total-total  ;D
Ich simuliere mal eine Ladung aus dem Netz, dann sollte today was anzeigen und total sich ändern. 
Auch funktionierende Lösungen kann man hinterfragen.

rabehd

Hallo Ralf,
Du hast Recht, es ist wohl die Speicherung von Netzstrom.

'total' => { 'gridInputTotal' => '9189.51',   },
'code' => 200,
'msg' => 'Erfolgreiche Operation',
'today' => {'batteryInput' => '40.8',
            'outputToInverse' => 0,
            'type' => 0,
            'batteryOutput' => '66.8',
            'gridDirectTotal' => 0,
            'gridInputTotal' => '0.61',  },
'success' => 1,
'data' => {  'gridInputTotal' => '9189.51',       }
        };


Das Reading wurde heute morgen angelegt, aber scheint sich nicht zu aktualisieren.
Auch funktionierende Lösungen kann man hinterfragen.

Shadow3561

#77
Moin,
Ich hatte jetzt auch mal Zeit deine neue Version zu testen.
Hier ein list

Internals:
   DEF        crypt:x crypt:x v2
   FUUID      67c4aa27-f33f-d66d-07b6-3999269976aa2330
   FVERSION   76_Zendure.pm:?/2025-04-15
   NAME       Zendure
   NR         1582
   STATE      Energy data successful loaded!
   TYPE       Zendure
   VERSION    v0.0.5
   devices    1
   eventCount 1661
   server     v2
   serverNodeUrl https://app.zendure.tech/as
   OLDREADINGS:
   READINGS:
     2025-04-17 16:54:22   Device_63640_deviceKey x
     2025-04-17 16:54:24   Device_63640_energy_batteryInput 623.42
     2025-04-17 16:54:24   Device_63640_energy_batteryOutput 995.24
     2025-04-17 16:54:24   Device_63640_energy_home 639.11
     2025-04-17 16:54:24   Device_63640_energy_solar 440.81
     2025-04-17 16:54:22   Device_63640_id 63640
     2025-04-17 16:54:22   Device_63640_name Hyper 2000
     2025-04-17 16:54:22   Device_63640_productKey x
     2025-04-17 16:54:22   Device_63640_productName Hyper 2000
     2025-04-17 16:54:22   Device_63640_productType 17
     2025-04-17 16:54:22   Device_63640_snNumber x
     2025-04-17 16:54:22   Device_63640_subscriptions /x/# x/#
     2025-04-17 16:54:24   Device_63640_total_energy_batteryInput 219751.84
     2025-04-17 16:54:24   Device_63640_total_energy_batteryOutput 263755.16
     2025-04-17 16:54:24   Device_63640_total_energy_home 323795.23
     2025-04-17 16:54:24   Device_63640_total_energy_solar 291779.2
     2025-04-17 16:54:17   MQTT_accessToken x
     2025-04-17 16:54:17   MQTT_iotPassword x
     2025-04-17 16:54:17   MQTT_iotUrl     mq.zen-iot.com:1883
     2025-04-17 16:54:17   MQTT_iotUserName zenApp
     2025-04-17 16:54:17   MQTT_userId     x
     2025-04-17 16:54:24   state           Energy data successful loaded!
   helper:
     accessToken x
     deviceKey  x
     id         63640
     iotPassword x
     iotUrl     mq.zen-iot.com:1883
     iotUserName zenApp
     password   crypt:x
     productKey x
     serverNode as
     serverNodeUrl https://app.zendure.tech/as
     subscriptions /x/# x/#

     userId     53378
     username   crypt:x
     zone       Europe/Berlin
     auth:
       code       200
       msg        Vorgang erfolgreich
       success    1
       data:
         accessToken x
         account   
         authority 
         avatar     https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png
         countryCode DE
         hemsFlag   0
         iotPassword x
         iotUrl     mq.zen-iot.com
         iotUserName zenApp
         isNew      1
         mallSwitch 1
         oauthId   
         serverH5Url https://app.zendure.tech
         serverNode as
         serverNodeUrl https://app.zendure.tech/as
         tenantId  
         userId     x
         userName  
         userType   21
         whitelist  0
         zone       Europe/Berlin
     devices:
       code       200
       msg        Vorgang erfolgreich
       success    1
       data:
         HASH(0xxx)
     get:
       auth:
         code       200
         msg        Vorgang erfolgreich
         success    1
         data:
           accessToken x
           account   
           authority 
           avatar     https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png
           countryCode DE
           hemsFlag   0
           iotPassword x
           iotUrl     mq.zen-iot.com
           iotUserName zenApp
           isNew      1
           mallSwitch 1
           oauthId   
           serverH5Url https://app.zendure.tech
           serverNode as
           serverNodeUrl https://app.zendure.tech/as
           tenantId  
           userId     x
           userName  
           userType   21
           whitelist  0
           zone       Europe/Berlin
       devices:
         code       200
         msg        Vorgang erfolgreich
         success    1
         data:
           HASH(0xx)
Attributes:
   UpdateInterval 600
   room       Zendure

Anmerkung:
_total_energy_batteryInput 219751.84 ist korrekt
_total_energy_batteryOutput 263755.16 ist korrekt
auch hier wieder verdreht, aber egal

_total_energy_home 323795.23 ist korrekt
_total_energy_solar 291779.2 ist korrekt

Wenn ich jetzt "expert 1" setze kommen noch ein paar werte mehr

Hier ohne Attribut
Device_63640_deviceKey x
Device_63640_energy_batteryInput 643.71
Device_63640_energy_batteryOutput 995.24
Device_63640_energy_home 662.94
Device_63640_energy_solar 444.29
Device_63640_id x
Device_63640_name Hyper 2000
Device_63640_productKey x
Device_63640_productName Hyper 2000
Device_63640_productType 17
Device_63640_snNumber x
Device_63640_subscriptions /x/# x/#
Device_63640_total_energy_batteryInput 219772.13
Device_63640_total_energy_batteryOutput 263755.16
Device_63640_total_energy_home 323819.06
Device_63640_total_energy_solar 291782.68
Hier mit
Device_63640_deviceKey x
Device_63640_electric_bindDeviceInput 0
Device_63640_electric_fromSolar 0
Device_63640_electric_outputToBindDevice 0
Device_63640_electric_toHome 0
Device_63640_energy_acOutputTotal 0
Device_63640_energy_batteryInput 643.71
Device_63640_energy_batteryOutput 995.24
Device_63640_energy_bindDeviceInput 0
Device_63640_energy_dcOutputTotal 0
Device_63640_energy_gridDirectTotal 0
Device_63640_energy_gridInputTotal 553.63
Device_63640_energy_home 662.94
Device_63640_energy_outputToBindDevice 0
Device_63640_energy_outputToInverse 0
Device_63640_energy_socketOutputTotal 0
Device_63640_energy_solar 445.53
Device_63640_id 63640
Device_63640_name Hyper 2000
Device_63640_productKey x
Device_63640_productName Hyper 2000
Device_63640_productType 17
Device_63640_snNumber x
Device_63640_subscriptions /x/# x/#
Device_63640_total_energy_batteryInput 219772.13
Device_63640_total_energy_batteryOutput 263755.16
Device_63640_total_energy_home 323819.06
Device_63640_total_energy_solar 291783.92

das "energy_gridInputTotal 553.63" ist der Bezug vom Stromnetz/Überschuss grosse PV um den Akku zu laden. Dieser Wert fehlt leider in der Gesamtstatistik.

Mit freundlichen Grüßen

Edit:
Ich habe ab Zeile 612 folgendes eingefügt.
So sind für den Hyper alle Daten vorhanden.
Mit freundlichen Grüßen
elsif(($devices->{productType} == 8) || ($devices->{productType} == 17)){
readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "Device_".$devices->{id}."_energy_batteryOutput", $devices->{energy}{today}{batteryOutput});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_energy_batteryInput", $devices->{energy}{today}{batteryInput});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_energy_solar", $devices->{energy}{today}{solar});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_energy_home", $devices->{energy}{today}{home});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_energy_gridInput", $devices->{energy}{today}{gridInputTotal});

readingsBulkUpdate($hash, "Device_".$devices->{id}."_total_energy_batteryOutput", $devices->{energy}{total}{batteryOutput});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_total_energy_batteryInput", $devices->{energy}{total}{batteryInput});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_total_energy_solar", $devices->{energy}{total}{solar});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_total_energy_gridInput", $devices->{energy}{total}{gridInputTotal});
readingsBulkUpdate($hash, "Device_".$devices->{id}."_total_energy_home", $devices->{energy}{total}{home});
readingsEndUpdate($hash, 1);

RalfP

Hallo,

habe die neuen Versionen auf GitHub abgelegt. Update in Fhem ist möglich. ZendureUtils läuft seit gestern bei mir auf meinem Produktivsystem. Nehmt ca 15min (in Minuten anzugeben) für das updateIntervall, das solle ausreichend sein. Gehe später bestimmt mal auf 60min.

Grüße Ralf

rabehd

VERSION v0.0.5

Danke.
Ich vermisse den Wert von Heimgebrauch aus der App. Zumindest kann ich das keinem ähnlichen Wert zuordnen.
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

energy_today_home bzw. energy_total_home

Habe die bekannten Werte bzw. ihre bekannte Bedeutung hier zusammengefasst https://github.com/RP-Develop/Zendure/wiki/Statistikwerte


rabehd

Die Werte hier im Device liegen unter den Werten in der App. Das liegt wahrscheinlich am Interval. Ich schau mir das mal an, wenn die Sonne weg ist. 
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

...auf alle Fälle. Wenn du sie genau gleich sehen willst, must du sie in der App abrufen und gleichzeitig im Device.

rabehd

Zitat von: RalfP am 22 April 2025, 09:50:33Hallo,

habe die neuen Versionen auf GitHub abgelegt. Update in Fhem ist möglich. ZendureUtils läuft seit gestern bei mir auf meinem Produktivsystem. Nehmt ca 15min (in Minuten anzugeben) für das updateIntervall, das solle ausreichend sein. Gehe später bestimmt mal auf 60min.

Grüße Ralf

Seit dem fällt mir das auf
Zitaterror while HTTP requesting https://app.zendure.tech/eu/tdengine/device/solarFlow/energy - code: 200 - msg: Die Anfrage ist nicht autorisiert
Wenn ich mir das Device ansehe, dann steht es auf Initialisiert. Nach einem neuen Login geht es wieder.
Auch funktionierende Lösungen kann man hinterfragen.

Shadow3561

#84
Moin,
bei mir das selbe. Ein Login und die Daten werden abgerufen. Wenn ich das Fhem MQTT automatic configuration with loaded ZendureUtil.pm nutze, kann ich im angelegten Device keine Befehle an das Gerät senden und ich bekomme keine Daten vom Hyper, bis auf die Statistikdaten.
Nutze ich Fhem MQTT own configuration: dann muss ich erst einen Login bei dem Device für die Statistikdaten machen und danach ein Login beim matt Device damit alles funktioniert.

Ich werde noch ein wenig auf meinem Testsystem probieren.
Auf jeden Fall ein grosses Dankeschön für deine Arbeit.

Mit freundlichen Grüßen
Daniel

EDIT:
Hat sich erledigt. War ein Fehler meinerseits. Hatte noch beide Device (ZendureUtils.pm und Zendure.pm) gleichzeitig laufen.

RalfP

ja, es ist nicht vorgesehen, das man 76_Zendure und ZendureUtils gleichzeitig mit dem selben Accountdaten benutzt werden können. Es ist von Zendure nur vorgesehen, das nur ein Client mit  gleichen Accountdaten Zugriff bekommt. Dem anderen wird der Token ungültig gemacht. Deshalb auch die Fehler, wenn der Token ungültig ist.

Selbiges passiert auch mit der Zendure App auf zwei unterschiedlichen Geräten mit gleichem Account.

Shadow3561

Moin,
Gestern Abend hat das device 3 andere mqtt-Devices angelegt.
Energiezähler, Server52xxx und Server 53xxx.
2025.04.24 19:50:45.020 1: mq.zen-iot.com:1883 disconnected, waiting to reappear (TestHyper)
2025.04.24 19:50:45.371 1: TestHyper: <Zendure_connect> error while HTTP requesting https://app.zendure.tech/v2/auth/app/token returned data:
## HTTP-Statuscode ###
400
## Data ##############
{"code":400,"success":false,"data":{},"msg":"Falsches Konto oder Kennwort"}
## Header ############
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Connection: close
Date: Thu, 24 Apr 2025 17:50:45 GMT
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Accept-Encoding,Host,Connection,Content-Length,User-Agent,Origin, X-Requested-With, Content-Type, Accept,blade-auth,authorization,Accept-Language,appVersion,captcha-code,captcha-key
Access-Control-Allow-Credentials: true
X-Cache: Error from cloudfront
Via: 1.1 2b782f5f082f9exxxxx.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: HAM50-C3
X-Amz-Cf-Id: IPJkRGugTFloe_xxxxxxxxxxxGH90zw-TP-B7vqcrx6mw==

2025.04.24 19:50:55.969 1: TestHyper: <Zendure_connect> error while HTTP requesting https://app.zendure.tech/v2/auth/app/token returned data:
## HTTP-Statuscode ###
400
## Data ##############
{"code":400,"success":false,"data":{},"msg":"Falsches Konto oder Kennwort"}
## Header ############
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Connection: close
Date: Thu, 24 Apr 2025 17:50:55 GMT
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Accept-Encoding,Host,Connection,Content-Length,User-Agent,Origin, X-Requested-With, Content-Type, Accept,blade-auth,authorization,Accept-Language,appVersion,captcha-code,captcha-key
Access-Control-Allow-Credentials: true
X-Cache: Error from cloudfront
Via: 1.1 ad82d8a80fxxxxxxxxxxx722475c0.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: FRA60-P9
X-Amz-Cf-Id: EbjmP4Ud4K74xxxxxxxxxxxxxke3WaIn4Ty8W96TzVNmUOL2Qg==

2025.04.24 19:51:07.216 1: TestHyper: <Zendure_connect> Created device TestHyper_53378 for Server 53378
2025.04.24 19:51:07.597 1: mq.zen-iot.com:1883 reappeared (TestHyper)

Der Benutzername und das Kennwort sind definitiv richtig, aktuell habe ich eine Verbindung.
Mit freundlichen Grüßen

RalfP

#87
Hallo Shadow,

Diese Antwort hast du vom Zensur Server bekommen als du einen Token abgerufen hast. Vermutlich mit falschem User/Password.
{"code":400,"success":false,"data":{},"msg":"Falsches Konto oder Kennwort"}
Dieses zweite MQTT2_DEVICE (mit <name>_userID) lege ich an, bezogen auf deine userID, die in Abhängigkeit deiner Account Daten (User/Password) jeweils anders ist. Das zweite MQTT2_Device, welches nicht mehr zu deiner userID (Reading) passt kannst du löschen. Wenn du wieder die Accountdaten änderst, wird wieder ein entsprechendes Device angelegt. Das MQTT2_Device für die Daten wird immer nur überschrieben, da es sich auf die Seriennummer deines Gerätes bezieht, die ja gleich bleibt.

PS: das Server MQTT2_DEVICE habe ich gebaut, da man im Reading force den Token bekommt, der gerade die Oberhand bekommen hat, nur nicht den eigenen. Man könnte sich evtl. ein automatische relogin bauen, wenn dort das Reading sich ändert. Sehe ich aber nicht als notwendig an, sofern man einen Account hat, der nur in Fhem benutzt wird.

Grüße Ralf

rabehd

Mir ist bein "Basteln" was aufgefallen.

jsonMap:
properties_outputPackPower:outputPackPower
properties_outputPackPowerCycle:outputPackPowerCycle
properties_packInputPower:packInputPower
properties_packInputPowerCycle:packInputPowerCycle
Das ist nicht so einheitlich. Wie wäre es mit ?
properties_outputPackPower:outputPackPower
properties_outputPackPowerCycle:outputPackPowerCycle
properties_packInputPower:inputPackPower
properties_packInputPowerCycle:inputPackPowerCycle
Auch funktionierende Lösungen kann man hinterfragen.

RalfP

Hallo,

die Bezeichnungen habe ich alle von Zendure so übernommen. Manche ist auch für mich nicht ganz logisch. Die jsonMap lege ich zwar bei Erstellung des Device automatisch an, du bist aber frei in der Anpassung, sofern das Device mal vorhanden war. Die jsonMap wird dann nicht nochmals überschrieben.

Grüße
Ralf

rabehd

Hallo Ralf,
ich bin davon ausgegangen, dass Du die Bezeichner von zendure übernommen hast. Scheinbar finden wir das beide nicht optimal. Man kann das jetzt als Standard anpassen oder jeder macht das für sich oder man lässt es so.
Ich habe das jsonMap für mich angepasst.
Auch funktionierende Lösungen kann man hinterfragen.