Stromzähler auslesen mit COM-1 Ethernet-Modul - funktioniert fast...

Hallo Leute,
habe mir gestern IP-Symcom gekauft und weil meine Sensoren noch nicht da sind einfach mal geschaut was ich schon da habe:
Webcam an der Haustür tut.
Davis Wetterstation über WSWin tut :slight_smile:
Aber an meinem Stromzähler hänge ich gerade ein wenig, kann mir evtl. jemand ein bisschen weiterhelfen? Wäre nett…

Habe alles mal durchgeschaut was ich im Forum zu COM-1 gefunden habe, hauptsächlich geholfen hat dieser Thread:

Ich blicks aber noch nicht ganz…

Vorhanden ist ein eHZ-Zähler der ENBW.
Laut ENBW gibt der garkeine Daten raus, mit EDL-Cockpit zeigt er mir aber den Stromverbrauch an. Leider sonst nicht viel…

Ich verwende einen optischen Lesekopf von CO.MET und den Netzwerk-Adapter COM-1.
Mit EDL-Cockpit funktioniert die Verbindung einwandfrei, aber die Software ist nicht so wirklich der Brüller.

Habe mir einen Client-Socket installiert, IP 192.168.5.139 (mein COM-1) und Port 5000.
Im Debug-Modus gibt es folgende Daten:

28.11.2013 07:36:15.00 |             RECEIVED | /EMH5----eHZ-E0028E

1-0:0.0.0*255(20570795)
1-0:1.8.1*255(020328.2305)
1-0:2.8.1*255(008337.8534)
1-0:96.5.5*255(82)
0-0:96.1.255*255(0002240640)
!
  15721818
DE0000000000000000000000000000007

28.11.2013 07:36:16.00 |             RECEIVED | /EMH5----eHZ-E0028E

1-0:0.0.0*255(20570795)
1-0:1.8.1*255(020328.2308)
1-0:2.8.1*255(008337.8534)
1-0:96.5.5*255(82)
0-0:96.1.255*255(0002240640)
!
  15721819
DE0000000000000000000000000000007

28.11.2013 07:36:18.00 |             RECEIVED | /EMH5----eHZ-E0028E

1-0:0.0.0*255(20570795)
1-0:1.8.1*255(020328.2311)
1-0:2.8.1*255(008337.8534)
1-0:96.5.5*255(82)
0-0:96.1.255*255(0002240640)
!

1-0:0.0.0 dürfte die Zählernummer sein?
1-0:1.8.1 ist der Bezug
1-0:2.8.1 ist die Einspeisung
1-0:96.5.5 ist der Status
0-0:96.1 Fabriknummer?

Nachdem die Daten angezeigt werden habe ich mir eine Registervariable angelegt
Übergeordnete Instanz ist der obige Socket. Gehe ich auf Debug werden hier dieselben Werte angezeigt.
Mit Ziel-ID konnte ich nicht viel anfangen, habe da einfach mal Zähler ausgewählt, Zähler ist mein Script.

Die Daten kommen im Sekundentakt, anscheinend wird jetzt das Script Zähler jede Sekunde abgearbeitet.

Das Script habe ich aus dem genannten Thread kopiert und leicht angepasst (sorry, bin noch absoluter Einsteiger):

<?
$eHZdata = array("1-0:0.0.0*255" => 27454, // Zaehlernummer
                     "1-0:1.8.1*255" => 28174, // Strom Bezug
                     "1-0:2.8.1*255" => 25310, // Strom Einspeisung
                     "1-0:96.5.5*255" => 59298, // Status Hex
                     "0-0:96.1.255*255" => 22074, // Fabriknummer
                      );

$Netzperiodendauer = 0; // VariablenID der Obis Kennzahl der Netzperiodendauer
$var1 = 0; // VariablenID der Obis Kennzahl der Daten welche nicht umgerechnet werden
$var2 = 0; // VariablenID der Obis Kennzahl der Daten welche nicht umgerechnet werden
$var3 = 0; // VariablenID der Obis Kennzahl der Daten welche nicht umgerechnet werden

