Solarman Wechselrichter/Inverter Datenlogger

Seit ein paar Tagen hab ich einen Inverter mit einem WIFI Datenlogger von Solarman bzw heißt der Hersteller IGEN Tech. Die Einrichtung hat gut funktioniert und die Daten vom Wechselrichter werden auch brav in die Cloud verfrachtet. Ein Mail für den API Zugriff ist schon geschrieben. Ich warte auf Antwort. Mir wäre aber lieber, ich würde die Daten lokal abgreifen. Ich hab schon was von MODBUS gelesen, komme da aber nicht weiter. Es gibt da auf GitHub einige Ansätze und ich ahb schon versucht, in IPS einen ModBus Configurator einzurichten. Da tut sich aber irgendwie nichts.
Soweit ich herausgefunden habe, verwenden einige Hersteller von Wechselrichtern diesen Logger. Gibts da einschlägige Erfahrung?
Mir gehts jetzt gar nicht so sehr darum, wieviel das Teil produziert. Das bekomme ich ja am Ausgang mit entsprechenden Mitteln mit. Aber es werden noch andere interessante Daten geliefert. Z.b. Daten pro Panel und auch vom Wechselrichter direkt, wie Temperatur.

Hallo,

ich habe auch den Solarman in Verbindung mit einem WR von Bosswerk (MI-300). An einer API wäre ich sehr interessiert, aber Anfragen per Email werden nicht beantwortet und telefonisch erreicht man jemand erst nach tagelangen Versuchen.

Ich hatte Probleme mit meiner Voraus-Bezahlung an Hersteller statt über PayPal und es hat mich 2 1/2 Monate gekostet bis ich die Mahnungen weg hatte und das Problem gelöst war (auf die Lieferung hatte ich 4 Monate gewartet). Ich verstehe nicht, was das für Firmen sind.

Aber das ist jetzt OffTopic - das Balkonkraftwerk läuft gut und ich hätte auch gerne die Daten in IP-Symcon. Momentan greife ich Werte über einen Shelly EM ab. => Balkonkraftwerk

Viele Grüße aus dem Unterallgäu
Harry

Meiner kam 3 Tage nach Bestellung aus Polen an :slight_smile:
Egal.
Für die API musst du „freigeschalten“ werden. Was ich herausbekommen habe, reicht ein Mail. Angeblich kann es sein, dass noch ein paar Rückfragen kommen aber letztendlich soll ein Mail mit dem API Key und einer Beschreibung kommen.
Am vielversprechensden ist dieses Projekt, da das hier eher allgemein beschrieben ist und ich denke es könnte relativ einfach in IPS übernommen werden.

Trotzdem hätte ich gerne eine lokale Auswertung.
Ich hab auch was in Richtung MODBUS gefunden. Ob das alle Logger von denen können kann ich nicht sagen. Da mir da aber das Wissen fehlt, sind meine Versuche in IPS fehlgeschlagen. Was natürlich nicht heißt, dass es nicht geht.
Zum Beispiel hier

Sollt ich was bekommen, werde ich das gerne hier teilen. Aber der API Key ist halt leider einzigartig.

Versuch es mal hier
https://www.solarman.cn/enservice.html
über die Chatfunktion auf der rechten Seite
image
bei „Service“
Ich bin da grad dran.
So, nach ein paar Minuten hin und her schreiben (es kam auch die frage wofür ich es verwende und ob ich ein Professionist bin) haben sie mir zumindest bestätigt, dass sie die API für mich öffnen und mir alles per Mail zusenden. Gespannt ich bin.

Ich hab die Daten vor 3 Stunden (Zeitverschiebung) bekommen. Jetzt mal schauen, wie ich das reinbringe.
Diese Informationen haben sie mitgesendet
https://pro-cs.kefutoutiao.com/ticket_reply/tid30244/SOLARMAN3.0%20OPEN%20API%20Collection-DEMO.postman_collection_1660612893349_aj62g.json
SolarmanOpenAPI(v1.1.6)-EN_1660612888790_h6clo.pdf (1,5 MB)

Jetzt mal schaue, wie ich das mache.

So, ich glaube ich habe es für mich gelöst.
Ausgelesen wird

  • Daten vom Wechselrichter
  • Logdaten

Folgende Variablen hab ich für mich angelegt
Für die API


Für den Wechselrichter

