Daten von Fronius-Wechselrichter an CCU mit PHP

Geschrieben am 23.10.2018, zuletzt geändert am 20.10.2019
In Home » Technik & Elektronik

PHP-Cronjob zum Übertragen der Kenndaten eines Fronius Photovoltaik-Wechselrichters an einen HomeMatic-Zentrale

Zur Steuerung verschiedener Abläufe muss die CCU die aktuellen Daten der PV-Anlage (Status, Produktion, Verbrauch und somit auch Einspeisung bzw. Bezug) kennen.

Diese werden jede Minute von einem PHP-Cronjob auf dem Controller Server aus dem Fronius-Wechselrichter ausgelesen, (dort ebenfalls verarbeitet) und über die XML-API in Systemvariablen der HomeMatic-Zentrale geschrieben.

Systemvariablen

Auf der CCU folgende Systemvariablen anlegen:

Die ise_id der Variablen wird benötigt, um sie später ansprechen zu können.

Auslesen des Wechselrichters

Über die JSON-basierte Fronius Solar-API werden die Kenndaten ausgelesen, sortiert und in die CCU geschoben.

Die Datenlogger-URL für die Produktions-Daten des Wechselrichters lautet

$data_url_production = "http://".HOST_INV."/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceId=".DEV_ID_INVERTER."&DataCollection=CommonInverterData";

Die URL für die Daten des SmartMeters

$data_url_consumption = "http://".HOST_INV."/solar_api/v1/GetMeterRealtimeData.cgiScope=Device&DeviceId=".DEV_ID_METER."&DataCollection=MeterRealtimeData";

Setzen der Systemvariablen in der CCU

Als Beispiel wird über die XML-API der Variable mit der ise_id VAR_STATUS der neue Wert $inverter_statusmsg zugewiesen:

$update_url_status = "https://".HOST_CCU."/addons/xmlapi/statechange.cgi?ise_id=".VAR_STATUS."&new_value=".$inverter_statusmsg;

Skript

Hier das PHP-Skript, das als Cronjob die Aufgabe erledigt. Die Konfiguration in den markierten Zeilen muss angepasst werden.

Dies ist ein Rohgerüst ohne Fehlerbehandlung. "Works for me", macht was draus.
<?php
// cron_pva2ccu.php
// Stefan Onderka, www.onderka.com
// symo.local.lan   192.168.129.X
// homematic.local.lan  192.168.129.Y

// Konfiguration
define("DEBUG_JSON",   false);
define("DEBUG_XMLAPI", false);
define("VERSION_STRING",   "1.1-controller");
// HTTP Host Wechselrichter
define("HOST_INV", "symo.local.lan");
// HTTP Host CCU
define("HOST_CCU", "homematic.local.lan");
// Fronius JSON-API Geräte-ID Wechselrichter
define("DEV_ID_INVERTER",  1);
// Fronius JSON-API Geräte-ID SmartMeter
define("DEV_ID_METER", 0);
// ISE_ID und Name Systemvariable für Produktion
define("VAR_PRODUCTION",   7482);
define("VAR_NAME_PRODUCTION",  "PVA_Produktion");
// ISE_ID und Name Systemvariable für WR-Status
define("VAR_STATUS",   9022);
define("VAR_NAME_STATUS",  "PVA_Status");
// ISE_ID und Name Systemvariable für Verbrauch
define("VAR_CONSUMPTION",  9021);
define("VAR_NAME_CONSUMPTION", "Haus_Stromverbrauch");
// ISE_ID und Name Systemvariable für Einspeisung
define("VAR_FEEDIN",   12511);
define("VAR_NAME_FEEDIN",  "Strom_Einspeisung");
// ISE_ID und Name Systemvariable für Bezug
define("VAR_DRAW", 12512);
define("VAR_NAME_DRAW","Strom_Bezug");

// Fronius Wechselrichter Status-Codes
$inverter_status_codes = array(
   "" => "Kein Status",
   0  => "Sleep",
   1  => "Sleep",
   2  => "Sleep",
   3  => "Sleep",
   4  => "Sleep",
   5  => "Sleep",
   6  => "Start",
   7  => "Produktion",
   8  => "Standby",
   9  => "Bootloader",
   10 => "Fehler",
   11 => "Nicht erreichbar",
   12 => "Nicht erreichbar",
   13 => "CommonINV fehlt",
   14 => "Meter fehlt",
   15 => "MinMax fehlt"
);

// HTTP-Optionen
$opts = array(
  'http' => array(
  'method' => "GET",
  'user_agent' => "PVA2CCU-".VERSION_STRING."/monster.local.lan",
  'timeout' => 5,
  'ignore_errors' => true
   ),
   'ssl'=>array(
  'verify_peer' => false,
  'verify_peer_name' => false,
  'allow_self_signed' => true
   )
);
$context = stream_context_create($opts);

// Fronius JSON-API URLs
$data_url_production= "http://".HOST_INV."/solar_api/v1/GetInverterRealtimeData.cgiScope=Device&DeviceId=".DEV_ID_INVERTER."&DataCollection=CommonInverterData";
$data_url_consumption   = "http://".HOST_INV."/solar_api/v1/GetMeterRealtimeData.cgiScope=Device&DeviceId=".DEV_ID_METER."&DataCollection=MeterRealtimeData";

