Umstieg von OH1

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

uweu
Beiträge: 17
Registriert: 7. Dez 2020 15:29
Answers: 0

Umstieg von OH1

Beitrag von uweu »

Hallo zusammen,
ich habe mich jetzt doch mal an den Umstieg von OH1 zu OH3 gewagt und muss sagen, da hat sich doch ein bisschen was geändert :)
Hab mittlerweile schon einiges mehr oder weniger gut in der neuen basicui hin bekommen.

Jetzt schlage ich mich gerade mit der Heizungsregelung herum. Meine RTR sind KNX Tritons von Busch Jäger.
Denke dass ich meine alten Regeln der Betriebsarteneinstellungen sicher etwas vereinfachen kann. Weiß aber nicht wirklich wie ich da ran gehen soll. (Is schon ziemlich lange her dass ich das Programmiert habe)

Hat evtl. jemand einen Tipp wie ich das schöner hin bekomme? Glaube mit Gruppen geht das irgendwie eleganter...

Vielen Dank im Voraus
Uwe


RULE:

Code: Alles auswählen

rule "Modus Heizen"
 when
	Modus_Heizen  received update
	or
	Time cron "0 10 * * * ?"
 then
		var Number day    = now.getDayOfWeek
		var Number hour   = now.getHourOfDay +1
		var Number minute = now.getMinuteOfHour
		var boolean Nacht = false
		
		if( day == 5 ){		// Freitag
			if( hour < 6 || hour >= 22 ) Nacht = true
		}
		else if( day == 6 ){	// Samstag
			if( hour < 7 || hour >= 22 ) Nacht = true
		}
		else if( day == 7 ){	// Sonntag
			if( hour < 7 || hour >= 21 ) Nacht = true
		}
		else{			// Montag - Donnerstag
			if( hour < 6 || hour >= 21 ) Nacht = true
		}
		logInfo("test", "Modus heizen Schleife")
		
		if (Modus_Heizen.state == 1){				// Normal
				logInfo("test", "Modus heizen = Normal")
				sendCommand(Betriebsart_EG_WZ_OH, PreBetriebsart_EG_WZ_OH.state as DecimalType)
				sendCommand(Betriebsart_EG_Kochen_OH, PreBetriebsart_EG_Kochen_OH.state as DecimalType)
				sendCommand(Betriebsart_OG_Bad_OH, PreBetriebsart_OG_Bad_OH.state as DecimalType)
		}
		else if (Modus_Heizen.state == 2){			// Abwesend
				logInfo("test", "Modus heizen = Abwesend")
				Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
				Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
				Betriebsart_EG_WZ_Frost.postUpdate(OFF)
				Betriebsart_EG_WZ_OH.postUpdate(2)
				Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
				Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
				Betriebsart_EG_Kochen_Frost.postUpdate(OFF)
				Betriebsart_EG_Kochen_OH.postUpdate(2)
				Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
				Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
				Betriebsart_OG_Bad_Frost.postUpdate(OFF)
				Betriebsart_OG_Bad_OH.postUpdate(2)
		}		
		else if (Modus_Heizen.state == 3){			// Tag/Nacht
				if ( Nacht ) { 
					logInfo("test", "Modus heizen = Nacht")
					Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
					Betriebsart_EG_WZ_Nacht.postUpdate(ON)
					Betriebsart_EG_WZ_Frost.postUpdate(OFF)
					Betriebsart_EG_WZ_OH.postUpdate(3)
					Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
					Betriebsart_EG_Kochen_Nacht.postUpdate(ON)
					Betriebsart_EG_Kochen_Frost.postUpdate(OFF)
					Betriebsart_EG_Kochen_OH.postUpdate(3)
					Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
					Betriebsart_OG_Bad_Nacht.postUpdate(ON)
					Betriebsart_OG_Bad_Frost.postUpdate(OFF)
					Betriebsart_OG_Bad_OH.postUpdate(3)
				}
				else {
					logInfo("test", "Modus heizen = Tag")
					sendCommand(Betriebsart_EG_WZ_OH, PreBetriebsart_EG_WZ_OH.state as DecimalType)
					sendCommand(Betriebsart_EG_Kochen_OH, PreBetriebsart_EG_Kochen_OH.state as DecimalType)
					sendCommand(Betriebsart_OG_Bad_OH, PreBetriebsart_OG_Bad_OH.state as DecimalType)
				}
		}   
		else if (Modus_Heizen.state == 4){			// Frost
				logInfo("test", "Modus heizen = Frost")
				Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
				Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
				Betriebsart_EG_WZ_Frost.postUpdate(ON)
				Betriebsart_EG_WZ_OH.postUpdate(4)
				Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
				Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
				Betriebsart_EG_Kochen_Frost.postUpdate(ON)
				Betriebsart_EG_Kochen_OH.postUpdate(4)
				Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
				Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
				Betriebsart_OG_Bad_Frost.postUpdate(ON)
				Betriebsart_OG_Bad_OH.postUpdate(4)
				}
end
			
rule "Betriebsart EG WZ senden"
 when
	Item Betriebsart_EG_WZ_OH received command
 then
       if (receivedCommand == 1) {
			Betriebsart_EG_WZ_Komfort.postUpdate(ON)
			Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
			Betriebsart_EG_WZ_Frost.postUpdate(OFF)
			PreBetriebsart_EG_WZ_OH.postUpdate(1)
       }
	   	else if (receivedCommand == 2) {
			Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
			Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
			Betriebsart_EG_WZ_Frost.postUpdate(OFF)
			PreBetriebsart_EG_WZ_OH.postUpdate(2)
       }
        else if (receivedCommand == 3) {
            Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
			Betriebsart_EG_WZ_Nacht.postUpdate(ON)
			Betriebsart_EG_WZ_Frost.postUpdate(OFF)
			PreBetriebsart_EG_WZ_OH.postUpdate(3)
        }
        else if (receivedCommand == 4) {
            Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
			Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
			Betriebsart_EG_WZ_Frost.postUpdate(ON)
			PreBetriebsart_EG_WZ_OH.postUpdate(4)
        }
end 
 
rule "Betriebsart EG WZ lesen"
 when
	Item Betriebsart_EG_WZ_Komfort received command or
	Item Betriebsart_EG_WZ_Nacht received command or
	Item Betriebsart_EG_WZ_Frost received command or
	System started
 then
		if (Betriebsart_EG_WZ_Komfort.state == ON) {
			Betriebsart_EG_WZ_OH.postUpdate(1)
			PreBetriebsart_EG_WZ_OH.postUpdate(1)
		}
		else if (Betriebsart_EG_WZ_Nacht.state == ON) {
			Betriebsart_EG_WZ_OH.postUpdate(3)
			PreBetriebsart_EG_WZ_OH.postUpdate(3)
		}
		else if (Betriebsart_EG_WZ_Frost.state == ON) {
			Betriebsart_EG_WZ_OH.postUpdate(4)
			PreBetriebsart_EG_WZ_OH.postUpdate(4)
		}
		else {
			Betriebsart_EG_WZ_OH.postUpdate(2)
			PreBetriebsart_EG_WZ_OH.postUpdate(2)
		}
end
 
rule "Betriebsart EG Kochen senden"
 when
	Item Betriebsart_EG_Kochen_OH received command
 then
        if (receivedCommand == 1) {
			Betriebsart_EG_Kochen_Komfort.postUpdate(ON)
			Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
			Betriebsart_EG_Kochen_Frost.postUpdate(OFF)
			PreBetriebsart_EG_Kochen_OH.postUpdate(1)
       }
	   	else if (receivedCommand == 2) {
			Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
			Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
			Betriebsart_EG_Kochen_Frost.postUpdate(OFF)
			PreBetriebsart_EG_Kochen_OH.postUpdate(2)
       }
        else if (receivedCommand == 3) {
            Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
			Betriebsart_EG_Kochen_Nacht.postUpdate(ON)
			Betriebsart_EG_Kochen_Frost.postUpdate(OFF)
			PreBetriebsart_EG_Kochen_OH.postUpdate(3)
        }
        else if (receivedCommand == 4) {
            Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
			Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
			Betriebsart_EG_Kochen_Frost.postUpdate(ON)
			PreBetriebsart_EG_Kochen_OH.postUpdate(4)
        }
 end 
 
