SmartMeter ISKA MT681 / Optokoppler

Endlich konnte ich meine Optokoppler den ich bei Nils von Volkszähler bestellt habe in Betrieb nehmen. Bei mir hat es mit OH 2.4 und dem Einbinden des Optokopplers als Thing über die GUI auf Anhieb funktioniert. Aus unterschiedlichen Quellen habe ich hier aber auch schon von Problemen gehört von denen ich zum Glück verschont geblieben bin.

Nun zur Einrichtung. Ich möchte natürlich den aktuellen Verbrauch sowie den Gesamtverbrauch sehen. Dazu werden folgende Items angelegt und natürlich ins Sitemap eingebunden. Ich verwende hier auch das neue UOM Konzept:

Number:Energy STR_act   "Stromverbrauch akt [%.0f %unit%]" 	<energy>      					{channel="smartmeter:meter:6fd23207:1-0_16-7-0"} 
Number:Energy STR_sum   "Stromverbrauch ges [%.2f %unit%]" 	<energy>        {channel="smartmeter:meter:6fd23207:1-0_1-8-0"} 

Darüber hinaus will ich noch den Verbrauch der letzten 7 Tage (STR_D0 bis STR_D6) sowie pro Monat (STR_1 bis STR_12) sehen. Und ich hab mir noch zwei Hilfsvariablen angelegt. Diese habe ich als Item angelegt damit sie nicht weg sind wenn ich den PI einmal durchstarte. Um die Items muss ich mir nämlich keine Gedanken machen da die MAP DB diese speichert und wiederherstellt.

Number 		STR_help_d  "Stromverbruach helper Tag [%.2f]"
Number 		STR_help_m  "Stromverbruach helper Monat [%.2f]"
Number 		STR_D0		"heute [%.2f kWh]"
Number 		STR_D1		"-1 [%.2f kWh]"
Number 		STR_D2		"-2 [%.2f kWh]"
Number 		STR_D3		"-3 [%.2f kWh]"
Number 		STR_D4		"-4 [%.2f kWh]"
Number 		STR_D5		"-5 [%.2f kWh]"
Number 		STR_D6		"-6 [%.2f kWh]"
Number 		STR_1		"Januar [%.2f kWh]"	(gStrom)
Number 		STR_2		"Februar [%.2f kWh]"	(gStrom)	
Number 		STR_3		"März [%.2f kWh]"	(gStrom)
Number 		STR_4		"April [%.2f kWh]"	(gStrom)
Number 		STR_5		"Mai [%.2f kWh]"	(gStrom)
Number 		STR_6		"Juni [%.2f kWh]"	(gStrom)
Number 		STR_7		"Juli [%.2f kWh]"	(gStrom)
Number 		STR_8		"August [%.2f kWh]"	(gStrom)
Number 		STR_9		"September [%.2f kWh]"	(gStrom)
Number 		STR_10		"Oktober [%.2f kWh]"	(gStrom)
Number 		STR_11		"November [%.2f kWh]"	(gStrom)	
Number 		STR_12		"Dezember [%.2f kWh]"	(gStrom)

Kommen wir nun zu den Regeln und beginnen mit dem was wir für die Werte der letzten 7 Tage brauchen. Immer um Mitternacht reichen wir die Variablen eins weiter. Somit ist in D0 immer der Wert des aktuellen Tags und in den anderen Variablen absteigend die letzten Tage.

rule "Strom_taegl"
   when
		Time is midnight 
   then
		STR_D6.postUpdate(STR_D5.state)
		STR_D5.postUpdate(STR_D4.state)
		STR_D4.postUpdate(STR_D3.state)
		STR_D3.postUpdate(STR_D2.state)
		STR_D2.postUpdate(STR_D1.state)
		STR_D1.postUpdate(STR_D0.state)
		STR_help_d.postUpdate(STR_sum.state)  
		STR_D0.postUpdate(0.0)
end

Das ganze ist mit den labels leider etwas unschön weshalb die Regel auch die Tage in die labels setzt. Abhängig vom aktuellen Wochentag werden die labels absteigend entsprechend umbenannt:

switch now.getDayOfWeek{
case 1: { STR_D0.label = "Montag" STR_D1.label = "Sonntag" STR_D2.label = "Samstag" STR_D3.label = "Freitag" STR_D4.label = "Donnerstag" STR_D5.label = "Mittwoch" STR_D6.label = "Dienstag" }
case 2: { STR_D0.label = "Dienstag" STR_D1.label = "Montag" STR_D2.label = "Sonntag" STR_D3.label = "Samstag" STR_D4.label = "Freitag" STR_D5.label = "Donnerstag" STR_D6.label = "Mittwoch" }
case 3: { STR_D0.label = "Mittwoch" STR_D1.label = "Dienstag" STR_D2.label = "Montag" STR_D3.label = "Sonntag" STR_D4.label = "Samstag" STR_D5.label = "Freitag" STR_D6.label = "Donnerstag" }
case 4: { STR_D0.label = "Donnerstag" STR_D1.label = "Mittwoch" STR_D2.label = "Dienstag" STR_D3.label = "Montag" STR_D4.label = "Sonntag" STR_D5.label = "Samstag" STR_D6.label = "Freitag" }
case 5: { STR_D0.label = "Freitag" STR_D1.label = "Donnerstag" STR_D2.label = "Mittwoch" STR_D3.label = "Dienstag" STR_D4.label = "Montag" STR_D5.label = "Sonntag" STR_D6.label = "Samstag" }
case 6: { STR_D0.label = "Samstag" STR_D1.label = "Freitag" STR_D2.label = "Donnerstag" STR_D3.label = "Mittwoch" STR_D4.label = "Dienstag" STR_D5.label = "Montag" STR_D6.label = "Sonntag" }
case 7: { STR_D0.label = "Sonntag" STR_D1.label = "Samstag" STR_D2.label = "Freitag" STR_D3.label = "Donnerstag" STR_D4.label = "Mittwoch" STR_D5.label = "Dienstag" STR_D6.label = "Montag" }
}

Und hier die Regel komplett

rule "Strom_taegl"
   when
		Time is midnight 
   then
		STR_D6.postUpdate(STR_D5.state)
		STR_D5.postUpdate(STR_D4.state)
		STR_D4.postUpdate(STR_D3.state)
		STR_D3.postUpdate(STR_D2.state)
		STR_D2.postUpdate(STR_D1.state)
		STR_D1.postUpdate(STR_D0.state)
		STR_help_d.postUpdate(STR_sum.state)  
		STR_D0.postUpdate(0.0)
		switch now.getDayOfWeek{
			case 1: { STR_D0.label = "Montag" STR_D1.label = "Sonntag" STR_D2.label = "Samstag" STR_D3.label = "Freitag" STR_D4.label = "Donnerstag" STR_D5.label = "Mittwoch" STR_D6.label = "Dienstag" }
			case 2: { STR_D0.label = "Dienstag" STR_D1.label = "Montag" STR_D2.label = "Sonntag" STR_D3.label = "Samstag" STR_D4.label = "Freitag" STR_D5.label = "Donnerstag" STR_D6.label = "Mittwoch" }
			case 3: { STR_D0.label = "Mittwoch" STR_D1.label = "Dienstag" STR_D2.label = "Montag" STR_D3.label = "Sonntag" STR_D4.label = "Samstag" STR_D5.label = "Freitag" STR_D6.label = "Donnerstag" }
			case 4: { STR_D0.label = "Donnerstag" STR_D1.label = "Mittwoch" STR_D2.label = "Dienstag" STR_D3.label = "Montag" STR_D4.label = "Sonntag" STR_D5.label = "Samstag" STR_D6.label = "Freitag" }
			case 5: { STR_D0.label = "Freitag" STR_D1.label = "Donnerstag" STR_D2.label = "Mittwoch" STR_D3.label = "Dienstag" STR_D4.label = "Montag" STR_D5.label = "Sonntag" STR_D6.label = "Samstag" }
			case 6: { STR_D0.label = "Samstag" STR_D1.label = "Freitag" STR_D2.label = "Donnerstag" STR_D3.label = "Mittwoch" STR_D4.label = "Dienstag" STR_D5.label = "Montag" STR_D6.label = "Sonntag" }
			case 7: { STR_D0.label = "Sonntag" STR_D1.label = "Samstag" STR_D2.label = "Freitag" STR_D3.label = "Donnerstag" STR_D4.label = "Mittwoch" STR_D5.label = "Dienstag" STR_D6.label = "Montag" }
		}