Für das holen eines Tokens habe ich ein eigenes Skript erstellt, da dieser nicht immer neu geholt werden muss. Aber dazu später.

$url=getvalue(38165);
$user=getvalue(47023); //Benutzername vom Onlinezugang
$password=hash("sha256",getvalue(29895)); //Passwort vom Onlinezugang
$appId=getvalue(49005); //Daten kommen von Solarman
$appSecret=getvalue(41880); //Daten kommen Solarman

$erg=array();
$url = $url."/account/v1.0/token?appId=".$appId."&language=en&=";

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

$headers = array(
   "Content-Type: application/json",
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

$data ="
{
	\"appSecret\": \"".$appSecret."\",
	\"email\": \"".$user."\",
	\"password\": \"".$password."\"
}";

curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$resp = curl_exec($curl);
curl_close($curl);
$erg=json_decode($resp,true);
if ($erg["success"] == true)
{
	setvalue(24584,$erg["access_token"]);
	setvalue(47369,$erg["refresh_token"]);
	setvalue(52106,time()+$erg["expires_in"]);
}
else
{
	setvalue(24584,"");
	setvalue(47369,"");
	setvalue(52106,"");	
}

Das Auslesen der Daten erfolgt in einem eigenen Skript. Mich interessieren eigentlich nur relaitv wenige Werte.

  • Temperatur vom Wechselrichter
  • Updatezeit
  • Volt, Watt und Ampere der vier Eingänge
    *Logeinträge

Die Werte für die Erzeugung bekomme ich von einer anderen Stelle

<?php

function datenholen($sn)
{
	$token=getvalue(24584);
	$url = getvalue(38165)."/device/v1.0/currentData?appId=APPID&language=en&=";

	$curl = curl_init($url);
	curl_setopt($curl, CURLOPT_URL, $url);
	curl_setopt($curl, CURLOPT_POST, true);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

	$headers = array(
   		"Authorization: bearer ".$token,
   		"Content-Type: application/json",
	);
	curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

	$data = "{
		\"deviceSn\": \"".$sn."\"
		}";
	curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
	$resp = curl_exec($curl);
	curl_close($curl);
	return $resp;
}

function logdatenholen($sn)
{
	$token=getvalue(24584);
	$url = getvalue(38165)."/device/v1.0/alertList?appId=APPID&language=en&=";
	//Zeitstempel
    $starttimestamp=mktime(0,0,0,date("m"),date("d"),date("y"));
	$endtimestamp=time();

	$curl = curl_init($url);
	curl_setopt($curl, CURLOPT_URL, $url);
	curl_setopt($curl, CURLOPT_POST, true);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

	$headers = array(
   		"Authorization: bearer ".$token,
   		"Content-Type: application/json",
	);
	curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

	$data = "{
		\"deviceSn\": \"".$sn."\",
		\"endTimestamp\" : \"".$endtimestamp."\",
		\"startTimestamp\" : \"".$starttimestamp."\"		
		}";
	curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
	$resp = curl_exec($curl);
	curl_close($curl);
	return $resp;
}
function logschreiben($geraet,$logdaten)
{
	//level 0:Hinweis, 1:Warnung, 2: Fehler
	//influence 0:kein Einfluss, 1: Produktion, 2: Sicherheit, 3:Produktion&Sicherheit
	$level="";
	$influence="";
	foreach ($logdaten as $eintrag)
	{
		switch ($eintrag["level"])
		{
			case 0: $level="MESSAGE";break;
			case 1: $level="WARNING";break;
			case 2: $level="ERROR";break;
		}
		switch ($eintrag["influence"])
		{
			case 0: $influence="kein Einfluss";break;
			case 1: $influence="Produktion";break;
			case 2: $influence="Sicherheit";break;
			case 3: $influence="Produktion&Sicherheit";break;
		}
                // ich schreibe alle Logeinträge in das SymconLog und dieses in eine MySQL Datenbank. Das muss jeder anders machen
	 	Global_Log_Eintrag_erstellen($level,$geraet,date("d.m.Y G:i:s",$eintrag["alertTime"])." ".$eintrag["alertName"]." ".$influence);
	}
}