// HTTP Request ausführen
echo "Reading inverter data from ".HOST_INV."\n";
$data_production_json   = file_get_contents($data_url_production, false, $context);
echo "Reading meter data from ".HOST_INV."\n";
$data_consumption_json  = file_get_contents($data_url_consumption, false, $context);

// JSON-Antwort zu Array konvertieren
$data_production_array  = json_decode($data_production_json, true);
$data_consumption_array = json_decode($data_consumption_json, true);

if ( DEBUG_JSON ) {
   // Debug
   echo "--- prod -------------------------------------------";
   print_r($data_production_array);
   echo "--- cons -------------------------------------------";
   print_r($data_consumption_array);
}

// Werte aus Inverter
$inverter_status= $data_production_array["Body"]["Data"]["DeviceStatus"]["StatusCode"];
$inverter_statusmsg = $inverter_status_codes[$inverter_status];
$today_production   = $data_production_array["Body"]["Data"]["DAY_ENERGY"]["Value"];
$year_production= $data_production_array["Body"]["Data"]["YEAR_ENERGY"]["Value"];

if ( $inverter_status == 7 ) {
   // Produktion
   $current_production = $data_production_array["Body"]["Data"]["PAC"]["Value"];
} else {
   // Keine Produktion
   $current_production = 0;
}

// Werte aus Smart Meter
$current_comsumption_phase1 = $data_consumption_array["Body"]["Data"]["PowerReal_P_Phase_1"];
$current_comsumption_phase2 = $data_consumption_array["Body"]["Data"]["PowerReal_P_Phase_2"];
$current_comsumption_phase3 = $data_consumption_array["Body"]["Data"]["PowerReal_P_Phase_3"];
$current_consumption= $data_consumption_array["Body"]["Data"]["PowerReal_P_Sum"];
$current_consumption= intval($current_consumption * -1);

// Einspeisung
$current_feedin = $current_production - $current_consumption;
if ( $current_feedin < 0 ) {
   // Keine Einspeisung
   $current_feedin = 0;
}

// Bezug
$current_draw = $current_consumption - $current_production;
if ( $current_draw < 0 ) {
   // Kein Bezug
   $current_draw = 0;
}

// Fixes
if ( $current_production == "" ) {
   $current_production = 0;
}

// Variablen in HomeMatic CCU setzen
$update_url_status= "https://".HOST_CCU."/addons/xmlapi/statechange.cgi?ise_id=".VAR_STATUS."&new_value=".$inverter_statusmsg;
$update_url_production= "https://".HOST_CCU."/addons/xmlapi/statechange.cgi?ise_id=".VAR_PRODUCTION."&new_value=".$current_production;
$update_url_consumption   = "https://".HOST_CCU."/addons/xmlapi/statechange.cgi?ise_id=".VAR_CONSUMPTION."&new_value=".$current_consumption;
$update_url_einspeisung   = "https://".HOST_CCU."/addons/xmlapi/statechange.cgi?ise_id=".VAR_FEEDIN."&new_value=".$current_feedin;
$update_url_bezug = "https://".HOST_CCU."/addons/xmlapi/statechange.cgi?ise_id=".VAR_DRAW."&new_value=".$current_draw;

echo "Writing inverter data to ".HOST_CCU."\n";
$request_status_xml   = file_get_contents($update_url_status, false, $context);
$request_production_xml   = file_get_contents($update_url_production, false, $context);
echo "Writing meter data to ".HOST_CCU."\n";
$request_consumption_xml  = file_get_contents($update_url_consumption, false, $context);
$request_einspeisung_xml  = file_get_contents($update_url_einspeisung, false, $context);
$request_bezug_xml= file_get_contents($update_url_bezug, false, $context);

$status_xml   = json_decode(json_encode(simplexml_load_string($request_status_xml)));
$production_xml   = json_decode(json_encode(simplexml_load_string($request_production_xml)));
$consumption_xml  = json_decode(json_encode(simplexml_load_string($request_consumption_xml)));
$einspeisung_xml  = json_decode(json_encode(simplexml_load_string($request_einspeisung_xml)));
$bezug_xml= json_decode(json_encode(simplexml_load_string($request_bezug_xml)));

// Ausgabe
echo "\n";
echo "Status:   ".$inverter_status." (".$inverter_statusmsg.")\n";
echo "Produktion:   ".$current_production." Watt\n";
echo "Verbrauch:".$current_consumption." Watt\n";
echo "Einspeisung:  ".$current_feedin." Watt\n";
echo "Bezug:".$current_draw." Watt\n";

if ( DEBUG_XMLAPI ) {
   // Debug
   print_r($status_xml);
   echo "\n";
   print_r($production_xml);
   echo "\n";
   print_r($consumption_xml);
   echo "\n";
   print_r($einspeisung_xml);
   echo "\n";
   print_r($bezug_xml);
   echo "\n";
}
?>

Status-Codes des Wechselrichters

Die erweiterten Status-Codes ($inverter_status) des Wechselrichters aus der Dokumentation der Fronius-API:

Gesetzte Systemvariablen

Nach dem ersten Durchlauf sind die Werte für die weitere Verwendung verfügbar:

Andere Seiten unter 'Technik & Elektronik'