Hilfe bei HTTP Datenabfrage Fenecon

Hallo Community,

ich lerne gerade erst die Basics von IPS und PHP daher bedanke ich mich gleich schonmal im voraus für die Hilfe. Ausgangspunkt ist wie folgend:

Ich besitze einen Fenecon Stromspeicher welche mir Daten über Energieverbrauch, Speicherladung, PV-Erzeugung usw. liefert. Diesen versuche ich über die API auszulesen, das funktioniert auch soweit jedoch werden mir die Infos nicht in einer einzigen Abfrage zur Verfügung gestellt. Ich muss jeden einzelnen Wert abfragen (Wenn es einen besseren weg gibt bin ich jederzeit für Tipps dankbar (Modbus evtl.?)). Ich würde die Werte gerne so aktuell wie möglich halten und lasse das Skript zur abfrage daher alle 5 Sekunden neu ausführen.

Nun zum eigentlichen Problem: Teilweise dauert die Abfrage des Speichers etwas länger und und das Skript wird während es noch läuft erneut gestartet. Dadurch wird IPS teilweise etwas träge und ich bekomme auch Fehlermeldungen das zu viele Skripts gleichzeitig ausgeführt werden.

Dauert eine solche Abfrage einfach seine Zeit und die einfachste Lösung ist die Abfragezeit zu erhöhen?
Gibt es einen einfacheren weg an die Variablen zu kommen ?
Kann ich das Skript automatisch erneut starten wenn es „fertig“ ist ?

hier noch der Code:

<?php

$VerbrauchGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePower"),true);
$VerbrauchL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePowerL1"),true);
$VerbrauchL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePowerL2"),true);
$VerbrauchL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePowerL3"),true);


$NetzGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePower"),true);
$NetzL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePowerL1"),true);
$NetzL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePowerL2"),true);
$NetzL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePowerL3"),true);


$SpeicherGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePower"),true);
$SpeicherL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePowerL1"),true);
$SpeicherL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePowerL2"),true);
$SpeicherL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePowerL3"),true);
$SpeicherLadung = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssSoc"),true);

$PVGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePower"),true);
$PVL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePowerL1"),true);
$PVL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePowerL2"),true);
$PVL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePowerL2"),true);

$NetzbezugWh = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridBuyActiveEnergy"),true);
$NetzbezugkWh = $NetzbezugWh ['value'] * 0.001;

$NetzeinspeisungWh = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridSellActiveEnergy"),true);
$NetzeinspeisungkWh = $NetzeinspeisungWh ['value'] * 0.001;

$ErzeugungWh = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionActiveEnergy"),true);
$ErzeugungkWh = $ErzeugungWh ['value'] * 0.001;

//Verbrauch
setvalue(17292, $VerbrauchGesamt ['value']);
setvalue(38324, $VerbrauchL1 ['value']);
setvalue(37695, $VerbrauchL2 ['value']);
setvalue(33962, $VerbrauchL3 ['value']);

//NETZ
setvalue(10625, $NetzGesamt ['value']);
setvalue(59789, $NetzL1 ['value']);
setvalue(31634, $NetzL2 ['value']);
setvalue(52611, $NetzL3 ['value']);

if($NetzGesamt ['value']  > 0 ) {
    setvalue(11804, $NetzGesamt ['value']);
    setvalue(26301, 0);
    }
elseif ($NetzGesamt ['value']  < 0 ) {
        setvalue(11804, 0);
        setvalue(26301, $NetzGesamt ['value']*-1);
    }
else {
    setvalue(11804, 0);
    setvalue(26301, 0);
    }

//SPEICHER
setvalue(17660, $SpeicherGesamt ['value']);
setvalue(56736, $SpeicherL1 ['value']);
setvalue(58141, $SpeicherL2 ['value']);
setvalue(41429, $SpeicherL3 ['value']);
setvalue(36552, $SpeicherLadung ['value']);

if($SpeicherGesamt ['value']  > 0 ) {
    setvalue(31972, 0);
    setvalue(29347, $SpeicherGesamt ['value']);
    }
elseif ($SpeicherGesamt ['value']  < 0 ) {
        setvalue(31972, $SpeicherGesamt ['value']*-1);
        setvalue(29347, 0);
    }
else {
    setvalue(31972, 0);
    setvalue(29347, 0);
    }

//PV
setvalue(24122, $PVGesamt ['value']);
setvalue(21979, $PVL1 ['value']);
setvalue(54932, $PVL2 ['value']);
setvalue(17750, $PVL3 ['value']);

//Energie
setvalue(52292, $NetzbezugkWh);
setvalue(51061, $NetzeinspeisungkWh);
setvalue(41466, $ErzeugungkWh);

Wodurch startest du das Script denn aktuell? Timer alle ~10 Sekunden, aber es braucht 15 Sekunden?

Hier gegen hilft a) Timer hoch stellen, b) Semaphore IPS_SemaphoreEnter — IP-Symcon :: Automatisierungssoftware

