Hallo
Marc hat mich per PN ersucht meine Scripte zur Abfrage der Akkus über die Konsole zu posten. Mach ich gerne, wobei ich sie nicht mit dem Ziel sie zu sharen gebaut habe. Ist eher nur Quick&Dirty für mich schnell hingedengelt. Laufen tuns echt brav. Bei der Einrichtung kann gut sein das die ein oder andere Variable erst händisch angelegt werden muß. Manches geht von selbst, manches benötigt Handarbeit.- bzw. dann eben in den Scripten die entsprechende ID austauschen. Inline Doku ist auch eher keine vorhanden.
Beginnen tu ma mit dem Seriellen Port und hängen ihn auf einen Splitter.
Am Splitter hängt dann eine Registervariable welche die Schnittstelle zu den Scripten darstellt.
So sieht der relevante Objektbaum aus. Soweit ich mich erinnere müssen die Kategorien Modul 1 - Modul 4 händisch angelegt und die ID dann im Pylontech_Receive Data eingetragen werden. Die Variablen darin müßten dann automatisch angelegt werden.
Pylontech_SendData wird periodisch aufgerufen (ich triggere es bei mir synchron mit der Datenabfrage vom Wechselrichter) , geht aber natürlich acuh per Timer.
Dieses Script schickt die Abfragebefehle zu den Akkus.
<?php
// check if Pylon is in Console Mode
if (GetValue(19666 /*[PV\Batterie\ConsoleModeAktive]*/) == False) {
IPS_Setproperty (18969 /*[Pylon_Serial_COM12]*/,'BaudRate',1200);
IPS_ApplyChanges(18969 /*[Pylon_Serial_COM12]*/);
IPS_Sleep (1000);
$StringToSend = chr(0x7E).chr(0x32).chr(0x30).chr(0x30).chr(0x31).chr(0x34).chr(0x36).chr(0x38).chr(0x32).chr(0x43).chr(0x30).chr(0x30).chr(0x34).chr(0x38).chr(0x35).chr(0x32).chr(0x30).chr(0x46).chr(0x43).chr(0x43).chr(0x33).chr(0x0D);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (1000);
IPS_Setproperty (18969 /*[Pylon_Serial_COM12]*/,'BaudRate',115200);
IPS_ApplyChanges(18969 /*[Pylon_Serial_COM12]*/);
IPS_Sleep (1000);
$StringToSend = chr(0x0D).chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
$StringToSend = chr(0x0D).chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
$StringToSend = chr(0x0D).chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
}
$StringToSend = "pwr".chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
$StringToSend = "stat 1".chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
$StringToSend = "stat 2".chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
$StringToSend = "stat 3".chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
$StringToSend = "stat 4".chr(0x0A);
REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
IPS_Sleep (100);
IPS_RunScriptWait(59710 /*[PV\Batterie\Scripte\Pylon_AverageData]*/);
#$StringToSend = "getpwr 4".chr(0x0A);
#REGVar_SendText(35339 /*[PV\Batterie\Register Variable]*/, $StringToSend);
Dann gibt es Pylontech_ ReceiveData welcehs über den Splitter-> Registervariable die Antwort vond en Akkus erhält.
<?php
$idModul1 = 20944 /*[PV\Batterie\Modul 1]*/;
$idModul2 = 44776 /*[PV\Batterie\Modul 2]*/;
$idModul3 = 42742 /*[PV\Batterie\Modul 3]*/;
$idModul4 = 35089 /*[PV\Batterie\Modul 4]*/;
$strReceived = $_IPS['VALUE'] ;
#echo $strReceived;
if (substr($strReceived,2,5) == 'pylon') {
SetValue(19666 /*[PV\Batterie\ConsoleModeAktive]*/,true);
};
// Auswerten von 'pwr' Anfrage
if (substr($strReceived,0,3) == 'pwr') {
$posStart = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."1");
$posEnd = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."2");
$strReceivedCut = substr($strReceived,$posStart, $posEnd- $posStart);
processPWR($strReceivedCut,$idModul1);
$posStart = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."2");
$posEnd = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."3");
$strReceivedCut = substr($strReceived,$posStart, $posEnd- $posStart);
processPWR($strReceivedCut,$idModul2);
$posStart = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."3");
$posEnd = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."4");
$strReceivedCut = substr($strReceived,$posStart, $posEnd- $posStart);
processPWR($strReceivedCut,$idModul3);
$posStart = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."4");
$posEnd = strpos($strReceived, chr(0x0D).chr(0x0D).chr(0x0A)."5");
$strReceivedCut = substr($strReceived,$posStart, $posEnd- $posStart);
processPWR($strReceivedCut,$idModul4);
}
// Auswerten von 'stat' Anfrage kommt viel Zeugs, Cycle Times sind ggfl. brauchbar
if (substr($strReceived,0,4) == 'stat') { //String: stat 1
$posStart = strpos($strReceived,'CYCLE Times') +17; //String: CR><LF>CYCLE Times : 2<CR><CR><LF>
$posEnd = strpos($strReceived,chr(0x0D).chr(0x0D),$posStart);
$Cycles = intval(substr($strReceived,$posStart,$posEnd- $posStart));
if (substr($strReceived,5,1) == '1') { // 1 is the module #
$idCycles = GetOrCreateVariable('Cycles',1,"", "","",true, $idModul1,"10",false);
SetValue($idCycles,$Cycles);
}
if (substr($strReceived,5,1) == '2') { // 1 is the module #
$idCycles = GetOrCreateVariable('Cycles',1,"", "","",true, $idModul2,"10",false);
SetValue($idCycles,$Cycles);
}
if (substr($strReceived,5,1) == '3') { // 1 is the module #
$idCycles = GetOrCreateVariable('Cycles',1,"", "","",true, $idModul3,"10",false);
SetValue($idCycles,$Cycles);
}
if (substr($strReceived,5,1) == '4') { // 1 is the module #
$idCycles = GetOrCreateVariable('Cycles',1,"", "","",true, $idModul4,"10",false);
SetValue($idCycles,$Cycles);
}
// echo substr($strReceived,$posStart,$posEnd- $posStart);
}
function processPWR($dataString, $idModul) {
$idVolt = GetOrCreateVariable('Spannung',2,"", "~Volt","",true, $idModul,"1",false);
$idCurr = GetOrCreateVariable('Strom',2,"", "~Ampere","",true, $idModul,"2",false);
$idSOC = GetOrCreateVariable('SOC',2,"", "Prozent","",true, $idModul,"3",false);
$idTemp = GetOrCreateVariable('Temperatur',2,"", "~Temperature","",true, $idModul,"4",false);
$idLoVolt = GetOrCreateVariable('LowestVoltage',2,"", "~Volt","",true, $idModul,"5",false);
$idHighVolt = GetOrCreateVariable('HighestVoltage',2,"", "~Volt","",true, $idModul,"6",false);
$idCharge = GetOrCreateVariable('OperationMode',3,"", "","",false, $idModul,"9",false);
$idStatusVolt = GetOrCreateVariable('StatusSpannung',0,"", "~Alert","",true, $idModul,"7",false);
$idStatusCurrent = GetOrCreateVariable('StatusStrom',0,"", "~Alert","",true, $idModul,"8",false);
$idStatusTemp = GetOrCreateVariable('StatusTemperatur',0,"", "~Alert","",true, $idModul,"9",false);
$dataString = trim($dataString);
$dataString = str_replace(" ", " ",$dataString);
$dataString = str_replace(" ", " ",$dataString);
$dataString = str_replace(" ", " ",$dataString);
$dataString = str_replace(" ", " ",$dataString);
#echo $dataString;
#echo chr(0x0D).chr(0x0A);
$arryData = explode (" ",$dataString);
#print_r($arData1);
SetValue ($idVolt, floatval($arryData[1]) / 1000);
SetValue ($idCurr, floatval($arryData[2]) / 1000);
SetValue ($idTemp, floatval($arryData[3])/ 1000);
SetValue ($idLoVolt, floatval($arryData[6])/ 1000);
SetValue ($idHighVolt, floatval($arryData[7])/ 1000);
if ($arryData[8] == "Dischg") {
SetValue($idCharge,"wird entladen");
}
else {
SetValue($idCharge,"wird geladen");
}
if ($arryData[9] == "Normal") {
SetValue($idStatusVolt,false);
}
else {
SetValue($idStatusVolt,true);
}
if ($arryData[10] == "Normal") {
SetValue($idStatusCurrent,false);
}
else {
SetValue($idStatusCurrent,true);
}
if ($arryData[11] == "Normal") {
SetValue($idStatusTemp,false);
}
else {
SetValue($idStatusTemp,true);
}
SetValue ($idSOC, floatval($arryData[12]));
}
// ------------------------- IPS GRUNFUNKTIONEN -------------------------------------------------------------------------------------------------------------------------
// Erstellt eine Variable, wenn diese noch nicht existiert
function GetOrCreateVariable($name, $vtyp, $ident, $profil, $ascript, $log, $parentID, $position, $logVisual) // erstellt eine Variable, wenn es noch nicht exestiert
/*
Wert 1 = Name
Wert 2 = Variablentyp
Wert 3 = Variablen-Ident
Wert 4 = Variablenprofil
Wert 5 = ScriptID
Wert 6 = Logging der Daten (True/False)
Wert 7 = Übergeordnete Instanz, wo die Variable angelegt werden soll
Wert 8 = Reihenfolge / Sortierung der Variablen
Wert 9 = Anzeige der Variable in der Visualisierung im Webfront deaktiveren oder aktivieren
*/
{
$ObjId = @IPS_GetObjectIDByName($name, $parentID);
if ($ObjId === false)
{
$ObjId = IPS_CreateVariable($vtyp);
IPS_SetName($ObjId, $name); //Namen vergeben
IPS_SetIdent($ObjId, $ident); //ObjectIdent vergeben
IPS_SetParent($ObjId, $parentID); //Variable unter die Instantz verschieben
@IPS_SetVariableCustomProfile($ObjId, $profil); //Variablen-Profil zuordnen
@IPS_SetVariableCustomAction($ObjId, $ascript); //Verknüpft das Script mit der Variable als Actionscript
// Archive Control ID herrausfinden
foreach(IPS_GetInstanceList ( ) as $m_id) //Durchsucht alle Instanzen und gibt die InstanzID an $i_id weiter
{
$typ = IPS_GetInstance($m_id)['ModuleInfo']['ModuleName']; //Fragt die Instanzen nach den Modulnamen ab
if ($typ =="Archive Control") $modul_id = $m_id; //Wenn die Instanz den Modulnamen "Archive Control" hat, dann schreibe die ID in $modul_id
}
$logging = AC_GetLoggingStatus($modul_id,$ObjId);
if ($logging != 1)
{
AC_SetLoggingStatus($modul_id, $ObjId, $log);
AC_SetGraphStatus($modul_id, $ObjId, $logVisual);
IPS_ApplyChanges($modul_id);
}// Ende Logging
IPS_SetPosition($ObjId, $position);
}
return $ObjId;
}
Pylontech _Averagedata ist nicht unbedingt notwendig, es macht nur ein paar nachfolgende Berechnungen und bedient Overall Statusflags.
Die IDs der referenzierten Variablen sind händisch einzupflegen.Hatte keine Lust da was generisches zu bauen.
<?php
{
$idPylon = 28031 /*[PV\Batterie]*/;
$idVolt = GetOrCreateVariable('Spannung',2,"", "~Volt","",true, $idPylon,"1",false);
$idCurrent = GetOrCreateVariable('Strom',2,"", "~Ampere","",true, $idPylon,"2",false);
$idSOC = GetOrCreateVariable('SOC',2,"", "Prozent","",true, $idPylon,"3",false);
$idCycles = GetOrCreateVariable('Cycles',2,"", "","",true, $idPylon,"4",false);
$idPower = GetOrCreateVariable('Power',2,"", "","",true, $idPylon,"5",false);
$idDiffVolt1 = GetOrCreateVariable('maxCellDifference1',2,"", "my_mVolt","",true, $idPylon,"1",false);
$idDiffVolt2 = GetOrCreateVariable('maxCellDifference2',2,"", "my_mVolt","",true, $idPylon,"1",false);
$idDiffVolt3 = GetOrCreateVariable('maxCellDifference3',2,"", "my_mVolt","",true, $idPylon,"1",false);
$idDiffVolt4 = GetOrCreateVariable('maxCellDifference4',2,"", "my_mVolt","",true, $idPylon,"1",false);
$idStatusTemp = GetOrCreateVariable('Status Temperatur',0,"", "~Alert","",true, $idPylon,"1",false);
$idStatusSpannung = GetOrCreateVariable('Status Spannung',0,"", "~Alert","",true, $idPylon,"1",false);
$idStatusStrom = GetOrCreateVariable('Status Strom',0,"", "~Alert","",true, $idPylon,"1",false);
SetValue($idVolt, (GetValue(32839 /*[PV\Batterie\Modul 1\Spannung]*/) + GetValue(21456 /*[PV\Batterie\Modul 2\Spannung]*/) + GetValue(23341 /*[PV\Batterie\Modul 3\Spannung]*/) + GetValue(28610 /*[PV\Batterie\Modul 4\Spannung]*/))/4);
SetValue($idCurrent, GetValue(17580 /*[PV\Batterie\Modul 1\Strom]*/) + GetValue(22124 /*[PV\Batterie\Modul 2\Strom]*/) + GetValue(59611 /*[PV\Batterie\Modul 3\Strom]*/) + GetValue(53759 /*[PV\Batterie\Modul 4\Strom]*/));
SetValue($idSOC, (GetValue(29307 /*[PV\Batterie\Modul 1\SOC]*/) + GetValue(26857 /*[PV\Batterie\Modul 2\SOC]*/) + GetValue(39278 /*[PV\Batterie\Modul 3\SOC]*/) + GetValue(32048 /*[PV\Batterie\Modul 4\SOC]*/))/4);
SetValue($idCycles, (GetValue(40579 /*[PV\Batterie\Modul 1\Cycles]*/) + GetValue(58497 /*[PV\Batterie\Modul 2\Cycles]*/) + GetValue(17488 /*[PV\Batterie\Modul 3\Cycles]*/) + GetValue(53570 /*[PV\Batterie\Modul 4\Cycles]*/))/4);
SetValue($idPower, GetValue($idVolt) * GetValue($idCurrent)*-1);
SetValue($idDiffVolt1, (GetValue(19520 /*[PV\Batterie\Modul 1\HighestVoltage]*/) - GetValue(48112 /*[PV\Batterie\Modul 1\LowestVoltage]*/))*1000);
SetValue($idDiffVolt2, (GetValue(19130 /*[PV\Batterie\Modul 2\HighestVoltage]*/) - GetValue(55992 /*[PV\Batterie\Modul 2\LowestVoltage]*/))*1000);
SetValue($idDiffVolt3, (GetValue(53629 /*[PV\Batterie\Modul 3\HighestVoltage]*/) - GetValue(17956 /*[PV\Batterie\Modul 3\LowestVoltage]*/))*1000);
SetValue($idDiffVolt4, (GetValue(31395 /*[PV\Batterie\Modul 4\HighestVoltage]*/) - GetValue(42576 /*[PV\Batterie\Modul 4\LowestVoltage]*/))*1000);
SetValueBoolean($idStatusTemp, (GetValueBoolean(29152 /*[PV\Batterie\Modul 1\StatusTemperatur]*/) or GetValueBoolean(58775 /*[PV\Batterie\Modul 2\StatusTemperatur]*/) or GetValueBoolean(35619 /*[PV\Batterie\Modul 3\StatusTemperatur]*/) or GetValue(24392 /*[PV\Batterie\Modul 4\StatusTemperatur]*/))/4);
SetValueBoolean($idStatusSpannung, (GetValueBoolean(27744 /*[PV\Batterie\Modul 1\StatusSpannung]*/) or GetValueBoolean(57924 /*[PV\Batterie\Modul 2\StatusSpannung]*/) or GetValueBoolean(45008 /*[PV\Batterie\Modul 3\StatusSpannung]*/) or GetValue(34118 /*[PV\Batterie\Modul 4\StatusSpannung]*/))/4);
SetValueBoolean($idStatusStrom, (GetValueBoolean(47077 /*[PV\Batterie\Modul 1\StatusStrom]*/) or GetValueBoolean(43578 /*[PV\Batterie\Modul 2\StatusStrom]*/) or GetValueBoolean(37541 /*[PV\Batterie\Modul 3\StatusStrom]*/) or GetValue(31175 /*[PV\Batterie\Modul 4\StatusStrom]*/))/4);
}
// ------------------------- IPS GRUNFUNKTIONEN -------------------------------------------------------------------------------------------------------------------------
// Erstellt eine Variable, wenn diese noch nicht existiert
function GetOrCreateVariable($name, $vtyp, $ident, $profil, $ascript, $log, $parentID, $position, $logVisual) // erstellt eine Variable, wenn es noch nicht exestiert
/*
Wert 1 = Name
Wert 2 = Variablentyp
Wert 3 = Variablen-Ident
Wert 4 = Variablenprofil
Wert 5 = ScriptID
Wert 6 = Logging der Daten (True/False)
Wert 7 = Übergeordnete Instanz, wo die Variable angelegt werden soll
Wert 8 = Reihenfolge / Sortierung der Variablen
Wert 9 = Anzeige der Variable in der Visualisierung im Webfront deaktiveren oder aktivieren
*/
{
$ObjId = @IPS_GetObjectIDByName($name, $parentID);
if ($ObjId === false)
{
$ObjId = IPS_CreateVariable($vtyp);
IPS_SetName($ObjId, $name); //Namen vergeben
IPS_SetIdent($ObjId, $ident); //ObjectIdent vergeben
IPS_SetParent($ObjId, $parentID); //Variable unter die Instantz verschieben
@IPS_SetVariableCustomProfile($ObjId, $profil); //Variablen-Profil zuordnen
@IPS_SetVariableCustomAction($ObjId, $ascript); //Verknüpft das Script mit der Variable als Actionscript
// Archive Control ID herrausfinden
foreach(IPS_GetInstanceList ( ) as $m_id) //Durchsucht alle Instanzen und gibt die InstanzID an $i_id weiter
{
$typ = IPS_GetInstance($m_id)['ModuleInfo']['ModuleName']; //Fragt die Instanzen nach den Modulnamen ab
if ($typ =="Archive Control") $modul_id = $m_id; //Wenn die Instanz den Modulnamen "Archive Control" hat, dann schreibe die ID in $modul_id
}
$logging = AC_GetLoggingStatus($modul_id,$ObjId);
if ($logging != 1)
{
AC_SetLoggingStatus($modul_id, $ObjId, $log);
AC_SetGraphStatus($modul_id, $ObjId, $logVisual);
IPS_ApplyChanges($modul_id);
}// Ende Logging
IPS_SetPosition($ObjId, $position);
}
return $ObjId;
}
Ach ja, bevor du beginnst solltest erst mir einer beliebigen Terminalapplikation überprüfen ob Kabel/Schnittstellen und Pylonkonfiguration in Ordnung sind. Sonst suchst ewig im IPS rum und das Problem liegt an der Hardware. Im PV Forum wird ja auch gerne mit den Pylontech gearbeitet. Da gibt es jede Menge Threads mit Infos dazu.
viel Erfolg
Bernhard