//eventuell Token holen
if (time()>=getvalue(52106)) IPS_RunScriptWait(56619); //ScriptID Token holen
//Logdaten Logger
logschreiben("WR Logger",json_decode(logdatenholen("SERIENNUMMER_LOGGER"),true)["alertList"]);
//Wechselrichter
logschreiben("WRr",json_decode(logdatenholen("SERIENNUMMER_WECHSELRICHTER"),true)["alertList"]);
//Modul 1
logschreiben("WR Modul1",json_decode(logdatenholen("SERIENNUMMER_WR-1"),true)["alertList"]);
//Modul 2
logschreiben("WR Modul2",json_decode(logdatenholen("SERIENNUMMER_WR-2"),true)["alertList"]);
//Modul 3
logschreiben("WR Modul3",json_decode(logdatenholen("SERIENNUMMER_WR-3"),true)["alertList"]);
//Modul 4
logschreiben("WR Modul4",json_decode(logdatenholen("SERIENNUMMER_WR-4"),true)["alertList"]);
//Logger
//var_dump(json_decode(datenholen("SERIENNUMMER_LOGGER"),true));
//Wechselrichter
$wrdaten=json_decode(datenholen("SERIENNUMMER_WR"),true);
setvalue(20614,mktime(intval($wrdaten["dataList"][7]["value"]),intval($wrdaten["dataList"][8]["value"]),intval($wrdaten["dataList"][9]["value"]),intval($wrdaten["dataList"][5]["value"]),intval($wrdaten["dataList"][6]["value"]),intval($wrdaten["dataList"][4]["value"])));
setvalue(42688,$wrdaten["dataList"][39]["value"]);

//PV1
setvalue(15569,$wrdaten["dataList"][17]["value"]);
setvalue(10271,$wrdaten["dataList"][21]["value"]);
setvalue(12127,$wrdaten["dataList"][13]["value"]);

//PV2
setvalue(19442,$wrdaten["dataList"][18]["value"]);
setvalue(14759,$wrdaten["dataList"][22]["value"]);
setvalue(39168,$wrdaten["dataList"][14]["value"]);

//PV3
setvalue(20520,$wrdaten["dataList"][19]["value"]);
setvalue(54745,$wrdaten["dataList"][23]["value"]);
setvalue(48708,$wrdaten["dataList"][15]["value"]);

//PV4
setvalue(22639,$wrdaten["dataList"][20]["value"]);
setvalue(44506,$wrdaten["dataList"][24]["value"]);
setvalue(12708,$wrdaten["dataList"][16]["value"]);

Das Skript zum Holen der Daten läuft bei mir alle 5 Minuten, da die Inervalle genau diese 5 Minuten betragen.
Im Webfront schaut das dann bei mir so aus

Grundsätzlich kommen noch wesentlich mehr Werte rüber. Auch von den Anschlüssen. Aber zum einen ist da vieles doppelt und wirklich interessant sind sie nicht. Zumindest nicht für mich.
Bei Fragen oder Anregungen gerne melden.

1 „Gefällt mir“

Danke fürs Teilen, ich schau mir das die nächsten Tage an.
Momentan gibt es leider andere Prioritäten.

Viele Grüße aus dem Unterallgäu
Harry

Hallo harry28 und hfichtinger, ich habe auch einen Solarman von Bosswerk (Mi-600) und die externe Cloud da abgeschaltet, bzw auch IPS umgeleitet, da kommen auch daten an und ich suche, was da geht.
Schaut Euch mal die „config_hide.html“ Seite auf den WR’s an. Dort habe ich mein IPS eingetragen und dort lasse ich einen Server Socket laufen um die Daten im DEBUG zu sehen. Mal sehen ob ich was finde…

Cloud will ich einfach nicht haben !

lg Thomas

ps :

Das klingt sehr interessant. Ich mag auch nicht unbedingt die Cloud. In diesem Fall wäre es verschmerzbar, da nicht systemkritisch.
Ich hab die Seite auch, was hast du da wo eingetragen?

Ich hab das mal probiert und die Hex Daten durch einen Onlinekoverter geschickt. Ok, der kann zwar nicht viel herausfiltern, aber unter anderem steht da die IP drinnen und auch Versionen. Ich hab auch schon was gefunden, wo sich einer die Mühe gemacht hat, den Hex-String aufzudröseln, aber da werd ich nicht ganz schlau

Solis Inverter data logger message (for hybrid model with LAN data logging stick)
Message length 250 bytes: (message 14 bytes, message 130 bytes still to decode!)

