- Offizieller Beitrag
Hallo liebe Homematic-Freunde und Beta-Tester.
Zunächst mal ein Danke für Eure Unterstützung.
Was ist neu in Version 4?
- zusätzliche Variablen legt das Skript automatisch an
- Jahresvaraiablen (=Gesamtverbrauch / Jahr) werden am 27.12. jeweils für das Folgejahr automatisch erzeugt und ab 01.01. beschrieben
- Monatsvariablen werden am 28. jedes Monats neu (für den Folgemonat) erzeugt und auf Wunsch in eine bestehende Favoritenliste eingefügt.
- Anzeige der aktuellen Last (Summe der 3 Phasen)
- CUxD-Ping-Device entfällt!
Hinsichtlich der anzulegenden Geräte könnt Ihr Euch an der unter Homematic publizierte Version 2 orientieren. (Version 3 war der Zwischenschritt "Jahresvariable" und ist nicht publiziert.)
Hier mal eine Übersicht aller Variablen, die pro 3EM benötigt werden und manuell anzulegen sind:
manuell anzulegende Variablen
Warum müssen diese Variablen noch manuell angelegt werden?
Das Skript erzeugt eine im Vergleich zu anderen Kopplungen hohe Laufzeit (auf Test-CCU2 ca. 10 Sekunden, CCU3 ca 2-3 Sekunden).
Jede automatisch erzeugte Variable muß im Skript zunächst auf Vorhandensein geprüft werden. Diese Zeit kann bei diesen Variablen, die ja nur einmal angelegt werden, elemeniert werden.
Somit werden spürbare Verzögerungen im übrigen Homeatic-Ablauf vermieden.
Und diese Variablen werden dann vom Skript autom. erstellt:
Gibt man im Setup für die Monats-Verbrauchsvariablen eine Favoritenliste an, so werden die Variablen bei der Erstellung automatisch in die Favoritenliste eingefügt. Die Favoritenliste selbst muß schon angelegt sein!
Das sieht dann z.B. so aus:
Favoritenliste für die monatlichen Verbrauchsdaten Heizstrom
(Der Wert -1 ist kein Fehler, sondern identifiziert noch nicht beschriebene Variablen )
Für die Aktualisierung benötigen wir natürlich wie immer ein kleines Programm:
Und nun noch das kleine Skript:
(Anmerkung: bei der 1. Monatsvariablen bedient sich das Skript der im 3EM bereits vorhandenen Werte. Alternativ können die Daten des 3EM via WEB-UI oder in der App gelöscht werden. Dann gelten die Werte des 1. Monats ab Inbetriebnahme des Skriptes.)
Achtung: jeweils aktuelle Skriptversion liegt nun in Beitrag #4
! V4.0.5 für den "smarten Stromzähler" mit Shelly 3EM mit Originalfirmware (c)2020 by 66er (alias Stefan K.)
! 3EM als Verbrauchszähler, Anzeige der aktuellen Last gesamt und je Phase und einem Tageszähler inkl. Kostenanzeige,
! - mit autom. Erstellung einer neuen Jahresvariablen bei Jahreswechsel
! - Monatsvariablen für den Verbrauch / Monat
! - und NEU: optionales automatisiertes Einfügen der neuen Monatsvariablen in eine bestehende Favoritenliste
! BITTE BEACHTEN:
! Dieses Skript legt ggf. selbstständig zusätzliche Systemvariablen auf Deiner Homematiczentrale an!
! Das ist nötig, um Inkonsistenzen zu vermeiden und eine temporäre Blockade der CCU durch das Skript zu vermeiden.
! Wer das nicht möchte, kann dieses Skript leider nicht nutzen!
!Heizstrom (nur zur Orientierung, ggf anpassen)
! ACHTUNG:
! Im Setup KEINE " " LÖSCHEN!
! Variablennamen dürfen keine Leerzeichen und keine Punkte (.) enthalten
! In den manuell angelegten Variablen auf gleiche Schreibweise im Skript achten (Groß/Kleinschreibung)
! ****** SETUP SETUP SETUP SETUP SETUP SETUP *****
! Setup des Shelly 3EM
var url = "http://192.168.1.171/status"; ! IP-Adresse des Shelly anpassen
! Setup der CUxD-GERÄTE
var exec3em = "CUxD.CUX2801001:6"; ! Adresse und Kanal des CUxD-Exec-Device anpassen
!Setup der SYSTEMVARIABLEN
! Setup Anzeige der 3Phasen
var svLv = "J";! Ohne Variablen für die aktuelle Leistung auf "N" setzen
var svL1 = "3EM-Heizstrom_aktuell-L1"; !Name der SV für den aktuellen Verbrauch L1 anpassen
var svL2 = "3EM-Heizstrom_aktuell-L2"; !Name der SV für den aktuellen Verbrauch L2 anpassen
var svL3 = "3EM-Heizstrom_aktuell-L3"; !Name der SV für den aktuellen Verbrauch L3 anpassen
var svlgv = "J" ;! Variable für den aktuellen Gesamtverbrauch, wenn nicht gewünscht auf "N" setzen
var svlg = "3EM-Heizstrom_akt-Gesamtverbrauch"; ! Name der Variablen für den aktuellen Gesamtverbrauch anpassen
! Setup der Verbrauchsanzeige
var svVgest = "3EM-Heizstrom_Verbrauch-gesamt_"; ! Name der SV für den Gesamtverbrauch anpassen
var svVbu = "3EM-Heizstrom_Gesamtverbrauch-Backup"; ! Name der SV für den Backupwert eintragen
var svVbu2 = "3EM-Heizstrom_Gesamtverbrauch-Backup2"; ! Name der SV für den Backupwert2 eintragen
! Setup der Kostenanzeige
var sykov = "J"; ! Kostenvariable vorhanden J oder N setzen
real pkwh = "0.2863"; ! Preis je kWh angeben
var syko = "3EM-Heizstrom_Kosten"; ! Name der SV für die Verbrauchskosten
! Setup Tageszähler
var emtzv = "J"; !Tageszähler vorhanden J oder N setzen
var emtz = "3EM_Heizstrom_TZ-Verbrauch"; ! Name der SV für den Backupwert eintragen
var emtzk = "3EM_Heizstrom_TZ-Kosten"; ! Name der SV für die Tageskostenwert eintragen
var emtzs = "3EM_Heizstrom_TZ-Startwert"; ! Name der SV für den Startwert des Tageszählers eintragen
! Setup Prüfung und Anzeige Onlinestatus
var emp = "1"; ! Ohne Onlienstatusprüfung auf 0 setzen Vom Deaktivieren wird DRINGEND ABGERATEN
var padr = "192.168.1.171"; ! IP des Shelly 3EM eintragen
var svonl = "Onlinestatus_3EM-Heizstrom" ; ! Name der SV für den Onlinestatus angeben
! Setup Monatsvariable
var emmv = "J" ; ! Ohne Variablen für den Verbrauch / Monat bitte auf N setzen
var emmk = "J" ; ! Ohne Kostenberechnung für den Monatsverbrauch auf N setzen
var emmvfv = "J" ; ! Variable in Favoriten einfügen, der in der nächsten Einstellung zu definieren ist. Falls nicht gewünscht auf N setzen
var emmvfn = "Verbrauch-HS" ; ! Name der Favoritenliste eintragen, DIE FAVORITENLISTE MUSS ANGELEGT SEIN!
!****ENDE SETUP ********ENDE SETUP ********ENDE SETUP ******
!***********************************************************
! AB HIER NICHTS MEHR ÄNDERN
! Variable für Onlinestatus prüfen,ggf.anlegen
if (emp == 1) {
string sName= ""#svonl#""; ! Onlinestatus
if (!dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName)) {
object svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(ivtBinary);
svObj.ValueSubType(istBool);
svObj.ValueName0("Offline");
svObj.ValueName1("Online");
svObj.State (true); !. Zustand der Sysvar nach dem Anlegen
dom.RTUpdate(0);
}
}
! Onlineabfrage und setzen des Status
string stderr;
string stdout;
integer Status;
system.Exec("ping -c 1 '"#padr#"'", &stdout, &stderr);
Status = stdout.Find("ms");
if (((emp) == 1 ) && ((Status) == -1)) {
WriteLine("Shelly 3EM ist offline");
dom.GetObject (""#svonl#"").State(0);
quit; ! Programmabbruch bei Shelly offline
}
if ((emp) == 1 ) {
dom.GetObject (""#svonl#"").State(1);
WriteLine("Shelly 3EM ist online");
}
!***********************************************************
!Ausführungszeit ermitteln
var monat = (system.Date("%m").ToInteger()) ;
var tag = (system.Date("%d").ToInteger()) ;
string ntmp = (""#svVgest#"" + "tmp"); !Variablenname mit Jahresangabe
!WriteLine(ntmp);
! Systemvariable Gesamtverbrauch_temp anlegen
string svName = ntmp;
object svObj = dom.GetObject(svName);
if (!svObj){
object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);
svObj = dom.CreateObject(OT_VARDP);
svObjects.Add(svObj.ID());
svObj.Name(svName);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("kWh");
svObj.ValueMin(0);
svObj.ValueMax(65000);
svObj.DPArchive(false);
svObj.State(0);
svObj.Internal(false);
svObj.Visible(true);
dom.RTUpdate(false);
}
! aktuelle Jahresvariable bestimmen
real jahr = (system.Date("%y").ToInteger()) ;
real ay = jahr + 2000 ;
real ny = jahr + 2001 ;
real ly = jahr + 1999 ;
string nd = (""#svVgest#"" + ny);
string svVges = (""#svVgest#"" + ay);
!WriteLine(svVges);
!WriteLine(nd);
if ((tag == 27) && (monat == 12)) {
! Systemvariable für neues Jahr anlegen
string svName = (""#nd#"");
object svObj = dom.GetObject(svName);
if (!svObj){
object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);
svObj = dom.CreateObject(OT_VARDP);
svObjects.Add(svObj.ID());
svObj.Name(svName);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("kWh");
svObj.ValueMin(0);
svObj.ValueMax(65000);
svObj.DPArchive(false);
svObj.State(0);
svObj.Internal(false);
svObj.Visible(true);
dom.RTUpdate(false);
}
}
else {
var svVges = (""#svVgest#"");
!WriteLine("Variablenautomatik ist deaktiviert oder Erstellungszeitpunkt nicht erfüllt!");
}
var svVges = (""#svVgest#"" + ay);
!WriteLine("aktuelle Jahresvariable ist:" + svVges);
!****Abfrage des Shelly 3EM *****
dom.GetObject(""#exec3em#".CMD_SETS").State("wget -q -O - '"#url#"'");
dom.GetObject(""#exec3em#".CMD_QUERY_RET").State(1);
string Antwort = dom.GetObject(""#exec3em#".CMD_RETS").State();
string t = dom.GetObject(""#exec3em#".CMD_RETS").State();
dom.GetObject(""#exec3em#".CMD_SETS").State("0");
WriteLine(Antwort);
!*****************************************
!**** Auswertung der Total-Werte je Phase ****
string output = Antwort;
string part; string code;string slist;integer collect = -1;
foreach (part, output.Split("emeters")){
collect = part.Find("total");
if (collect>-1){
code = ((part.StrValueByIndex(",",1)).StrValueByIndex(":",1));
code = code.Substr(0, code.Length()-1);
slist = slist#code#"/";
}}
! Ergebnis in Einzelwerte auflösen
var pl1 = slist.StrValueByIndex("/", 0);
var pl2 = slist.StrValueByIndex("/", 1);
var pl3 = slist.StrValueByIndex("/", 2);
! Berechnung Gesamtverbrauch in Watt
var pg = pl1.ToFloat() + pl2.ToFloat() + pl3.ToFloat();
! Berechnung und Setzen der Variablen (Gesamtverbrauch)
var pjg = dom.GetObject(""#svVges#"").State();
var pbu = dom.GetObject(""#svVbu#"").State();
var pbu2 = dom.GetObject(""#svVbu2#"").State();
integer pz;
!Normalbetrieb
if (pg >= (pbu*1000))
{
dom.GetObject(""#ntmp#"").State(pg/1000); !svVgest
dom.GetObject(""#svVbu#"").State(pg/1000);
dom.GetObject(""#svVbu2#"").State(pg/1000);
}
elseif ((pg < (pbu*1000)) && (pg < (pbu2*1000)))
{
!nach Wertereset im Shelly
pz = pjg + (pg/1000) ;
dom.GetObject(""#ntmp#"").State(pz);
dom.GetObject(""#svVbu#"").State(pz); ,
dom.GetObject(""#svVbu2#"").State(pg/1000);
}
elseif ((pg < (pbu*1000)) && (pg > (pbu2*1000)))
{
pz = pjg + ((pg/1000) - pbu2) ;
dom.GetObject(""#ntmp#"").State(pz);
dom.GetObject(""#svVbu#"").State(pz);
dom.GetObject(""#svVbu2#"").State(pg/1000);
}
!WriteLine("Verbrauchsberechnung gesamt abgeschlossen");
! svVges schreiben
if (ay == 2020) {
var Vgesend = dom.GetObject(""#ntmp#"").State();
dom.GetObject(""#svVges#"").State(Vgesend);
WriteLine("alle Verbrauchsvariablen in 2020 geschrieben");
}
if (ay <> 2020) {
Vgesend = dom.GetObject(""#ntmp#"").State();
string lasty = (""#svVgest#"" + ly);
var svgly = dom.GetObject(""#lasty#"").State();
var Vgend = Vgesend - svgly;
dom.GetObject(""#svVges#"").State(Vgend);
WriteLine("alle Verbrauchsvariablen für Jahr >2020 geschrieben");
}
!Betrag berechnen
var vbw = dom.GetObject(""#svVges#"").State();
var sykoberg = vbw * pkwh.ToFloat();
if (sykov == "J") {dom.GetObject(""#syko#"").State(sykoberg);} ;
!WriteLine("Kostenberechnung gesamt abgeschlossen");
! aktuelle Last
string output = Antwort;
string part; string code;string slist;integer collect = -1;
foreach (part, output.Split("{")){
collect = part.Find("power");
if (collect>-1){
code = ((part.StrValueByIndex(":",1)).StrValueByIndex(",",0));
code = code.Substr(0, code.Length()-1);
slist = slist#code#"/";
}}
WriteLine(slist);
var l1 = slist.StrValueByIndex("/", 1);
var l2 = slist.StrValueByIndex("/", 2);
var l3 = slist.StrValueByIndex("/", 3);
var lg = l1.ToFloat() + l2.ToFloat() + l3.ToFloat();
!WriteLine(lg);
!Werte in Systemvariablen schreiben
if ((svLv) == "J") {dom.GetObject(""#svL1#"").State(l1.ToFloat()); };
if ((svLv) == "J") {dom.GetObject(""#svL2#"").State(l2.ToFloat()); };
if ((svLv) == "J") {dom.GetObject(""#svL3#"").State(l3.ToFloat()); };
if (svlgv == "J") {
!Variable für aktuellen Gesamtverbrauch prüfen, ggf. anlegen
string sName= ""#svlg#""; ! Summe der Phasenwerte
if (!dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName)) {
object svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("W");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.ValueMin(0);
svObj.ValueMax(65000);
svObj.State (0);
dom.RTUpdate(0);
}
dom.GetObject(""#svlg#"").State(lg);
}
WriteLine("Berechnung aktuelle Last der 3 Phasen abgeschlossen");
!***********************************************************************
! Monatsvariable, Namenserstellung
var emsvam = (""#svVges#"" + "-" + monat);
if (monat == 12) {
var nmonat = 1;
var emsvnm = (""#nd#"" + "-" + nmonat);
!WriteLine(emsvnm);
}
else {
var nmonat = (monat + 1) ;
!WriteLine(emsvam);
var emsvnm = (""#svVges#"" + "-" + nmonat);
!WriteLine(emsvnm);
}
!Monatsvariablen, prüfen und ggf. erstellen
if (emmv == "J") {
string sName= ""#emsvam#""; !aktueller Monat
if (!dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName)) {
object svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("kWh");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.ValueMin(-1);
svObj.ValueMax(65000);
svObj.State (-1); !. Zustand der Sysvar nach dem Anlegen
dom.RTUpdate(0);
}
WriteLine("SV für AM geprüft/angelegt");
var emsvmsw = (""#svVgest#"" + "Startwert-Mv");
string sName= ""#emsvmsw#""; !Startwert aktueller Monat
if (!dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName)) {
object svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("kWh");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.ValueMin(-1);
svObj.ValueMax(65000);
svObj.State (-1); !. Zustand der Sysvar nach dem Anlegen
dom.RTUpdate(0);
}
WriteLine("SV Startwert geprüft/angelegt");
}
if ((emmv == "J") && (tag == 28)) {
string sName= ""#emsvnm#""; !nächster Monat
if (!dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName)) {
object svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("kWh");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.ValueMin(-1);
svObj.ValueMax(65000);
svObj.State (-1); !. Zustand der Sysvar nach dem Anlegen
dom.RTUpdate(0);
}
WriteLine("SV für NM geprüft/angelegt");
! Favorit ergänzen
if (emmvfv == "J") {
object oSysVar = dom.GetObject (ID_SYSTEM_VARIABLES).Get (""#emsvnm#"");
object oFav= dom.GetObject (ID_FAVORITES).Get(""#emmvfn#"");
oFav.Add (oSysVar);
WriteLine("Favorit ergänzt");
}
}
! Startwert setzen
var emmzsw = dom.GetObject(""#emsvmsw#"").Value();
!!WriteLine(emmzsw);
var vges = dom.GetObject(""#svVges#"").Value();
!!WriteLine(vges);
!tag = 1; ! löschen bzw. deaktivieren
if ((tag == 1) && (emmzsw == -1)) {
dom.GetObject(""#emsvmsw#"").State(vges);
}
! Monatsverbrauch
var emmvges = vges - emmzsw;
!WriteLine("Montasverbrauch ist " + emmvges);
dom.GetObject(""#emsvam#"").State(emmvges);
! Kostenanzeige Monatsverbrauch
if (emmk == "J")
{
var emsvmzk = (""#svVgest#"" + "Kosten-akt.Monat");
!WriteLine(emsvmzk);
string sName= ""#emsvmzk#""; !Kosten aktuelller Monat
if (!dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName)) {
object svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("autom. angelegt durch Skript 3EM");
svObj.ValueUnit("Euro (brutto)");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(ivtFloat);
svObj.ValueSubType(istGeneric);
svObj.ValueMin(0);
svObj.ValueMax(65000);
svObj.State (0); !. Zustand der Sysvar nach dem Anlegen
dom.RTUpdate(0);
}
WriteLine("SV für KM geprüft/angelegt");
var mzk = emmvges * pkwh.ToFloat();
dom.GetObject(""#emsvmzk#"").State(mzk);
}
!***********************************************************************
! Tageszähler
if (emtzv == "N") {quit ; };
string sw = dom.GetObject(""#emtzs#"").State();
string pg = dom.GetObject(""#svVges#"").State();
var tz = pg - sw;
dom.GetObject(""#emtz#"").State(tz);
var tzk = tz * pkwh.ToFloat();
dom.GetObject(""#emtzk#"").State(tzk);
WriteLine("Skript beendet!");
!Ende Skript
Alles anzeigen
Bis hierhin schon mal viel Spass und Erfolg.
Bitte beachten:
Die Jahresverbrauchsvariable des Vorjahres darf nicht gelöscht werden! Älere Variablen dürfen gelöscht werden. (Zukunftsmusik halt )
Was kommt (eventuell) noch?
Wie aus dem Forum bekannt, ist der Schutz des Skriptes immer noch Thema. Ich habe eine Idee für einen "kleinen Lizenzschutz".
Bitte sendet mir mal Euren Antwortstring auf ip des 3EM /status per PN zu. Dann kann ich damit prüfen / entwickeln. Vielen Dank.