//Dateneingang von Registervariable
$string = explode("
", trim($IPS_VALUE));

for($i = 0; $i < count($string); $i++)
{
    $id = strstr($string[$i], "(", true); // split nach Obis Kennzahl
    $value = strstr($string[$i], "("); // split nach Daten
    $check = strpos($value, "*"); // suche nach Daten mit Angaben V-A-W
    if($check !== false) // Daten mit V-A-W ausgeben und formatieren auf 2 Stellen nach dem Komma
    {
       $value = strstr($value, "*", true); // split nach *V-A-W
        $data = substr($value, 1);
        SetValue($eHZdata[$id], number_format((float)$data, 2, ',', ''));
    }
    else // alle anderen Daten ausgeben
    {
        $data = substr(trim($value), 1, -1);
        if(strlen($data) <= 4) // Daten mit bis zu 2 Byte
        {
           if($eHZdata[$id] == $Netzperiodendauer)
            {
               $data = hexdec($data)/100; // Daten umrechnen 1/100 in ms
            }
            elseif(($eHZdata[$id] == $var1) || ($eHZdata[$id] == $var2) || ($eHZdata[$id] == $var3))
            {
               $data = $data; // Daten ohne Umrechnung
            }
            else
            {
               $data = hexdec($data); // Daten von Hex nach Dec umrechnen
            }
        }
        SetValue($eHZdata[$id], (float)$data);
    }
}
?>

Soweit habe ich es verstanden: im Array habe ich die Werte die mein Zähler liefert, die werden auf die jeweiligen Variablen abgebildet.

Die Variable 28174 ändert sich auch im Sekundentakt. Schön. Einspeisung ist nichts weil dunkel.

Was ich nicht ganz verstehe - wieso läuft das Script überhaupt? Wo kommen die Daten her?

Folgende Fehlermeldungen gibt es:

Notice:  Undefined variable: IPS_VALUE in C:\IP-Symcon\scripts\20484.ips.php on line 15

Notice:  Undefined offset: 0 in C:\IP-Symcon\scripts\20484.ips.php on line 33

Notice:  Undefined offset: 0 in C:\IP-Symcon\scripts\20484.ips.php on line 46

Warning:  Variable #0 existiert nicht in C:\IP-Symcon\scripts\20484.ips.php on line 46

Wenn ich das richtig verstehe sollen die Werte aus $IPS_VALUE ausgelesen werden, die gibts aber nicht. Wieso gibts dann trotzdem Daten? Wo kommen die her?

Brauche ich für meinen Zähler Netzperiodendauer, Var1-Var3?

Wie bekomme ich die Fehler weg?

Und da ich den Verbrauch gerne loggen würde:
kann ich den Takt der Abfrage irgendwie auf 30sekunden oder 1 Minute ändern? Mit 1 Sekunden läuft mir ja sonst bald die Platte voll.

Kann ich aus dem Verbrauch irgendwie die Leistung berechnen?
Variablen Strom-Bezug (28174) und Strom-Einspeisung (25310) funktionieren.
Die Bezugsleistung müsste dann (Strom-Bezug(letzte Messung) - Strom-Bezug(aktuelle Messung)/Messintervall) sein, richtig?
Gleiches für Einspeiseleistung. Hat mir jemand einen Tipp wie ich das im Script korrekt implementiere?

Die Co-Met Software zeigt die aktuelle Leistung an. Der Zähler gibt die aber nicht aus, also muss die ja berechnet sein?

Wäre toll wenn mir jemand weiterhelfen könnte. Im genannten Thread ging es ja am Ende nur noch um „moderne“ Zähler mit anderem Protokoll.

Hallo.

Das Skript wird jedesmal getriggert wenn die Registervariable - in deren Definition Du ja das Skript als Ziel angegeben hast - Daten empfangen hat.

Diese Daten werden dann an das Skript übergeben und hier

$string = explode("
", trim($IPS_VALUE));

erstmals weiterverarbeitet.

Wie Systemvariablen funktionieren findest Du hier.

Rufst Du das Skript manuell auf ist eine Datenübergabe an das Skript logischerweise nicht passiert und $IPS_VALUE daher nicht definiert. Daher die Fehler.

Und lass Dich nicht verwirren, die neue Schreibweise für $IPS_VALUE ist $_IPS[‚VALUE‘].

Hallo Kronos,
danke für die schnelle Antwort.

D.h. mein Script hat manuell garnicht funktioniert, der Wert hat sich nur geändert weil das sowieso jede Sekunde im Hintergrund gestartet wurde? :slight_smile:

Habe jetzt das Ziel aus der Registervariable entfernt und versucht die Variable direkt anzusprechen, funktioniert aber nicht.

$string = explode("
", trim(18112));

Hast Du Dich schon einmal mit Arrays beschäftigt und Dir angeschaut was der Befehl explode macht?

trim(18112))

Und was soll 18112 sein?

Nochmal: Der Zähler schickt Daten die in Deiner Registervariable landen. Die übergibt das an Dein Skript. Dort wird der String in ein Array zerlegt und anhand der Adressdefinitionen

$eHZdata = array(„1-0:0.0.0255" => 27454, // Zaehlernummer
"1-0:1.8.1
255“ => 28174, // Strom Bezug
„1-0:2.8.1255" => 25310, // Strom Einspeisung
"1-0:96.5.5
255“ => 59298, // Status Hex
„0-0:96.1.255*255“ => 22074, // Fabriknummer
);

in die zugehörigen Variablen geschrieben.

Wenn Du das Skript über die RegVar triggern lässt - wirft es denn Fehler im Logfile bzw. im Message Fenster aus?

Hi Kronos,
um es mit Deiner Signatur zu sagen - ich bin Version 1.0 :smiley:

Explode habe ich mittlerweile genau angeschaut. die 18112 ist die ID der Register Variable. Naja…

Habe jetzt etwas weiter geforscht. Da mein Zähler so gut wie nichts ausgibt benötige ich die ganzen Variablen wohl nicht.

Mein aktuelles Skript sieht jetzt so aus:

<?
$eHZdata = array("1-0:0.0.0*255" => 27454, // Zaehlernummer
                     "1-0:1.8.1*255" => 28174, // Strom Bezug
                     "1-0:2.8.1*255" => 25310, // Strom Einspeisung
                     "1-0:96.5.5*255" => 13137, // Status Hex
                     "0-0:96.1.255*255" => 24530, // Fabriknummer
                      );

//Dateneingang von Registervariable
$string = explode("
", trim($IPS_VALUE));

for($i = 0; $i < count($string); $i++)
{
    $id = strstr($string[$i], "(", true); // split nach Obis Kennzahl
    $value = strstr($string[$i], "("); // split nach Daten
    $check = strpos($value, "*"); // suche nach Daten mit Angaben V-A-W
    if($check !== false) // Daten mit V-A-W ausgeben und formatieren auf 2 Stellen nach dem Komma
    {
       $value = strstr($value, "*", true); // split nach *V-A-W
        $data = substr($value, 1);
        SetValue($eHZdata[$id], number_format((float)$data, 2, ',', ''));
    }
    else // alle anderen Daten ausgeben
    {
        $data = substr(trim($value), 1, -1);


        SetValue($eHZdata[$id], (float)$data);
   }
}
?>

Es gibt diese Fehlermeldungen:

Notice: Undefined offset: 0 in C:\IP-Symcon\scripts\20484.ips.php on line 28

Warning: Variable #0 existiert nicht in C:\IP-Symcon\scripts\20484.ips.php on line 28

Und zwar kommt das pro Ausführung 5x
Könnten das die 5 Zeilen im Code sein die das Datum, das Ausrufezeichen und die fortlaufende Nummer bzw. das DE enthalten?

Die angegebenen Variablen werden laufend aktualisiert, das klappt schon mal :slight_smile:

Aber wie bekomme ich es hin, daß das nur alle 30sekunden ausgeführt wird?

Magst Du mal einen Screenshot von dem betreffenden Teil Deines Objektbaumes posten?

Hallo,
siehe Anhang.

Abgesehen von den Fehlermeldungen läuft es schon ganz brauchbar.

Habe daher schon ein wenig weiter gespielt:

Aus den daten sollte ja auch die Leistung ermittelbar sein:
Bezug-30s speichert den Wert von Strom-Bezug von vor 30 Sekunden.
Alle 30 Sekunden wird ein kleines Skript ausgeführt das mir die Durchschnittsleistung über diese 30 Sekunden berechnet. Müsste doch so stimmen:

<?
 $var1 = 25310 /*[strom\Strom-Einspeisung]*/;
 $var2 = 45821 /*[strom\Bezug-30s]*/;
  $var3 = 28174 /*[strom\Strom-Bezug]*/; 
  
  $var4 = 16450 /*[strom\Watt]*/;
  
  $tmp_vor30s = $var2;
  
SetValue ($var4,(GetValue($var3)*1000*3600 - GetValue($var2)*1000*3600)/30);
SetValue ($var2,GetValue($var3));
?>

*1000 weil Wert in kw, *3600 weil Stunde (kwh), damit habe ich die Wattsekunden.
Die Differenz über 30 Sekunden durch 30 sollte die aktuelle Leistung sein.

Die Werte schwanken zwischen 600 und 700, das könnte der aktuelle Wert sein.
Jetzt geh ich mal ein Schnitzel braten und schau ob man das später sieht :slight_smile:

Und zwar kommt das pro Ausführung 5x
Könnten das die 5 Zeilen im Code sein die das Datum, das Ausrufezeichen und die fortlaufende Nummer bzw. das DE enthalten?

Damit liegst Du wohl richtig. Im ursprünglichen Skipt gab es einen Teil der sich um diesen „Abfall“ gekümmert hat. Den hast Du zumindest teilweise eliminiert und deswegen kommen die Fehler.

Entweder Du willst den Datenmüll auswerten - bei manchen Zählern stehen da brauchbare Dinge drin - oder Du lässt es bei den Werten die Du jetzt schon bekommst.

Im letzterem Fall wirf die ELSE-Verzweigung aus dem Skript.

Hallo,
die Daten scheinen bei mir über den ELSE-Zweig verarbeitet zu werden, wenn ich den entferne werden die Variablen nicht mehr aktualisiert. Das muss ich noch genauer überprüfen.

Eine Frage zur Auslastung hätte ich noch:

Ich will die aktuelle Leistung mitloggen (Bezug+Einspeisung) und grafisch darstellen.
Aktuell habe ich das im letzten Beitrag gepostete Script seit gestern laufen, damit werden alle 15 Sekunden die aktuellen Leistungsdaten berechnet und abgespeichert. Ist halt immer der Durchschnitt auf die 15 Sekunden.

Wenn ich das Script in das Abfrage-Script der Registervariable mit einbaue hätte ich die Sekundenwerte.
Wie sieht es da mit Leistung und Speicherverbrauch aus. Kann man das bedenkenlos machen oder besser nur alle 15 Sekunden auswerten?
Float sind 2 Byte? 60x pro Sekunde wären 120Byte pro Minute, 7,2KB pro Stunde, 172KB pro Tag, 64MB pro Jahr - pro Wert. Wieviel Overhead ist da dabei?

Wieviel Overhead ist da dabei?

Versuch macht kluch.

Ich weiss nicht was für Reserven Dein System hat und womit es sonst so alles beschäftigt ist. Hier im Forum sind genügend Anwender unterwegs die Skripte im Sekundentat auswerten lassen und damit keine Leistungs-Probleme haben.

Mache aber nicht den Fehler der Mitloggerietis zu verfallen sondern überlege Dir ob Du die Daten wirlich im Sekundentakt benötigst. Ich habe am Anfang auch den Fehler gemacht und alles mitgelogged was bei drei nicht auf den Bäumen war. Letztendlich ist doch nur der Verbrauch wirklich interessant uns den bekommst Du auch mit grösseren Intervallen.

Abgesehen davon speichert die Datenbank nicht nur den Inhalt der Variable sondern z.b. auch den TimeStamp eines gespeicherten Wertes. Mit Deiner Platzberechnung kommst Du daher nicht hin.

Eventuell ist bezüglich Datenbankhygiene/-pflege der RS-DB-Analyzer von Raketenschnecke noch interessant für Dich.

Hallo,

ich muss diesen Thread noch einmal aus den Tiefen hervorholen.

Ich habe auch so einen COM-1 Ethernet in Betrieb und möchte ihn in IPS einbinden.
Verbindung mit EDL-Cockpit funktioniert, aber anders als hier beschrieben erhalte ich nach Einrichtung des Client-Sockets mit IP und Port aus EDL-Cockpit keinerlei Daten im Debug-Modus.
Muss man hier noch irgendetwas anschieben?

Gruß
Frank

OK, hat sich geklärt.

Mein COM-1 erwartet ein „%send_1_1“ und spuckt dann die Daten raus.
Jetzt geht’s weiter an die nächste Hürde mit der Auswertung der SML-Daten. :confused:

Das sollte aber zu schaffen sein.

Gruß
Frank

Hallo,

sorry erstmal für den Revive.

Haben auch einen COM-1 SML von Comet in Betrieb. Das „Configuration Tool“ des Herstellers findet die Schnittstelle, auch die DHCP Adresse scheint dort zu stimmen. IP-Symcon nimmt die IP und den Port erfolgreich an, aber auch dort keine Daten im Debug. Auch mit einer anderen Software empfange ich keinerlei Daten auf der Schnittstelle.

Wie habt ihr das gelöst? Muss das Gerät explizit angefragt werden, oder sollte es die Daten zyklisch senden? Die EDL Software ist nicht vorhanden.

Moin,

ich habe eine Registervariable, die übergeordnete Instanz ist der Client-Socket mit IP und Port des COM-1. Ziel ist dieses Script: (zusammengesucht, erweitert und geändert)

<?
$ClientSocket_ID = 12345;
$RegisterVariable_ID = 54321;

$bezug_ID = xxxxx /*[Zählerwerte\Strom\Bezugsstrom\Stand]*/;
$lieferung_ID = yyyyy /*[Zählerwerte\Strom\Lieferstrom\Stand]*/;
$erzeugung_ID = zzzzz /*[Zählerwerte\Strom\Erzeugungsstrom\Stand]*/;

$send1 = '%send_id_1_1';
$send2 = '%send_id_2_2';

switch ($IPS_SENDER)
{case "TimerEvent": // sendet anfrage an COM-1 EEG
 case "Execute":
    IPS_SetProperty($ClientSocket_ID, "Open",true); //I/O Instanz wird aktiviert
    IPS_ApplyChanges($ClientSocket_ID);

    EEG_Send($RegisterVariable_ID, $send1); //Abfrage Zählwerk 1
    EEG_Send($RegisterVariable_ID, $send2); //Abfrage Zählwerk 2
    break;
 case "RegisterVariable": // auf Antwort warten und verarbeiten
    $zaehler_ID = substr($IPS_VALUE, 94, 1);
//    $hexstring = strtohex($IPS_VALUE); // SML Daten herausschneiden

    // Werte je nach Zähler ID unterschiedlich extrahieren
    switch ($zaehler_ID)
        {case "0":
				 SetValueFloat($bezug_ID, intval(hexdec(substr($IPS_VALUE, 480, 12)))/10000);
				 SetValueFloat($lieferung_ID, intval(hexdec(substr($IPS_VALUE, 528, 12)))/10000);
				 break;
			case "1":
             SetValueFloat($erzeugung_ID, intval(hexdec(substr($IPS_VALUE, 466, 12)))/10000);
             // socket schliessen
    			 IPS_SetProperty($ClientSocket_ID, "Open",false); //I/O Instanz wird deaktiviert
    			 IPS_ApplyChanges($ClientSocket_ID);
    			 break;
			}
	 break;

}

//******** fc's*********************************************

function EEG_send($ID, $str) {
    RegVar_SendText($ID, $str);
    IPS_Sleep(40);}
?>

Knackpunkt war bei mir der Befehl „%send_id_1_1“ ohne den mein COM-1 keine Daten herausgibt.

Da ich bei mir zwei Zähler auslese, ist auch noch die Position der Zähler-ID (1 oder 2) im SML-Datensatz wichtig.(Zeile 22, bei mir auf Pos. 94) Ich schätze 'mal, dass ist bei jedem COM-1 gleich(?).

Wichtig sind auch noch die Positionen der Zählerwerte im Datensatz (Zeilen 28, 29 und 32). Die sind auf jeden Fall zählerabhängig und müssen angepasst werden.

Gruß
Frank

Hallo Frank,

vielen Dank schonmal für diese Info! Das hilft schonmal enorm weiter. Leider sendet die Schnittstelle noch immer keine Daten auf Anfrage. Haben nicht den EEG, sondern den SML (kleine schwarze Box). Sollte man aber meinen, dass Geräte vom gleichen Hersteller auch gleich funktionieren.

Woher hast du denn die Informationen bekommen, besonders mit dem „%send_id_1_1“? Die Dokumentationen für den SML sind auf der offiziellen Seite nurnoch auffindbar wenn man manuell durch die FTP Datenstruktur geht… und dort stehen dazu keine Infos drin. Jedenfalls keine gefunden. Habe dem Hersteller aber auch mal eine Mail geschrieben.

Die Schnittstelle hat gestern EINMAL selbstständig einen Datenstrang geschickt, als der Lesekopf abgenommen und wieder aufgesetzt wurde. Wie verhält sich die Schnittstelle, wenn der Lesekopf keine Daten empfängt? Werden dann garkeine Daten versendet die man empfangen kann? Dann wäre eventuell der Sitz des Lesekopfes nochmal zu prüfen, jedoch würde ich erwarten dass die Schnittstelle auch bei fehlerhaften Daten „irgendwas“ sendet. Zumindest die Version, Mac-Adresse oder einen Fehler

Datenstrang mittels SocketTest empfangen:

 
mac=XX:XX:XX:XX:XX:XX
boot=1
fw=02.00
time=1259861700
zpb=DE0000000000000000000000000000001
SML(7604000001620001760400000162006200726500000101760101070000000000000B0141424E00000000123401016371A00076040000026200620072650000070177010B0141424E00000000123401017777078181C78203FF010101010441424E0177070100000009FF010101010B0141E3EF808080FF1B1B1B1B01010101)

Hallo Andy,

Woher hast du denn die Informationen bekommen, besonders mit dem „%send_id_1_1“?

Ich hatte befürchtet, dass diese Frage kommt. Es ist jetzt über drei Jahre her, und das DIng läuft seitdem problemlos durch. Deshalb meine Erinnerungslücken. :confused: Ich vermute, das stand in der Anleitung zum COM-1 EEG. Leider ist genau Diese momentan bei mir nicht auffindbar.

Der Hersteller war zumindest damals sehr kooperativ, eine Anfrage dort kann zumindest nicht schaden.

Wie verhält sich die Schnittstelle, wenn der Lesekopf keine Daten empfängt?

Wenn der Lesekopf nicht empfängt, schickt er auch nichts an die Schnittstelle. Wenn er Unsinn empfängt, schickt er Unsinn an die Schnittstelle. Manche Zähler und auch Leseköpfe sind sehr genau, was die Lesekopfposition angeht, manche sind aber auch so tolerant, dass ein um 180° gedrehter Lesekopf noch irgendwelche (meist aber unbrauchbare) Daten liefert.

Ich habe es noch nicht ausprobiert, aber ich vermute dass bei falsch gesetztem Lesekopf die Daten des COM-1 (die ersten 5 Zeilen Deines Datenstrangs) trotzdem kommen sollten.

Dein Datenstrang sieht SML-seitig jedoch etwas „verkrüppelt“ aus. SML-Frames beginnen nach Norm immer mit „1B 1B 1B 1B 01 01 01 01“. Bei Dir hat er sich wohl „mittendrin“ zugeschaltet.
Hier ein Beispiel von mir:

<r><i type="kom-1eeg" id="xx:xx:xx:xx:xx:xx" fw="06.04" tf="%s"></i><f ts="1425464390"><d id="1" proto="sml"><z n="0" zpb="000000000000000000000000000000000"/><t enc="hex">1B1B1B1B010101017607001108FE97976200620072630101760101070011056987DD0B06454D480104C569AD4801016340AA007607001108FE9798620062007263070177010B06454D480104C569AD480172620165056947787777078181C78203FF0101010104454D480177070100000009FF010101010B06454D480104C569AD480177070100010800FF63018201621E52FF560036D9E8E20177070100010801FF0101621E52FF560036D9E8E30177070100010802FF0101621E52FF56000000000001770701000F0700FF0101621B52FF550000B6190177078181C78205FF010101018302E6532D2F68DE9FCCF3D18268E4022FED89C760AA665493E0C955BCFE3FA2E4B4B837387DB25876C266429FB4FDADFFA601010163CFCB007607001108FE979B620062007263020171016319F900001B1B1B1B1A01DC52</t></d></f></r>

Nach Deine Beschreibung sieht es für mich aus der Ferne aus wie ein Wackelkontakt in der Verbindung zwischen Lesekopf und COM-1, aber das ist jetzt grobe Spekulation.

Gruß
Frank