rule "Betriebsart EG Kochen lesen"
 when
	Item Betriebsart_EG_Kochen_Komfort received command or
	Item Betriebsart_EG_Kochen_Nacht received command or
	Item Betriebsart_EG_Kochen_Frost received command or
	System started
 then
		if (Betriebsart_EG_Kochen_Komfort.state == ON) {
			Betriebsart_EG_Kochen_OH.postUpdate(1)
			PreBetriebsart_EG_Kochen_OH.postUpdate(1)
		}
		else if (Betriebsart_EG_Kochen_Nacht.state == ON) {
			Betriebsart_EG_Kochen_OH.postUpdate(3)
			PreBetriebsart_EG_Kochen_OH.postUpdate(3)
		}
		else if (Betriebsart_EG_Kochen_Frost.state == ON) {
			Betriebsart_EG_Kochen_OH.postUpdate(4)
			PreBetriebsart_EG_Kochen_OH.postUpdate(4)
		}
		else {
			Betriebsart_EG_Kochen_OH.postUpdate(2)
			PreBetriebsart_EG_Kochen_OH.postUpdate(2)
		}
end

rule "Betriebsart OG Bad senden"
 when
	Item Betriebsart_OG_Bad_OH received command
 then
        if (receivedCommand == 1) {
			Betriebsart_OG_Bad_Komfort.postUpdate(ON)
			Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
			Betriebsart_OG_Bad_Frost.postUpdate(OFF)
			PreBetriebsart_OG_Bad_OH.postUpdate(1)
       }
	   	else if (receivedCommand == 2) {
			Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
			Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
			Betriebsart_OG_Bad_Frost.postUpdate(OFF)
			PreBetriebsart_OG_Bad_OH.postUpdate(2)
       }
        else if (receivedCommand == 3) {
            Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
			Betriebsart_OG_Bad_Nacht.postUpdate(ON)
			Betriebsart_OG_Bad_Frost.postUpdate(OFF)
			PreBetriebsart_OG_Bad_OH.postUpdate(3)
        }
        else if (receivedCommand == 4) {
            Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
			Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
			Betriebsart_OG_Bad_Frost.postUpdate(ON)
			PreBetriebsart_OG_Bad_OH.postUpdate(4)
        }
 end 
 
rule "Betriebsart OG Bad lesen"
 when
	Item Betriebsart_OG_Bad_Komfort received command or
	Item Betriebsart_OG_Bad_Nacht received command or
	Item Betriebsart_OG_Bad_Frost received command or
	System started
 then
		if (Betriebsart_OG_Bad_Komfort.state == ON) {
			Betriebsart_OG_Bad_OH.postUpdate(1)
			PreBetriebsart_OG_Bad_OH.postUpdate(1)
		}
		else if (Betriebsart_OG_Bad_Nacht.state == ON) {
			Betriebsart_OG_Bad_OH.postUpdate(3)
			PreBetriebsart_OG_Bad_OH.postUpdate(3)
		}
		else if (Betriebsart_OG_Bad_Frost.state == ON) {
			Betriebsart_OG_Bad_OH.postUpdate(4)
			PreBetriebsart_OG_Bad_OH.postUpdate(4)
		}
		else {
			Betriebsart_OG_Bad_OH.postUpdate(2)
			PreBetriebsart_OG_Bad_OH.postUpdate(2)
		}
end

ITEMS:

Code: Alles auswählen

Group	Temperatur
String	TempStr_EG_Wohnen	"Wohnzimmer Soll/Ist  [%s]"	<heating>
Number	TempIst_EG_Wohnen	"Temperatur [%.1f °C]"		<heating>	(Temperatur,EG_WZ_Temp,EG_Wohnen)	{ channel="knx:device:bridge:heizung:TempIst_EG_Wohnen" }
Number	TempSoll_EG_Wohnen	"Solltemperatur [%.1f °C]" 	<heating>	(Temperatur,EG_WZ_Temp,EG_Wohnen)	{ channel="knx:device:bridge:heizung:TempSoll_EG_Wohnen" }
Number	TempBSoll_EG_Wohnen	"Basis Sollwert [%.1f °C]"	<heating>	(EG_WZ_Temp,EG_Wohnen)			    { channel="knx:device:bridge:heizung:TempBSoll_EG_Wohnen" }
Contact	Heizen_EG_Wohnen	"Heizen [MAP(heizen_de.map):%s]"	<heating>	(EG_WZ_Temp)	        	{ channel="knx:device:bridge:heizung:Heizen_EG_Wohnen" }
String	TempStr_EG_Kochen	"Küche Soll/Ist  [%s]"	    <heating>
Number	TempIst_EG_Kochen	"Temperatur [%.1f °C]"		<heating>	(Temperatur,EG_WZ_Temp,EG_Kochen)	{ channel="knx:device:bridge:heizung:TempIst_EG_Kochen" }
Number	TempSoll_EG_Kochen	"Solltemperatur [%.1f °C]" 	<heating>	(Temperatur,EG_WZ_Temp,EG_Kochen)	{ channel="knx:device:bridge:heizung:TempSoll_EG_Kochen" }
Number	TempBSoll_EG_Kochen	"Basis Sollwert [%.1f °C]"	<heating>	(EG_WZ_Temp,EG_Kochen)			    { channel="knx:device:bridge:heizung:TempBSoll_EG_Kochen" }
Contact	Heizen_EG_Kochen	"Heizen [MAP(heizen_de.map):%s]"	<heating>	(EG_WZ_Temp)		        { channel="knx:device:bridge:heizung:Heizen_EG_Kochen" }
String	TempStr_EG_Bad	    "Bad Soll/Ist  [%s]"	    <heating>
Number	TempIst_EG_Bad	    "Temperatur [%.1f °C]"		<heating>	(Temperatur,EG_WZ_Temp,EG_Bad)	    { channel="knx:device:bridge:heizung:TempIst_EG_Bad" }
Number	TempSoll_EG_Bad	    "Solltemperatur [%.1f °C]" 	<heating>	(Temperatur,EG_WZ_Temp,EG_Bad)	    { channel="knx:device:bridge:heizung:TempSoll_EG_Bad" }
Number	TempBSoll_EG_Bad	"Basis Sollwert [%.1f °C]"	<heating>	(EG_WZ_Temp,EG_Bad)			        { channel="knx:device:bridge:heizung:TempBSoll_EG_Bad" }
Contact	Heizen_EG_Bad	    "Heizen [MAP(heizen_de.map):%s]"	<heating>	(EG_WZ_Temp)		        { channel="knx:device:bridge:heizung:Heizen_EG_Bad" }

Number	TempIst_OG_Buero	"Temperatur Büro [%.1f °C]"	    <temperature>	(Nur_Temp)			    { channel="knx:device:bridge:heizung:TempIst_OG_Buero" }
Number	TempIst_EG_Windfang	"Temperatur Winfang [%.1f °C]"	<temperature>	(Nur_Temp)			    { channel="knx:device:bridge:heizung:TempIst_EG_Windfang" }
Number	TempIst_OG_Flur		"Temperatur OG [%.1f °C]"	    <temperature>	(Nur_Temp)			    { channel="knx:device:bridge:heizung:TempIst_OG_Flur" }
Number	TempIst_DG_Flur		"Temperatur DG [%.1f °C]"	    <temperature>	(Nur_Temp)			    { channel="knx:device:bridge:heizung:TempIst_DG_Flur" }
Number	TempKeller		    "Temperatur Keller [%.1f °C]"	<temperature>	(Nur_Temp)			    { exec="<[./configurations/scripts/getTempKeller.sh:300000:REGEX((.*?))]" }
Number	HumKeller		    "Luftfeuchte Keller [%.1f %%]"	<temperature>	(Nur_Temp)				{ exec="<[./configurations/scripts/getHumiKeller.sh:300000:REGEX((.*?))]" }


Number	Modus_Heizen "Modus Heizen"
Group   BetriebsartOH
Group   BetriebsartKNX