Zudem würde ich prüfen, ob man ggf. über eine URL wie:

http://x:user@192.168.250.58:80/rest/allChannels/

alles gleichzeitig abfragen kann und dann selbst zerlegt. Das spart den ganzen http overhead.

1 „Gefällt mir“

Eine URL um alle Datenpunkte auf einmal auszulesen gibt es laut Dokumentation nicht.

Ich habe das Skript nochmals angepasst jetzt funktionierts scheinbar stabil.
Davor wurde das Skript durch ein zyklisches Ereignis gestartet, jetzt wird es direkt aus dem Skript heraus gestartet. Das denke ich war das Hauptproblem :man_shrugging:

Mit der Sempaphore Funktion bekomme ich jetzt aber auch eine Fehlermeldung wenn’s mal länger als 5 Sekunden gedauert hat.

Danke dir !

<?php

$Time = 5000;
if ( IPS_SemaphoreEnter("Abfrage", $Time))
{

$VerbrauchGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePower"),true);
$VerbrauchL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePowerL1"),true);
$VerbrauchL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePowerL2"),true);
$VerbrauchL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ConsumptionActivePowerL3"),true);


$NetzGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePower"),true);
$NetzL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePowerL1"),true);
$NetzL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePowerL2"),true);
$NetzL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridActivePowerL3"),true);


$SpeicherGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePower"),true);
$SpeicherL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePowerL1"),true);
$SpeicherL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePowerL2"),true);
$SpeicherL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssActivePowerL3"),true);
$SpeicherLadung = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/EssSoc"),true);

$PVGesamt = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePower"),true);
$PVL1 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePowerL1"),true);
$PVL2 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePowerL2"),true);
$PVL3 = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionAcActivePowerL2"),true);

$NetzbezugWh = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridBuyActiveEnergy"),true);
$NetzbezugkWh = $NetzbezugWh ['value'] * 0.001;

$NetzeinspeisungWh = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/GridSellActiveEnergy"),true);
$NetzeinspeisungkWh = $NetzeinspeisungWh ['value'] * 0.001;

$ErzeugungWh = json_decode(
        file_get_contents("http://x:user@192.168.250.58:80/rest/channel/_sum/ProductionActiveEnergy"),true);
$ErzeugungkWh = $ErzeugungWh ['value'] * 0.001; 




// echo "erfolgreich Abgefragt";
IPS_SemaphoreLeave("Abfrage");
} else {
    echo "abfrage Fehlgeschlagen";
}

//Verbrauch
setvalue(17292, $VerbrauchGesamt ['value']);
setvalue(38324, $VerbrauchL1 ['value']);
setvalue(37695, $VerbrauchL2 ['value']);
setvalue(33962, $VerbrauchL3 ['value']);

//NETZ
setvalue(10625, $NetzGesamt ['value']);
setvalue(59789, $NetzL1 ['value']);
setvalue(31634, $NetzL2 ['value']);
setvalue(52611, $NetzL3 ['value']);

if($NetzGesamt ['value']  > 0 ) {
    setvalue(11804, $NetzGesamt ['value']);
    setvalue(26301, 0);
    }
elseif ($NetzGesamt ['value']  < 0 ) {
        setvalue(11804, 0);
        setvalue(26301, $NetzGesamt ['value']*-1);
    }
else {
    setvalue(11804, 0);
    setvalue(26301, 0);
    }

//SPEICHER
setvalue(17660, $SpeicherGesamt ['value']);
setvalue(56736, $SpeicherL1 ['value']);
setvalue(58141, $SpeicherL2 ['value']);
setvalue(41429, $SpeicherL3 ['value']);
setvalue(36552, $SpeicherLadung ['value']);

if($SpeicherGesamt ['value']  > 0 ) {
    setvalue(31972, $SpeicherGesamt ['value']);
    setvalue(29347, 0);
    }
elseif ($SpeicherGesamt ['value']  < 0 ) {
        setvalue(31972, 0);
        setvalue(29347, $SpeicherGesamt ['value']*-1);
    }
else {
    setvalue(31972, 0);
    setvalue(29347, 0);
    }

//PV
setvalue(24122, $PVGesamt ['value']);
setvalue(21979, $PVL1 ['value']);
setvalue(54932, $PVL2 ['value']);
setvalue(17750, $PVL3 ['value']);

//Energie
setvalue(52292, $NetzbezugkWh);
setvalue(51061, $NetzeinspeisungkWh);
setvalue(41466, $ErzeugungkWh);

IPS_Sleep($Time);
IPS_RunScript(35586);

Welche Fehlermeldung kommt denn genau? Wieso startest du das Script denn direkt aus sich selbst? Und wie willst du das extern unterbrechen können? Brauchst du die Daten wirklich so schnell, dass alle 2~5 Sekunden notwendig sind?