Start:
<1byte 0xA5>
Header (13 bytes):
<1byte data length> <3byte flags> <2byte counter> <4byte logger serial number> <3byte flags>
Time data fields:
<4byte datestamp1 (running seconds)> <2byte data logger seconds> <2byte null> <3byte datastamp2 (‘restart’)> <2byte ?> <2byte message counter> <2byte null>
Inverter:
<16byte serial number ASCI + " ">
Data:
100 x 2byte values. Mostly unsigned integer little endian, with factor determined by inspection
offset / value
48: Inverter operating temperature
50: PV 1 voltage
52: PV 2 voltage
54: PV 1 current
56: PV 2 current
58: Inverter AC bus current (phase 1 - assume ph2/3 follow)
64: Inverter AC voltage (phase 1 - assume ph2/3 follow)
70: AC frequency (assume inverter, not meter)
72: ?unknown
74: ?signed integer flag (0/-1)
76: Yield today
78: Total Yield
88: ?
108: Solar Power watts
112: Yield this month
116: Yield last month
120: Yield yesterday
122: Yield this year
126: ?
130: ?
134: ?
138: ? - max inverter current? my model is 4.6kW so 100 amps?
140: date YY
142: date MM
144: date DD
146: time hh
148: time mm
150: time ss
152: Meter grid voltage
154: Meter grid current (don’t believe this value)
156: signed integer - power from/to grid (import is -ve)
158: signed integer flag 0/-1 (import is -1)
160: ?
162: Inverter Battery Voltage
164: Inverter Battery Current (I find this is incorrect - use BMS values)
166: ?
168: Voltage (think this is backup critical load)?
170: Current (ditto)?
172: BMS reported battery SOC
174: BMS SOH
176: BMS battery voltage
178: BMS battery current (agrees with what Pylontech is pushing out)
180: BMS recommended charge current
182: BMS recommended discharge current
188: Load power watts
190: ?
192: Total energy to battery
196: Energy to battery today
198: Energy to battery this month
200: Total energy from battery
204: Energy from battery today
206: ?
208: Total energy imported
212: Energy imported today
214: Total energy exported?
218: Energy exported today?
220: Total energy consumed (load)
224: Energy consumed today (load)
226: ?
229: Model number <1byte read as Hex>
230: Firmware version <3byte read as little endian Hex>
234: ?
244: ?

Ending: <1byte check digit?> <1byte 0x15>

Quelle: Getting Data from Solis Inverter - #30 by Biscuit - Share your Projects! - Home Assistant Community
Was mich allerdings stört, ist dass der Datensatz länger ist.

Es gibt, zumindest bei mir, noch die seite status.html. Da sehe ich nur Striche. Im Sourcecode der Seite ein paar Werte.
Es soll dann noch z.b. eine /status.json und eine /js/status.js geben. Bei mir allerdings nicht.

IP und Version habe ich auch gefunden, mehr noch nicht…

ps :

Man müsste irgendwie den String, den der Socket Server empfängt rausbekommen… Dann könnte man sich „spielen“.

Hallo Tom,

Deine Lösung gefiele mir am Besten, aber ich scheitere momentan an User/Passwort auf der Config_html-Seite. Kannst Du mr auf die Sprünge helfen? Danke.

Viele Grüße aus dem UA
Harry

Probier mal admin/admin

Es kann so einfach sein - vielen Dank, passt.

Gruß Harry

Ich bekomme auch nur die 143 Bytes wie Tom, kann aber nichts damit anfangen.

Gruß
Harry

@hfichtinger:
Hallo,

was versteckt sich denn in Deiner Variablen URL?

Ich versuche gerade Deine Lösung nachzubauen.

API-ID und SecretKey habe ich von SOLARMAN bekommen.

Viele Grüße aus dem Unterallgäu
Harry

das da https://api.solarmanpv.com :slight_smile:

Danke - ich werde heute abend weiter testen.
Bin gerade im Freibad.

Viele Grüße
Harry

Ich taste mich vorwärts: ich bin schon bei
AUTH_INVALID_USERNAME_OR_PASSWORD

Ich habe in der App einen Usernamen und ein Passwort neu vergeben, aber das scheint nicht zu API-ID und SecretKey zu passen. Mal sehen ob ich das alte Passwort noch einmal vergeb kann.

Gruß Harry

Soweit ich meine sollte das schon zusammenpassen. Ich verwende jedenfalls die selben Daten wie in der App

Ist der SecretKey abhängig vom Passwort?
Dann war die Änderung vielleicht dämlich von mir?

Gruß Harry