Number	Betriebsart_EG_WZ_OH		    "Betriebsart WZ"	<betriebsart>	(BetriebsartOH)
Number	PreBetriebsart_EG_WZ_OH		    "Betriebsart"		<betriebsart>	(BetriebsartOH)
Switch	Betriebsart_EG_WZ_Komfort	    "Komfort"   		<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_EG_WZ_Komfort" }
Switch	Betriebsart_EG_WZ_Nacht		    "Nacht"		    	<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_EG_WZ_Nacht" }
Switch	Betriebsart_EG_WZ_Frost		    "Frost"			    <heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_EG_WZ_Frost" }
Number	Betriebsart_EG_Kochen_OH	    "Betriebsart Küche"	<betriebsart>	(BetriebsartOH)
Number	PreBetriebsart_EG_Kochen_OH	    "Betriebsart"		<betriebsart>	(BetriebsartOH)
Switch	Betriebsart_EG_Kochen_Komfort	"Komfort"   		<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_EG_Kochen_Komfort" }
Switch	Betriebsart_EG_Kochen_Nacht	    "Nacht"		    	<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_EG_Kochen_Nacht" }
Switch	Betriebsart_EG_Kochen_Frost 	"Frost"			    <heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_EG_Kochen_Frost" }
Number	Betriebsart_OG_Bad_OH		    "Betriebsart Bad"	<betriebsart>	(BetriebsartOH)
Number	PreBetriebsart_OG_Bad_OH    	"Betriebsart"		<betriebsart>	(BetriebsartOH)
Switch	Betriebsart_OG_Bad_Komfort	    "Komfort"   		<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_OG_Bad_Komfort" }
Switch	Betriebsart_OG_Bad_Nacht	    "Nacht"		    	<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_OG_Bad_Nacht" }
Switch	Betriebsart_OG_Bad_Frost	    "Frost"			    <heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_OG_Bad_Frost" }
Number	Betriebsart_Alle_OH		        "Betriebsart Alle"	<betriebsart>	(BetriebsartOH)
Switch	Betriebsart_Alle_Komfort	    "Komfort"	    	<heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_Alle_Komfort" }
Switch	Betriebsart_Alle_Nacht		    "Nacht"			    <heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_Alle_Nacht" }
Switch	Betriebsart_Alle_Frost		    "Frost"			    <heating>		(BetriebsartKNX)	{ channel="knx:device:bridge:heizung:Betriebsart_Alle_Frost" }

Benutzeravatar
udo1toni
Beiträge: 15248
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Umstieg von OH1

Beitrag von udo1toni »

Vorweg: Sorry für die Bleiwüste...

Also, ich kann ja verstehen, dass man die Version 2 nicht noch anfängt, wenn doch die 3 schon lang stable ist, aber... Der Sprung ist schon weit. Vor allem, wo die Basic UI nur noch gerade so dabei ist (neu war die vor etwa 6 Jahren...)

Ein paar wichtige Dinge, auf die ich Dich gezielt aufmerksam machen möchte, da das Verhalten von openHAB, bezüglich knx ab Version 2.3 (da kam das knx2 Binding mit Things...) komplett anders ist als in openHAB1 mit dem knx1 Binding:

Früher gab es bei knx keinen Unterschied zwischen received update und received command. Das ist mit knx2/3 anders. Nun ist es so, dass Telegramme aus knx von openHAB grundsätzlich als Status gewertet werden. Deshalb löst ein Datentelegramm nun in der Rule engine nur noch die Trigger changed und received update aus, nicht aber received command.
Es kann aber sein, dass Du von knx aus ein Gerät steuern möchtest, welches gar nicht in knx eingebunden ist, sondern nur in openHAB zur Verfügung steht. Dazu musst Du dann *-control Channel verwenden. Die *-control Channel kehren die Kommunikation um, das heißt, openHAB wertet Datentelegramme solcher Channel als command und sendet auf solche Channel ausschließlich Status. Dieses Verhalten ist einzigartig im openHAB Umfeld, ein postUpdate in einer Rule auf ein Item, welches mit einem *-control Channel verlinkt ist, löst ein Datentelegramm in Richtung Bus aus.
openHAB ist per Definition in diesen Fällen "Eigentümer" des Status, kann also den Status auch nicht in knx abfragen, auch wenn das < bei einer GA gesetzt ist. Das hat schon oft zu Verwirrung geführt, ist aber logisch erklärbar.

Weiterhin (weil Deine Rule entsprechende Funktionen enthält) ist eine fast noch wichtigere Änderung der Wegfall von Joda Time. Das ist der Teil, der für now.getDayOfWeek usw. zuständig ist. Joda Time wurde durch JavaTime abgelöst, welches seit Java8 regulär zur Verfügung steht. Damit ist Joda Time überflüssig geworden (auch die Entwickler von Joda Time empfahlen den Umstieg). JavaTime verwendet in Teilen ein leicht abweichende Syntax, an anderen Stellen funktioniert es exakt gleich, an wiederum anderen Stellen funktioniert es radikal anders, weshalb Rules mit Bezug auf now() sehr genau überprüft werden müssen, um sicherzustellen, dass sie weiterhin wie gewünscht funktionieren.

Womit wir bei Deinen Rules sind. Allerdings scheue ich mich, die Rules gleich anzufassen denn:

Das erste, was mir auffällt, ist, dass Du offensichtlich die RTR für die Betriebsart im Bit-Modus betreibst. Hat das einen besonderen Grund?
Laut Handbuch unterstützen die Triton auch ein Byte als KO, mit den erlaubten Werten 0 - 4 für die fünf verschiedenen Betriebsarten. Das würde Dir schon mal eine Menge unnötiger Zeilen und sogar Items und Channel ersparen. Und wo wir bei Channels entlang schrammen :) es sieht für mich stark danach aus, als hättest Du ein generic Device "heizung" angelegt und dort alle RTR Funktionen hineingepackt. Das ist aus verschiedenen Gründen suboptimal.

Das Wichtigste: das Thing Modell ist so gedacht, dass jedes Gerät ein Thing ist. Alle Aspekte eines Geräts, die gemessen und/oder gesteuert werden können, werden dann als Channel dieses Geräts abgebildet. Ein einfacher Dimmer ohne alles hätte also nur einen einzigen Channel, ein 6-fach Schaltaktor ohne Strommessung und solchem Firlefanz ;) hätte sechs Channel.
Der RTR hat drei Channel oder auch mehr, aber die drei Channel gehören auf jeden Fall zum RTR, die Ist-Temperatur, die Soll-Temperatur und die Betriebsart.
Hast Du nun mehrere solche RTR, so hat jeder diese drei Channel. Da man Things hervorragend auch über Textdateien anlegen kann, kannst Du ein Thing erstellen und dieses zweimal kopieren, die GA anpassen, die Namen der Kopien anpassen, fertig. Der Unterschied ist dann im Link zu sehen. Statt

Code: Alles auswählen

{ channel="knx:device:bridge:heizung:TempIst_EG_Wohnen" }
{ channel="knx:device:bridge:heizung:TempIst_EG_Kochen" }
z.B.

Code: Alles auswählen

{ channel="knx:device:bridge:RTRwohnen:TempIst" }
{ channel="knx:device:bridge:RTRkochen:TempIst" }
Die Zuordnung erfolgt also über das Device, nicht über eine Unterscheidung des Channels.
Beide Arten der Konfiguration sind grundsätzlich möglich, aber die strikte Trennung nach Hardware bietet auch andere Vorteile, z.B. kannst Du mit der Ping-Funktion überwachen, dass das Gerät erreichbar ist. Dazu muss aber die physikalische Adresse im Thing hinterlegt werden, was nur einmal pro Thing geht, Du könntest also nur eines der RTR prüfen.