Modbus Fenecon
Das hier schon probiert?
Beim Mobus brauchst du dich um nichts zu kümmern.

image

1 „Gefällt mir“

Sorry gemeint war keine richtige Fehlermeldung sondern eine Meldung wenn die Semaphore fehlschlägt. Die Daten hätte ich doch gern so aktuell wie möglich da diese sich auch in der Visualisierung angezeigt werden.
Was ist denn die eleganteste Art ein Skript zyklisch zu starten ? (Wie schon erwähnt lerne ich das ganze erst, das ist mein erstes Skript)

Wie lange braucht das Script denn?

$time_start = microtime(true);

// hier das gesamte SCript

$time_end = microtime(true);
$time = $time_end - $time_start;
print $time;

Zyklisch fände ich schon besser. Entsprechend mit Semaphore schützen und eine Zeit finden, die etwas über der durchschnittlichen Laufzeit liegt.

Habs ein paar mal ausgeführt. Dauert immer unterschiedlich zwischen 4-7 Sekunden. Wahrscheinlich ist es wirklich das einfachste nur alle 10 Sekunden abzufragen.

Habs gerade ausprobiert. Das funktioniert super, hätt ich mir das Skript sparen können :grin:
Ich werde hier noch ein paar Datenpunkte hinzufügen und über Modbus die Daten auslesen

Danke !

Falls du noch die einzeln String-Werte benötigst

<?php
$debug = false;

$apiUrl = "http://192.168.0.15:80/rest/channel/charger1/(.*)(ActualPower|Voltage|Current|ActualEnergy)";
$ch = curl_init($apiUrl); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_HTTPHEADER,  
            ["Authorization:Basic eDp1c2Vy"]); 
$response = curl_exec($ch); 
if (curl_errno($ch)) { 
    echo "Curl error: " . curl_error($ch); 
} 
curl_close($ch); 
  
$data = json_decode($response, true); 
  
if ($data) { 
    if ($debug) print_r($data); 
} else { 
    echo "Error fetching data from GitHub API."; 
} 

for ($i=0;$i<count($data);$i++)
    {
    if ($debug) echo $data[$i]['address']." ";
    if ($debug) echo $data[$i]['value']."\n";
    switch ($data[$i]['address'])
            {
            case "charger1/Voltage":
                $a = $data[$i]['value']/1000;
                SetValue(13260,$a);
                break;

            case "charger1/ActualPower":
                $a = $data[$i]['value']/1000;
                SetValue(32682,$a);
                break;

            case "charger1/ActualEnergy":
                $a = $data[$i]['value']/1000;
                SetValue(55391,$a);
                break;

            case "charger1/Current":
                $a = $data[$i]['value']/1000;
                SetValue(27238,$a);
                break;

            default:
                break;
            }
    }
ips_Sleep(2000);

$apiUrl = "http://192.168.0.15:80/rest/channel/charger0/(.*)(ActualPower|Voltage|Current|ActualEnergy)";
$ch = curl_init($apiUrl); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_HTTPHEADER,  
            ["Authorization:Basic eDp1c2Vy"]); 
$response = curl_exec($ch); 
if (curl_errno($ch)) { 
    echo "Curl error: " . curl_error($ch); 
} 
curl_close($ch); 
  
$data = json_decode($response, true); 
  
if ($data) { 
    if ($debug) print_r($data); 
} else { 
    echo "Error fetching data from GitHub API."; 
} 

for ($i=0;$i<count($data);$i++)
    {
    if ($debug) echo $data[$i]['address']." ";
    if ($debug) echo $data[$i]['value']."\n";
    switch ($data[$i]['address'])
            {
            case "charger0/Voltage":
                $a = $data[$i]['value']/1000;
                SetValue(25213,$a);
                break;

            case "charger0/ActualPower":
                $a = $data[$i]['value']/1000;
                SetValue(55393,$a);
                break;

            case "charger0/ActualEnergy":
                $a = $data[$i]['value']/1000;
                SetValue(35258,$a);
                break;

            case "charger0/Current":
                $a = $data[$i]['value']/1000;
                SetValue(10320,$a);
                break;

            default:
                break;
            }
    }
1 „Gefällt mir“

Kann man mit dieser URL doch alles auf einmal abrufen?

Noch nicht probiert, Modbus war einfacher.
Das ist meine Modbus Vorlage
modbus (2).json (16,5 KB)

1 „Gefällt mir“

Ja, die API unterstützt die Angabe eines regulären Ausdrucks sowohl für die Komponente (z. B. _sum, meter0, charger0, etc.) als auch den Channel (z. B. ActivePower oder ActualPower). Im Beispiel:

charger1/(.*)(ActualPower|Voltage|Current|ActualEnergy)

Wer es ganz genau wissen will: hier ist der Code dafür in OpenEMS → openems/io.openems.edge.controller.api.rest/src/io/openems/edge/controller/api/rest/RestHandler.java at develop · OpenEMS/openems · GitHub

Gruß,
Stefan

1 „Gefällt mir“