end

Für die Anzeige der monatlichen Werte habe ich einen etwas anderen Ansatz gewählt. Dazu muss man sich zunächst am Monatsersten den aktuellen Wert speichern und zwar mit folgender Regel:

rule "Strom_monatl"
   when
		Time cron "0 0 0 1 * ?" 
   then
		STR_help_m.postUpdate(STR_sum.state)
end

Und damit haben wir dann auch unser Rüstzeug und können die Werte schließlich ermitteln und updaten. Der Teil für die täglichen Werte ist ganz einfach. Mit ein paar kleinen Helferlein wird die Differenz berechnet und dann schließlich in STR_D0 geschrieben.

var float helper_d = 0
var float diff_d = 0
var float sum = 0

rule "Strom_aktualisiert"
   when
		Item STR_sum changed
   then 
		helper_d = (STR_help_d.state as Number).floatValue
		sum	 = (STR_sum.state as QuantityType<Number>).floatValue
		diff_d 	 = ( sum - helper_d ) / 1000
		STR_D0.postUpdate(diff_d)

end

Der Teil für die Monate ist etwas kniffeliger aber sobald man das System raus hat auch nicht wirklich schwierig. Zunächst ermitteln wir auch hier die Differenz zum Monatsanfang. Dann folgt die Magie indem wir den dynamisch ermittelten Namen in der Gruppe gStrom, welche wir oben den Items zugewiesen haben suchen und somit das aktuelle Monatsitem an der Hand haben um diesem dann den ermittelten Wert zuzuweisen.

var float helper_m = 0
var float diff_d = 0
var float sum = 0

rule "Strom_aktualisiert"
   when
		Item STR_sum changed
   then 
		helper_m = (STR_help_m.state as Number).floatValue
		sum	 = (STR_sum.state as QuantityType<Number>).floatValue
		diff_d 	 = ( sum - helper_d ) / 1000
		diff_m 	 = ( sum - helper_m ) / 1000

		val monthStrom = gStrom.members.findFirst[name.equals("STR_"+now.getMonthOfYear)]
		monthStrom.postUpdate(diff_m)
end

Die Regel sieht dann fertig so aus:

var float helper_d = 0
var float helper_m = 0
var float diff_d = 0
var float diff_m = 0
var float sum = 0

rule "Strom_aktualisiert"
   when
		Item STR_sum changed
   then 
		helper_d = (STR_help_d.state as Number).floatValue
		helper_m = (STR_help_m.state as Number).floatValue
		sum	 = (STR_sum.state as QuantityType<Number>).floatValue
		diff_d 	 = ( sum - helper_d ) / 1000
		diff_m 	 = ( sum - helper_m ) / 1000
		STR_D0.postUpdate(diff_d)
		val monthStrom = gStrom.members.findFirst[name.equals("STR_"+now.getMonthOfYear)]
		monthStrom.postUpdate(diff_m)
end

Und jetzt mal sehen ob sich das bewährt. Klar kann man hier auch viel mit Graphen etc. machen aber ich bin ein Freund der nackten Zahlen und möchte einfach und schnell eine Übersicht über den Verbrauch haben.

Off Topic: Da ich zu faul war das USB Kabel zu verlegen und noch ein nicht genutztes Netzwerkkabel in der Nähe des Zählerschranks verfügbar war habe ich mir bei Aliexpress für wenige € ein USB RJ45 Extern geschossen. Funktioniert super!