Man kann das ganze auch als hierarchisches System betrachten. Es gibt eine Bridge, über die der Bus zur Verfügung gestellt wird. Man könnte auch weitere knx Universen über weitere Bridges anbinden, notfalls könnte man mit einer einzigen openHAB Instanz alle knx Systeme weltweit steuern (auch wenn ich nicht wissen möchte, wieviele Gigabyte die Textdateien benötigen würden und wie lange so ein System zum starten bräuchte...)
Die Bridge ist also am ehesten mit dem Bus gleichzusetzen, weil sie Zugang zum Bus gewährt.
Die Things entsprechen dann den einzelnen Geräten, jedes gerät bietet einen exakt definierten Funktionsumfang. Die einzelnen Aspekte werden dann über die Channel bereitgestellt, wobei die Definition der Channel für gleiche Geräte auch gleich aussehen kann.

Die Zuordnung der Funktion zum Channel (Deckenlicht Wohnzimmer, Temperatur Küche usw.) kann man gerne schon im Label des Channels vornehmen, denn dieser wird von openHAB schon herangezogen, um Items zu erzeugen (allerdings sollte man das dennoch von Hand erledigen, die entstehenden Namen sind einfach zu lang...)

Ich habe mir jetzt dennoch mal die Rules angeschaut und ein wenig optimiert - wobei man das alles wesentlich einfacher gestalten könnte. Der erste Schritt dazu wäre aber, die RTR auf Byte umzustellen, so dass eine Zahl 0 - 4 geliefert wird, entsprechend den 5 verschiedenen Betriebsarten.
Deshalb hier erst mal nur die optimierte Version, so wie Deine Rules ursprünglich funktionierten:

Code: Alles auswählen

rule "Modus Heizen"
 when
    Item Modus_Heizen received update
    or
    Time cron "0 10 * * * ?"
 then
    val nDay    = now.getDayOfWeek.getValue
    val nHour   = now.getHour
    val nMinute = now.getMinute
    var bNacht  = false

    var nUseMode = 2
    if(Modus_Heizen.state instanceof Number)
        nUseMode = Modus_Heizen.state as Number

    var nLate   = 21
    var nEarly  = 6
    if(nDay == 5 || nDay == 6) nLate = 22
    if(nDay > 5) nEarly = 7
    if( nHour < nEarly || nHour > nLate ) bNacht = true

    if(nUseMode == 3 && !bNacht) nUseMode = 1

    logInfo("test", "Modus heizen Schleife")

    Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
    Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
    Betriebsart_EG_WZ_Frost.postUpdate(OFF)
    Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
    Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
    Betriebsart_EG_Kochen_Frost.postUpdate(OFF)
    Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
    Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
    Betriebsart_OG_Bad_Frost.postUpdate(OFF)

    switch(nUseMode) {
        case 1 : {
            if(Modus_Heizen.state.toString == "3")
                logInfo("test", "Modus heizen = Tag")
            else
                logInfo("test", "Modus heizen = Normal")
            Betriebsart_EG_WZ_OH.sendCommand(PreBetriebsart_EG_WZ_OH.state as DecimalType)
            Betriebsart_EG_Kochen_OH.sendCommand(PreBetriebsart_EG_Kochen_OH.state as DecimalType)
            Betriebsart_OG_Bad_OH.sendCommand(PreBetriebsart_OG_Bad_OH.state as DecimalType)
        }
        case 2 : {
            logInfo("test", "Modus heizen = Abwesend")
            Betriebsart_EG_WZ_OH.postUpdate(2)
            Betriebsart_EG_Kochen_OH.postUpdate(2)
            Betriebsart_OG_Bad_OH.postUpdate(2)
        }
        case 3 : {
            logInfo("test", "Modus heizen = Nacht")
            Betriebsart_EG_WZ_Nacht.postUpdate(ON)
            Betriebsart_EG_WZ_OH.postUpdate(3)
            Betriebsart_EG_Kochen_Nacht.postUpdate(ON)
            Betriebsart_EG_Kochen_OH.postUpdate(3)
            Betriebsart_OG_Bad_Nacht.postUpdate(ON)
            Betriebsart_OG_Bad_OH.postUpdate(3)
        }
        case 4 : {
            logInfo("test", "Modus heizen = Frost")
            Betriebsart_EG_WZ_Frost.postUpdate(ON)
            Betriebsart_EG_WZ_OH.postUpdate(4)
            Betriebsart_EG_Kochen_Frost.postUpdate(ON)
            Betriebsart_EG_Kochen_OH.postUpdate(4)
            Betriebsart_OG_Bad_Frost.postUpdate(ON)
            Betriebsart_OG_Bad_OH.postUpdate(4)
        }
    }

rule "Betriebsart EG WZ senden"
 when
    Item Betriebsart_EG_WZ_OH received command
 then
    var nModus = 2
    if(receivedCommand instanceof Number)
        nModus = receivedCommand as Number
    PreBetriebsart_EG_WZ_OH.postUpdate(nModus)

    Betriebsart_EG_WZ_Komfort.postUpdate(OFF)
    Betriebsart_EG_WZ_Nacht.postUpdate(OFF)
    Betriebsart_EG_WZ_Frost.postUpdate(OFF)

    switch(nModus) {
        case 1 : Betriebsart_EG_WZ_Komfort.postUpdate(ON)
        case 3 : Betriebsart_EG_WZ_Nacht.postUpdate(ON)
        case 4 : Betriebsart_EG_WZ_Frost.postUpdate(ON)
    }
end 
 
rule "Betriebsart EG WZ lesen"
 when
    Item Betriebsart_EG_WZ_Komfort received command or
    Item Betriebsart_EG_WZ_Nacht received command or
    Item Betriebsart_EG_WZ_Frost received command or
    System started
 then
    var nModus = 2
    if(Betriebsart_EG_WZ_Komfort.state == ON)    nModus = 1
    else if(Betriebsart_EG_WZ_Nacht.state == ON) nModus = 3
    else if(Betriebsart_EG_WZ_Frost.state == ON) nModus = 4

    Betriebsart_EG_WZ_OH.postUpdate(nModus)
    PreBetriebsart_EG_WZ_OH.postUpdate(nModus)
end
 
rule "Betriebsart EG Kochen senden"
 when
    Item Betriebsart_EG_Kochen_OH received command
 then
    var nModus = 2
    if(receivedCommand instanceof Number)
        nModus = receivedCommand as Number
    PreBetriebsart_EG_Kochen_OH.postUpdate(nModus)

    Betriebsart_EG_Kochen_Komfort.postUpdate(OFF)
    Betriebsart_EG_Kochen_Nacht.postUpdate(OFF)
    Betriebsart_EG_Kochen_Frost.postUpdate(OFF)

    switch(nModus) {
        case 1 : Betriebsart_EG_Kochen_Komfort.postUpdate(ON)
        case 3 : Betriebsart_EG_Kochen_Nacht.postUpdate(ON)
        case 4 : Betriebsart_EG_Kochen_Frost.postUpdate(ON)
    }
end 
 
rule "Betriebsart EG Kochen lesen"
 when
    Item Betriebsart_EG_Kochen_Komfort received command or
    Item Betriebsart_EG_Kochen_Nacht received command or
    Item Betriebsart_EG_Kochen_Frost received command or
    System started
 then
    var nModus = 2
    if(Betriebsart_EG_Kochen_Komfort.state == ON)    nModus = 1
    else if(Betriebsart_EG_Kochen_Nacht.state == ON) nModus = 3
    else if(Betriebsart_EG_Kochen_Frost.state == ON) nModus = 4

    Betriebsart_EG_Kochen_OH.postUpdate(nModus)
    PreBetriebsart_EG_Kochen_OH.postUpdate(nModus)
end

rule "Betriebsart OG Bad senden"
 when
    Item Betriebsart_OG_Bad_OH received command
 then
    var nModus = 2
    if(receivedCommand instanceof Number)
        nModus = receivedCommand as Number
    PreBetriebsart_OG_Bad_OH.postUpdate(nModus)

    Betriebsart_OG_Bad_Komfort.postUpdate(OFF)
    Betriebsart_OG_Bad_Nacht.postUpdate(OFF)
    Betriebsart_OG_Bad_Frost.postUpdate(OFF)

    switch(nModus) {
        case 1 : Betriebsart_OG_Bad_Komfort.postUpdate(ON)
        case 3 : Betriebsart_OG_Bad_Nacht.postUpdate(ON)
        case 4 : Betriebsart_OG_Bad_Frost.postUpdate(ON)
    }
end 

rule "Betriebsart OG Bad lesen"
 when
    Item Betriebsart_OG_Bad_Komfort received command or
    Item Betriebsart_OG_Bad_Nacht received command or
    Item Betriebsart_OG_Bad_Frost received command or
    System started
 then
    var nModus = 2

    if(Betriebsart_OG_Bad_Komfort.state == ON) nModus = 1
    else if(Betriebsart_OG_Bad_Nacht.state == ON) nModus = 3
    else if(Betriebsart_OG_Bad_Frost.state == ON) nModus = 4

    Betriebsart_OG_Bad_OH.postUpdate(nModus)
    PreBetriebsart_OG_Bad_OH.postUpdate(nModus)
end
Die erste Vereinfachung gleich zu Beginn, statt zig verschachtelte Vergleiche setze ich zwei einfache Variablen und mache einen vergleich, der die Boolean Variable setzt. Dann werden eigentlich alle Items auf OFF gesetzt, bis auf jeweils eines pro RTR, falls Modus 1,3, oder4 gelten. Es ist also durchaus effizient, alle auf OFF zu setzen und dann nur die ON zu setzen, die ON sein sollen. der RTR kippt maximal ein paar Millisekunden auf Abwesend. Selbst jetzt ließe sich da noch ein bisschen was optimieren :)
die anderen Rules sind für die Einzelsteuerung, auch hier bietet sich der Weg über "alle OFF, anschließend eines davon ON" an, Du siehst ja, wie viele Zeilen Code das spart.

Aber es geht noch wesentlich kompakter, wenn die Items passende Namen tragen und gut gruppiert sind.

Nur als beispiel die Rule, welche sich um meine neun RTR kümmert:

Code: Alles auswählen

rule "Betriebsart RTR"
 when
    Member of GHeat_Mode changed
 then
    var Integer newMode
    val mode = (triggeringItem.state as DecimalType).toBigDecimal.toBigInteger
    val iName = triggeringItem.name.split("_").get(0).toString
    logDebug("rtr","Name is: {}, Mode is: {}",iName,mode)
    switch (mode) {
        case mode.testBit(0) : newMode = 1
        case mode.testBit(2) : newMode = 3
        case mode.testBit(3) : newMode = 4
        default : newMode = 2
    }
    var myItem = GHeat_Set.members.filter[ f | f.name.startsWith(iName) ].head
    var Integer oldMode = 0
    if(myItem.state instanceof Number) oldMode = (myItem.state as Number).intValue
    if(oldMode != newMode) {
        logDebug("rtr","Name is: {}, oldMode is: {}, newMode is: {}",myItem.name,oldMode,newMode)
        myItem.postUpdate(newMode)
    }
end
Ich benötige die Rule, weil die Steuerung über ein Byte erfolgt, wobei die gültigen Steuerwerte 1 - 4 sind, die Rückmeldung erfolgt auch über eine Byte, aber hier hat jedes Bit eine bestimmte Bedeutung. Bit 0 entspricht dabei Modus 1, Bit1 entspricht Modus 2, Bit2 entspricht Modus 3 und Bit3 entspricht Modus 4. Ich kann von openHAB aus unkompliziert den Modus umschalten - einfach den gewünschten Modus als Zahl senden (1,2,3,4). Schalte ich aber am RTR selbst um, kommt eben als Ergebnis 33,34,36 oder 40 (das Bit4 ist bei mir immer gesetzt, es steht für Heizbetrieb).

Deshalb setzt diese Rule die Werte entsprechend um.
Der eigentliche Witz ist aber, dass die beteiligten Items sich in zwei Gruppen befinden. gHeat_Mode enthält alle Rückmeldungen der RTR, gHeat_Set enthält alle Items zum Setzen der Betriebsart. Dabei ist der erste Teil des Namens jeweils identisch, also z.B. RTRWohnzimmer_ModeSet und RTRWohnzimmer_ModeGet (heißen bei mir anders, hab aber gerade keine Lust nachzuschauen). Der Punkt ist, dass openHAB nun aus der zweiten Gruppe leicht das passende Gegenstück zu dem Item heraussuchen kann, welches die Rule ausgelöst hat.
In der UI verwende ich direkt die Sende-Items.
Zunächst erzeuge ich eine Arbeitsvariable (newMode) und setze eine lokale Konstante (mode) auf den Status des Items, welches die Rule ausgelöst hat (triggeringItem.state), wobei ich hier einen ganz bestimmten datentyp haben möchte, nämlich BigInteger. Das hängt mit der verwendeten Funktion .testBit() zusammen, die nut für BigInteger zur Verfügung steht.
Anschließend ermittle ich den ersten Teil des Namens des Items, welches die Rule ausgelöst hat.
Als nächstes setze ich newMode auf den neuen Wert. Dabei ist Modus 2 quasi der Default Wert, falls das Item etwas Unsinniges melden sollte (keines der unteren 4 Bits gesetzt).

Danach suche ich noch aus der zweiten Gruppe das passende Gegenstück anhand des Namens heraus und setzen eine lokale Variable mit dem aktuellen Status, falls dieser einen sinnvollen Wert hat. Ansonsten kommt halt 0 rein.
Nur falls der aktuelle Status vom Soll abweicht, wird zum Abschluss das Item gesetzt.

Die Rule könnte sich auch um 1000 RTR kümmern und würde nicht um ein einziges Zeichen anwachsen.
Ich denke, Du erkennst das Potential für Deine Rules :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

uweu
Beiträge: 17
Registriert: 7. Dez 2020 15:29
Answers: 0

Re: Umstieg von OH1

Beitrag von uweu »

Hallo Udo,
erstmal Danke für deine ausführlichen Erklärungen, das muss ich mir mal in Ruhe zu Gemüte führen.
Vielleicht hätte ich schon früher mal hier was schreiben sollen ;)

Meinst du es lohnt sich die ganzen Things, Channels und Items noch mal neu anzulegen?

Weiß auch nicht ob es mehr Sinn macht mit Textdateien zu arbeiten oder über das Webinterface,
vor allem wieso kann ich die Daten dann nicht im jeweils anderen System bearbeiten???

Wegen der RTR, der Grund ist dass ich nicht gefunden habe wo ich die Betriebsart auf Byte umstellen kann.
Ist mein Applikationsprogramm evtl. zu alt? Ich habe z.B. 5fach RTR 6327-20 ich glaube die können nur bit.

Wegen der BasicUI meinst du die wird es nicht mehr lange geben?
Welches UI würdest du empfehlen für Handys und Tablets?

Benutzeravatar
udo1toni
Beiträge: 15248
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Umstieg von OH1

Beitrag von udo1toni »

uweu hat geschrieben: 29. Okt 2022 09:50 Meinst du es lohnt sich die ganzen Things, Channels und Items noch mal neu anzulegen?
Auf jeden Fall, falls Du sie nicht gerätebezogen angelegt hast.
uweu hat geschrieben: 29. Okt 2022 09:50 Weiß auch nicht ob es mehr Sinn macht mit Textdateien zu arbeiten oder über das Webinterface,
vor allem wieso kann ich die Daten dann nicht im jeweils anderen System bearbeiten???
Da Du gewohnt bist, Dinge in Textdateien zu erledigen, wäre meine Empfehlung: bleib bei Textdateien.
openHAB verwendet intern allerdings ein anderes Format zum Speichern der Konfiguration. Damit nicht alles Durcheinander kommt, ist die Vorgehensweise folgende: Bei Systemstart wird der Inhalt der Webkonfiguration ins RAM geladen, ebenso werden die Textdateien eingelesen und passende Konfigurationen dazu erstellt, die ebenfalls im RAM landen. Wird eine Änderung an einer der Textdateien erkannt, werden die entsprechenden Items aus der Konfiguration entfernt und neu angelegt. Vorteil ist, dass man das relativ leicht umsetzen kann, der Parser zum Umsetzen der Konfiguration ist schon vorhanden (wenn auch komplett neu programmiert...) und Anwender können einfach mit ihren Textdateien weiter arbeiten.
Man kann beide Konfigurationsarten parallel nebeneinander nutzen (mit Einschränkungen) und weil alles, was Text ist in der UI Read Only ist, müssen auch keine besonderen Vorkehrungen getroffen werden.
Nachteil: Die beiden Konfigurationsarten haben keine Ahnung voneinander. Das höchste der Gefühle ist, dass Du in der UI zumindest die angelegten Sachen aus den Textdateien sehen (aber nicht bearbeiten) kannst. Da es kein Gegenstück zum Parser gibt, kann man UI-Konfiguration noch nicht mal in Textdateien exportieren.
Dieser Problemkomplex ist bestens bekannt, und zwar seit openHAB2.0. Daran wird sich auch nichts ändern, höchstens (da sei Gott vor!) dass die Textkonfiguration komplett gestrichen wird.

Ich bin mit OH1.0 eingestiegen und habe damals weniger als zehn Minuten gebraucht, eine erste knx Lampe zu schalten (MIT! Download). Es war so wahnsinnig einfach, zip-Ordner der Runtime entpacken, Demo entpacken, Dateien in die Konfig-Ordner kopieren, tada, Demo geht. knx Binding dazu packen, ein paar GA raus suchen und eintragen, zack, Licht geht.

So einfach.

Mit der UI (OH2.0 Paper UI...) hatte ich lange zu kämpfen, bis ich es hinbekommen habe, ein einzelnes Licht anzulegen. Ich habe anschließend gelacht und beschlossen, die UI nur für Autodiscovery zu nutzen, das ist echter Komfort, der mit Textdateien nicht erreicht werden kann.
Wenn ich aber 100 Channel manuell definieren muss, weil knx bis heute weder Autodiscovery (wie soll das zuverlässig funktionieren) noch Import der knx Projektdatei erlaubt (da gab es auch mal einen Ansatz), sehe ich gerade bei knx nur Nachteile, denn in einer Textdatei lege ich einen Channel an und kopiere die Zeile und passe nur noch die Unterschiede an, das geht ratz-fatz (ich muss dazu sagen, dass mein GA-Modell dieser Arbeitsweise extrem entgegen kommt).

Mit VisualStudio Code steht ein extrem potenter Editor zur Verfügung, der mit dem openHAB Plugin nicht nur eine dynamische Anzeige der Things, Channel und Items bietet (mit Status...), sondern auch noch über den Kontext automatisches Generieren von Konfigurationsteilen erlaubt (Rechtsklick auf ein Thing, create Items for Chanels, bääm hat man einen Satz Items in der aktuellen *.items Datei, in der man dann nur noch Gruppen ergänzen oder auch Itemnamen anpassen muss - noch wesentlich schneller als das Semantic Model (was allerdings wieder ganz anders funktioniert...)
uweu hat geschrieben: 29. Okt 2022 09:50 Wegen der RTR, der Grund ist dass ich nicht gefunden habe wo ich die Betriebsart auf Byte umstellen kann.
Ist mein Applikationsprogramm evtl. zu alt? Ich habe z.B. 5fach RTR 6327-20 ich glaube die können nur bit.
Oh. Ja, den Typ hattest Du oben nicht angegeben. Ja, das erklärt es. Macht aber nichts, wir können dennoch die Rules passend generalisieren, wird nur ein wenig komplizierter, ist aber machbar. Allerdings sollten die Itemnamen etwas geändert werden.
Auch was die Verwendung von postUpdate und sendCommand betrifft, müssen die Regeln noch etwas korrigiert werden, denn wie erwähnt wirkt postUpdate() nur auf den Status eines Items, nicht aber auf den knx Bus.

Hast Du die Things per UI oder per Text angelegt?
uweu hat geschrieben: 29. Okt 2022 09:50 Wegen der BasicUI meinst du die wird es nicht mehr lange geben?
Welches UI würdest du empfehlen für Handys und Tablets?
Doch, die Basic UI wird es bestimmt noch eine Weile geben. Die Main UI wird uns mit Sicherheit ebenfalls längere Zeit erhalten bleiben, und die ist schon sehr mächtig. Man kann sich selbst Widgets bauen (die entsprechenden Skills mal vorausgesetzt), was bei Classic UI/Basic UI einfach nicht vorgesehen ist.
Die openHAB App (Android/iOS) kann sowohl mit Sitemaps als auch mit Pages (das ist Main UI) umgehen.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

uweu
Beiträge: 17
Registriert: 7. Dez 2020 15:29
Answers: 0

Re: Umstieg von OH1

Beitrag von uweu »

Auf jeden Fall, falls Du sie nicht gerätebezogen angelegt hast.
Puh, hab ich nicht :(
Die Idee war es etwas übersichtlicher zu gestalten...
Hast Du die Things per UI oder per Text angelegt?
Die KNX Things hab ich in der UI angelegt und die Channels dann per Code, die Items und rules hab ich in Textdateien.
War mir nie sicher wann ich was nehmen soll. VS Code hab ich auch schon im Einsatz!
Ich bin mit OH1.0 eingestiegen und habe damals weniger als zehn Minuten gebraucht, eine erste knx Lampe zu schalten (MIT! Download). Es war so wahnsinnig einfach, zip-Ordner der Runtime entpacken, Demo entpacken, Dateien in die Konfig-Ordner kopieren, tada, Demo geht. knx Binding dazu packen, ein paar GA raus suchen und eintragen, zack, Licht geht.
Ging mir auch so, KNX war mit OH1 echt mega einfach im vergleich zu jetzt.
Hab sogar schon überlegt was anders zu nehmen :?

Ich denke ich bleib erstmal bei der BasicUI, noch eine Baustelle wird mir zu viel im Mom ;)

Benutzeravatar
udo1toni
Beiträge: 15248
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Umstieg von OH1

Beitrag von udo1toni »

Mein Tipp: Leg die Things ebenfalls per Text an. Sieht bei mir so aus:

Code: Alles auswählen

Bridge knx:ip:bridge "Weinzierl 730 IP" [ 
    ipAddress="192.168.178.138", 
    localIp="192.168.178.146", 
    type="TUNNEL", 
    portNumber=3671, 
    readingPause=50, 
    responseTimeout=10, 
    readRetriesLimit=3, 
    autoReconnectPeriod=60,
    localSourceAddr="0.0.0"
 ]

 {
    Thing device thebenBin1_1_1 "Tor vorne" [ 
        address="1.1.1",
        fetch=false,
        pingInterval=600,
        readInterval=0
     ] {
        Type switch                 : ch1 "Gehtor vorn"         [ ga="0/4/40" ]
        Type switch                 : ch2 "Tor vorn"            [ ga="0/4/43" ]
        Type contact                : ch3 "Tor 1 auf"           [ ga="0/4/49" ]
        Type contact                : ch4 "Tor 1 zu"            [ ga="0/4/46" ]
        Type contact                : ch5 "Tor 2 auf"           [ ga="0/4/55" ]
        Type contact                : ch6 "Tor 2 zu"            [ ga="0/4/52" ]
    }
    Thing device hagerDim1_1_5 "DimmerGruppe 1" [ 
        address="1.1.5",
        fetch=false,
        pingInterval=600,
        readInterval=0
     ] {
        Type dimmer                 : ch1 "Strahler Buffet"     [ switch="3/5/20",position="5.001:3/5/22+<3/5/27" ]
        Type dimmer                 : ch2 "Strahler Couch"      [ switch="3/5/0",position="5.001:3/5/2+<3/5/7" ]
        Type dimmer                 : ch3 "Strahler Essen"      [ switch="3/5/10",position="5.001:3/5/12+<3/5/17" ]
    }
    Thing device HagerBin1_1_11 "SchaltGruppe 1" [ 
        address="1.1.11",
        fetch=false,
        pingInterval=600,
        readInterval=0
     ] {
        Type switch                 : ch1 "Wozi Stehlampe"      [ ga="1.001:3/4/30+<3/4/34" ]
        Type switch                 : ch2 "Bad OG"              [ ga="1.001:7/4/0+<7/4/4" ]
        Type switch                 : ch3 "Wozi Vitrine"        [ ga="1.001:3/4/50+<3/4/54" ]
        Type switch                 : ch4 "Licht Außen vorn"    [ ga="1.001:0/4/10+<0/4/14" ]
        Type switch                 : ch5 "Wozi Buffet"         [ ga="1.001:3/4/40+<3/4/44" ]
        Type switch                 : ch6 "Flur"                [ ga="1.001:2/4/10+<2/4/14" ]
    }
    Thing device HagerShut1_1_41 "RollGruppe 1" [ 
        address="1.1.41",
        fetch=false,
        pingInterval=600,
        readInterval=0
     ] {
        Type rollershutter          : ch1 "Räder"               [ upDown="6/6/0",stopMove="6/6/1",position="5.001:6/6/3+<6/6/4" ]
        Type rollershutter          : ch2 "Technik"             [ upDown="5/6/0",stopMove="5/6/1",position="5.001:5/6/3+<5/6/4" ]
        Type rollershutter          : ch3 "Küche West"          [ upDown="4/6/0",stopMove="4/6/1",position="5.001:4/6/3+<4/6/4" ]
        Type rollershutter          : ch4 "Küche Nord"          [ upDown="4/6/10",stopMove="4/6/11",position="5.001:4/6/13+<4/6/14" ]
        Type rollershutter          : ch5 "Flur"                [ upDown="2/6/0",stopMove="2/6/1",position="5.001:2/6/3+<2/6/4" ]
        Type rollershutter          : ch6 "Ost1"                [ upDown="3/6/0",stopMove="3/6/1",position="5.001:3/6/3+<3/6/4" ]
        Type rollershutter          : ch7 "Ost2"                [ upDown="3/6/10",stopMove="3/6/11",position="5.001:3/6/13+<3/6/14" ]
        Type rollershutter          : ch8 "Süd1"                [ upDown="3/6/20",stopMove="3/6/21",position="5.001:3/6/23+<3/6/24" ]
    }
    Thing device GiraTSplus1_1_100 "TS2plus Flur" [ 
        address="1.1.100",
        fetch=false,
        pingInterval=600,
        readInterval=0
     ] {
        Type number                 : tempIs "Temperatur ist"           [ ga="<2/7/23" ]
        Type number                 : tempSet "Temperatur soll"         [ ga="9.001:2/7/26+<2/7/50" ]
        Type number                 : opMode "Betriebsart ist"          [ ga="5.005:<2/7/36" ]
        Type number                 : opSet "Betriebsart soll"          [ ga="5.005:2/7/28" ]
        Type switch                 : heat "Heizen"                     [ ga="2/7/37" ]
        Type switch                 : ch6 "Putzen"                      [ ga="2/4/101" ]
    }
    Thing device Virtuell "virtuelle" [ 
     ] {
        Type number-control         : ch1 "Stoptaste"           [ ga="5.005:7/6/253" ]
        Type switch-control         : ch2 "Tor hinten 1"        [ ga="0/4/61" ]
        Type switch-control         : ch3 "Tor hinten 2"        [ ga="0/4/62" ]
        Type number-control         : ch4 "Lux set/get"         [ ga="5.005:0/7/3" ]
        Type number-control         : scene1 "Lichtszene"       [ ga="17.001:3/0/0" ]
        Type number-control         : scene2 "Rolloszene"       [ ga="17.001:15/6/39" ]
        Type number-control         : tempOut "Temperatur"      [ ga="15/7/0" ]
        Type datetime-control       : wochenzeit "Zeit und Tag" [ ga="10.001:15/7/10" ]
//        Type datetime-control       : datum "Datum"             [ ga="11.001:15/7/11" ]
//        Type datetime-control       : zeit "Zeit"               [ ga="19.001:15/7/19" ]
        Type switch-control         : sommer "Sommer"           [ ga="15/4/1" ]
    }

}
Ein Ausschnitt meiner Konfiguration. Man kann sehr schön dfie Struktur der Geräte erkennen, und wenn man die Channel Label mit den GA abgleicht, kann man erahnen, wie das bei mir funktioniert... erster Teil = Raum (32 Räume dürften bei fast jedem reichen), zweiter Teil = Typ (8 verschiedene Kategorien, wie Switch, Dimmer, Rollladen, Heizung. Letzter Teil orientiert sich an der KO Nummer des ersten Channels eines REG bzw. UPG. Sind mehrere Channel des selben Typs in einem Raum verbaut (z.B. Dimmer und Rollläden) so zähle ich immer um 10 hoch. Dadurch muss ich fast immer lediglich eine Stelle innerhalb der GA anpassen, wenn ich einen Channel kopiere.
Wen ein REG mehrere Channel hat (das ist ja meist der Fall) so heißen dei bei mit einfach ch1, ch2 usw. Die Verknüpfung zum Item ist damit nur auf das Gerät bezogen, nicht aber auf eine bestimmte Funktion. Die ergibt sich dafür aus dem Namen des Items
Für mich ist das extrem logisch und da die Things streng nach Hardware angelegt sind (bis auf das letzte Thing, welches logische GA enthält, die keine bestimmte Hardware haben, z.B. Die Uhrzeit und das Datum, Szenen oder auch die Sommer/Winter Kennung), weiß ich auch innerhalb openHAB beim konfigurieren jederzeit, welcehs Gerät gerade angesprochen wird.
Die physikalische Adresse habe ich im Thingnamen integriert, ist eigentlich unnötig, schadet aber auch nicht. Ansonsten kannst Du am Thingnamen auch den Hersteller und die Art der Hardware ablesen.

das ist natürlic hnur meine Art, die Things zu organisieren, andere haben eine andere Herangehensweise. An der Hardware sollte man sich aber orientieren, denn Things und Channel abstrahieren die Haredware, und Der Teil der Konfiguration, der dsich nur auf das Thing bezieht (vor den Channels des Things in eckigen Klammern) sorgt eben dafür, dass man in openHAB sehen kann, ob ein Gerät am Bus nicht mehr erreichbar ist.

EDIT: @ "KNX" aus dem Code entfernt, da unter OH3 ohne Funktion
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

uweu
Beiträge: 17
Registriert: 7. Dez 2020 15:29
Answers: 0

Re: Umstieg von OH1

Beitrag von uweu »

Moin, klingt logisch.
Danke für den Tipp!
Ich schau mal ob ich das Konzept bei mir Umsetzen lässt, glaube bei mir sind die GA's nicht so klar sturkturiert...

uweu
Beiträge: 17
Registriert: 7. Dez 2020 15:29
Answers: 0

Re: Umstieg von OH1

Beitrag von uweu »

Sorry, jetzt muss ich noch mal blöde Fragen:
Ich leg dann nur meine Aktoren als Thing an oder auch die Taster usw.?
Wenn ich beides anlege, wo kommen dann die GAs rein die es bei beiden gibt???
und kann ich auch mehrere .things Dateien anlegen?

Hab jetzt mal zum Testen meine Binäreingänge so angelegt und meine Bridge im UI gelöscht, er zeigt mir die Bridge aus der Thingsdatei aber nicht an. "BinEingang Garage" und "BinEingang Keller" zeigt er, aber mit ERROR:BRIDGE.
Die alten KNX Things zeigt er mit ERROR: HANDLER an.

Code: Alles auswählen

Bridge knx:ip:bridge "MDT KNX/IP" [ 
    ipAddress="192.168.1.66", 
    localIp="192.168.1.80", 
    localSourceAddr="0.0.0",
    type="TUNNEL", 
    portNumber=3671, 
    readingPause=50, 
    responseTimeout=10, 
    readRetriesLimit=3, 
    autoReconnectPeriod=60,
    useNAT=false
]  {
      Thing device binGar "BinEingang Garage" @ "KNX" [ 
         address="3.1.4",
         fetch=false,
         pingInterval=600,
         readInterval=0
      ]  {
            Type contact                 : ch1  "Garage auf"            [ ga="0/6/0" ]
            Type contact                 : ch2  "frei"                  [ ga="0/6/1" ]
            Type contact                 : ch3  "frei"                  [ ga="0/6/2" ]
            Type contact                 : ch4  "frei"                  [ ga="0/6/3" ]
         }
      Thing device binKG "BinEingang Keller" @ "KNX" [ 
         address="1.3.100",
         fetch=false,
         pingInterval=600,
         readInterval=0
      ]  {
            Type contact                 : ch1  "frei"                  [ ga="0/4/0" ]
            Type contact                 : ch2  "KlingelEG"             [ ga="0/4/1" ]
            Type contact                 : ch3  "KlingelKG"             [ ga="0/4/2" ]
            Type contact                 : ch4  "frei"                  [ ga="0/4/3" ]
            Type contact                 : ch5  "frei"                  [ ga="0/4/4" ]
            Type contact                 : ch6  "frei"                  [ ga="0/4/5" ]
            Type contact                 : ch7  "frei"                  [ ga="0/4/6" ]
            Type contact                 : ch8  "frei"                  [ ga="0/4/7" ]
            Type contact                 : ch9  "frei"                  [ ga="0/4/8" ]
            Type contact                 : ch10 "FensterKG Bad"         [ ga="0/4/9" ]
            Type contact                 : ch11 "FensterKG Kü_R"        [ ga="0/4/10" ]
            Type contact                 : ch12 "FensterKG Kü_L"        [ ga="0/4/11" ]
            Type contact                 : ch13 "FensterKG WZ_R"        [ ga="0/4/12" ]
            Type contact                 : ch14 "FensterKG WZ_L"        [ ga="0/4/13" ]
            Type contact                 : ch15 "FensterEG HWR"         [ ga="0/4/14" ]
            Type contact                 : ch16 "FensterEG WC"          [ ga="0/4/15" ]
            Type contact                 : ch17 "FensterEG Kü_R"        [ ga="0/4/16" ]
            Type contact                 : ch18 "FensterEG Kü_L"        [ ga="0/4/17" ]
            Type contact                 : ch19 "FensterEG EZ_R"        [ ga="0/4/18" ]
            Type contact                 : ch20 "FensterEG EZ_L"        [ ga="0/4/19" ]
            Type contact                 : ch21 "Türe Terasse"          [ ga="0/4/20" ]
            Type contact                 : ch22 "FensterEG WZ_R"        [ ga="0/4/21" ]
            Type contact                 : ch23 "FensterEG WZ_M"        [ ga="0/4/22" ]
            Type contact                 : ch24 "FensterEG WZ_L"        [ ga="0/4/23" ]
            Type contact                 : ch25 "FensterKG WS R"        [ ga="0/4/24" ]
            Type contact                 : ch26 "FensterKG WS L"        [ ga="0/4/25" ]
            Type contact                 : ch27 "FensterKG Ans"         [ ga="0/4/26" ]
            Type contact                 : ch28 "HaustüreEG"            [ ga="0/4/27" ]
            Type contact                 : ch29 "HaustüreKG"            [ ga="0/4/28" ]
            Type contact                 : ch30 "Wasser Keller"         [ ga="0/4/29" ]
            Type contact                 : ch31 "frei"                  [ ga="0/4/30" ]
            Type contact                 : ch32 "frei"                  [ ga="0/4/31" ]
         }
   }
Fragen über Fragagn, hab das Konzept noch nicht ganz kapiert... :?

Benutzeravatar
udo1toni
Beiträge: 15248
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Umstieg von OH1

Beitrag von udo1toni »

Du legst als Priorität erst mal Aktoren an. Ein Schalter, der ausschließlich knx Aktoren steuert, muss im openHAB System nicht abgebildet werden; er ist nur eine weitere Steuermöglichkeit.
Sensoren musst Du natürlich ebenfalls anlegen, dazu gehören natürlich auch Temperaturfühler in den RTR.
Der RTR als solcher kann auch als Aktor betrachtet werden, er lässt sich aktiv steuern, also muss er auch in openHAB erreicht werden können. Die Tasten im selben Gerät aber wieder nicht :)

Um die Verwirrung zu komplettieren, kann es aber sein, dass Du mit einer Taste eines knx Tasters ein ganz anderes Gerät steuern möchtest, welches gar nicht an knx angeschlossen ist, sondern nur an openHAB. Solche Tasten musst Du natürlich trotzdem in openHAB anlegen, das sind dann die schon eingangs erwähnten *-control Channel.

Du kannst Dich auch an den GA orientieren: Jede GA, die in einem Aktor parametriert ist, gehört zu dem Aktor - Ausnahme: Die GA ist in vielen Aktoren parametriert (Zentral-Aus als Beispiel). Solche "unbestimmten" GA lege ich im virtuellen Device an, wenn ich sie den in openHAB brauche, z.B. die Szenen gehören per Definition keinem Gerät; sie haben auch keinen "echten" Status, sind also von openHAB aus nicht abfragbar, weil es eben kein Gerät gibt, welches dafür zuständig ist (nicht mal, wenn man einen Szenencontroller hat).

GA sollten grundsätzlich nur einmal in der Konfiguration auftauchen, das gilt insbesondere für solche GA, über die Status in openHAB ankommen, also die Empfangsseite. Eine Ausnahme gibt es auch hier, nämlich bei Jalousien. openHAB kennt keine Jalousien, stattdessen legt man einen Rollershutter an. Du weißt sicher, dass der Langzeit Befehl ausschließlich UP/DOWN beherrscht, ebenso wie der Kurzzeit Befehl. Um die Fahrt zu stoppen, muss man also den Kurzzeit Befehl senden. Also muss die selbe GA sowohl im Rollershutter Channel für Auf/Abfahrt wie auch im Channel für den Lamellenwinkel parametriert werden. ABER: Die GA wird ausschließlich zum Senden verwendet, das stellt kein Problem dar. Schwierigkeiten sind nur zu erwarten, wenn die selbe GA in mehreren Channels zum Empfang verwendet wird, das knx Addon durchsucht beim Empfang einer GA die Liste der Channel nach der GA und schreibt dort den empfangenen Wert hinein, wo sie zuerst fündig wird. alle weiteren Vorkommen werden ignoriert.

Aber wie gesagt braucht es die doppelten GA sonst auch nicht.

Warum Deine Bridge nicht online kommt, ist erst mal nicht so einfach zu sagen. Hast Du die per UI erstellte Bridge auch "bridge" genannt (also UID knx:ip:bridge)? Eventuell hilft ein einfacher Neustart von openHAB.

Stimmen Deine physikalischen Adressen? (1.3 vs. 3.1)
Sobald die Bridge online ist, werden verknüpfte Things sich dort auch mit dem Bus verbinden. Du kannst auch die UI Things mit der per *.things Datei angelegten Bridge verbinden, Du musst nur die Zuordnung pro Thing über die UI vornehmen (da gibt es ein Auswahlfeld).

EDIT: Ach so... *-things Dateien kannst Du beliebig viele anlegen. Du kannst auch Things unabhängig von der zugehörigen Bridge anlegen, dann musst Du aber bei jedem Thing extra dazu schreiben, zu welcher Bridge es gehört. Die Baumstruktur empfinde ich da als angenehmer.
Ich habe pro Bus eine *.things Datei, also z.B. eine knx.things, eine mqtt.things usw. Ein paar Things habe ich auch in einer datei zusammengefasst, weil mir zwei Zeilen pro Datei als etwas affig erschienen, aber vielleicht ändere ich das auch noch mal ab und trenne wirklich stur nach Addon (Binding).

Das @ "KNX" kannst Du übrigens weg machen... Das stammt noch aus der openHAB2-Zeit, wo es eine Thing-Ansicht in der UI gab (Paper UI Control). In openHAB3 ist der Parameter ohne Funktion. Ich hab das oben aus dem Posting auch entfernt, damit es nicht zu weiterer Verwirrung kommt...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

uweu
Beiträge: 17
Registriert: 7. Dez 2020 15:29
Answers: 0

Re: Umstieg von OH1

Beitrag von uweu »

ok hab ich soweit verstanden.

Die bridge hat den gleichen Namen wie Die im ui hatte,
reboot tut immer gut :) jetzt läuft es.

Ja die Adressen passen, 1 = Wohnhaus, 2 = ELW, 3 = Garage

Antworten