Seite 2 von 6

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 19. Jan 2019 13:01
von maxx92
Hallo Seppy

Danke für Deine Antwort. Ich werde mich bei Gelegenheit drum kümmern.

Gruss. Marc

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 18. Mär 2019 02:20
von trigan
Gute Morgen liebe Community!

Das Skript oben von Cyrelian geposted läuft zunächst mal eigentlich ganz gut bei mir.
Was mich jetzt ein wenig wundert ist: Ih habe noch Openhab2.2 laufen. Ich lese gerade daß Members erst ab 2.3 eingeführt wurde? Na wie auch immer es läuft trotzdem.

Was mir bei einigen Testläufen auffiel ist: Es werden fast jedesmal alle Lichter angeschalten (Es brennen dann zB. 5 verschiedene Lichter bevor das erste wieder ausgeht) . Kann sein daß ich hier wirklich mehrmal den Jackpot geschossen habe beim Testen. Ich würde aber trotzdem gerne etwas "nachhelfen" und sobald ein Licht an ist, die Wahrscheinlichkeiten etwas verschieben so daß es wahrscheinlicher ist das erste Licht wieder auszuschalten bevor ein weiteres dazugeschalten wird. Ich möchte also nicht ständig alle Lichter gleichzeitig an haben sondern mal hier eins und dann mal dort eins, mal zwei vielleicht.

Ich dachte daran einen Wert zu erhöhen wenn bereits ein licht an ist und den dann zum random wert zu addieren um die Wahrscheinlichkeiten zu Gunsten des Ausschaltens zu erhöhen je mehr Lichter brennen.

if ((new java.util.Random).nextInt(2+Wert) == 1)

um die Wahrscheinlichkeit von 50/50 auf z.B 4:1 zu erhöhen. Dann halt eine Verzweigung if ... in 75% der fälle wird wieder was ausgeschaltet
in 25% der fälle wird ein weiteres Licht angeschaltet

Geht das auch einfacher?

Wie kann ich eigentlich den "members" wert abfragen. Ich bin beim Googlen auf ein paar Beispiele gestossen, die das so in der Art

MyGroup.members.filter[ i | <condition> ]: Return a Set of all the members that meet the provided <condition>

Ich weiß aber nicht so recht wie man damit umgeht.

Hier meine Items zum Testen:

Code: Alles auswählen

Group:Switch:OR(ON, OFF) 	Hauslichter2 		"Alle Hauslichter [(%d)]"
Switch Licht1  (Hauslichter2)
Switch Licht2  (Hauslichter2)
Switch Licht3  (Hauslichter2)
Switch Licht4  (Hauslichter2)
Switch Licht5  (Hauslichter2)
Switch Test_Switch
und hier meine rule:

Code: Alles auswählen

var int Zufallsfaktor = 0  // Wert 0 -5

//===================================
rule "Urlaubsmodus / Licht zufällig einschalten" 
//===================================

when
	Time cron "*/30 * * * * ?"  // alle 30 sek zum Testen
then
	if (Test_Switch.state == ON){
		var zuf1 = (new java.util.Random).nextInt(2+Zufallsfaktor)
		if (zuf1 == 1) {   // Only turn a light on/off ocasionally		
		// Create a timer with a random value
		var int randomTime = (new java.util.Random).nextInt(16) 			// default 16 sek zum Testen
		logInfo("RULE","Setting random lights timer to " + randomTime + " seconds.")    //Die Dauer ist also immer min. 30sek und variiert zwischen 30 sek und 46 sek
		  var tRandomLights = createTimer(now.plusSeconds(randomTime)) [|
		    var randLightIndex = (new java.util.Random).nextInt(Hauslichter2.members.size)
		    var randLightStateCurrent = Hauslichter2.members.get(randLightIndex).state
		    var randLightStateNew = if (randLightStateCurrent == ON) OFF else ON
		    logInfo("RULE","Presence Simulation:Switching light (On Schleife)" + Hauslichter2.members.get(randLightIndex).name + " from " + randLightStateCurrent + " to " + randLightStateNew)
		    sendCommand(Hauslichter2.members.get(randLightIndex), randLightStateNew)
		    postUpdate(Hauslichter2.members.get(randLightIndex), randLightStateNew)
			Zufallsfaktor = 0
			if (Licht1.state == ON)
			{ Zufallsfaktor = 1 }
			if (Licht2.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			if (Licht3.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			if (Licht4.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			if (Licht5.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			logInfo("RULE","On Schleife - Zufallsfaktor = " + Zufallsfaktor)
		        ]
			}
		 else if (zuf1 != 1) {   // Only turn a light on/off ocasionally  random 0-1, 50-50 chance
			// Create a timer with a random value
		    var int randomTime = (new java.util.Random).nextInt(16) 			// 360 Sek = 6 Minuten //alle 6 Minuten
		    logInfo("RULE","Setting random lights timer to " + randomTime + " seconds.")    //Die Dauer ist also immer min. 20Min und variiert zwischen 20Min. und 26Min.
		    var tRandomLights = createTimer(now.plusSeconds(randomTime)) [|
		    var randLightIndex = (new java.util.Random).nextInt(Hauslichter2.members.size)
		    var randLightStateCurrent = Hauslichter2.members.get(randLightIndex).state
		    var randLightStateNew = OFF
                      if (randLightStateCurrent == ON ) {
		    	logInfo("RULE","Presence Simulation:Switching light (Off Schleife V1)" + Hauslichter2.members.get(randLightIndex).name + " from " + randLightStateCurrent + " to " + randLightStateNew)
		    	sendCommand(Hauslichter2.members.get(randLightIndex), randLightStateNew)
			postUpdate(Hauslichter2.members.get(randLightIndex), randLightStateNew)}
		      else {
				var randLightIndex = (new java.util.Random).nextInt(Hauslichter2.members.size)
		    		var randLightStateCurrent = Hauslichter2.members.get(randLightIndex).state
			     	   if (randLightStateCurrent == ON ) {
		    			logInfo("RULE","Presence Simulation:Switching light (Off Schleife V2)" + Hauslichter2.members.get(randLightIndex).name + " from " + randLightStateCurrent + " to " + randLightStateNew)
		    			sendCommand(Hauslichter2.members.get(randLightIndex), randLightStateNew)
					postUpdate(Hauslichter2.members.get(randLightIndex), randLightStateNew)}
				else {
					var randLightIndex = (new java.util.Random).nextInt(Hauslichter2.members.size)
		    			var randLightStateCurrent = Hauslichter2.members.get(randLightIndex).state
						logInfo("RULE","Presence Simulation:Switching light (Off Schleife V3)" + Hauslichter2.members.get(randLightIndex).name + " from " + randLightStateCurrent + " to " + randLightStateNew)
		    				sendCommand(Hauslichter2.members.get(randLightIndex), randLightStateNew)
						postUpdate(Hauslichter2.members.get(randLightIndex), randLightStateNew)}
			}
			Zufallsfaktor = 0
			if (Licht1.state == ON)
			{ Zufallsfaktor = 1 }
			if (Licht2.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			if (Licht3.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			if (Licht4.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
			if (Licht5.state == ON)
			{ Zufallsfaktor = (Zufallsfaktor + 1) }
		        ]
			
			}
logInfo("RULE","Off Schleife - Zufallsfaktor = " + Zufallsfaktor)
logInfo("RULE","Random zahl " + (zuf1))	
}	
end
Ich muß zugeben ich bin nicht sonderlich stolz auf den code. Es funktioniert. ABER es ist sehr umständlich und außerdem passiert manchmal mehrere umläufe einfach gar Nichts. Im zweiten Teil habe ich mehrere if -Schleifen verschachtelt. Die rule hat also 3 versuche ,eins der lichter auszuschalten.
problem war mit dem ursprünglichen code nämlich, es wurde sehr oft ein licht ausgeschalten, das bereits aus war.
Aber auch mitd den drei Versuchen ist es nicht sicher, eins von den angeschalteten Lichtern zu treffen. Sehr dilletantisch ich gebs zu.

Wie kann man es besser machen?

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 18. Mär 2019 11:24
von udo1toni
Zuerst zu den members. Da hast Du etwas falsch zugeordnet. Das Konstrukt GroupItem.members gibt es von Anbeginn, es ist die Methode, eine Liste aller Gruppenmember zu erhalten. Seit OH2.3 kann man eine Rule statt auf Item GroupItem <trigger> auch mit Member of GroupItem <trigger> triggern lassen, also z.B.

Code: Alles auswählen

rule "meine Rule"
when
    Member of gMyGroup received update
then
...
end
Der Unterschied zum alten Code

Code: Alles auswählen

rule "meine Rule"
when
    Item gMyGroup received update
then
...
end
besteht darin, dass der Code oben exakt einmal ausgeführt wird, wenn ein Item ein Update empfängt, welches zur Gruppe gMyGroup gehört. Der untere Code führt den Code für jeden Member aus, sobald ein Item ein Update empfängt. Wenn ich also eine Gruppe mit 10 Membern habe, wird die Rule zehnmal getriggert.

Nun zu Deiner Rule. Deine Herangehensweise ist unglücklich. Besser ist es, schon beim Einschalten des Lichts einen (per Zufall variablen) Zeitpunkt zu definieren, wann das Licht wieder ausgeschaltet wird.
Du suchst also per Zufall ein ausgeschaltetes Licht, bestimmst den zufälligen Ausschaltzeitpunkt (innerhalb der Grenzen minimale Einschaltdauer und maximale Einschaltdauer), bestimmst evtl. den zufälligen Einschaltzeitpunkt und setzt einen Timer zum einschalten und einen Timer zum Ausschalten. Damit hast Du das Ausschalten aus dem Kreuz, denn das passiert ganz von selbst. Deine Rule muss sich nur um den Zufall kümmern.


Du kannst eine Gruppe z.B. mit

Code: Alles auswählen

Hauslichter2.members.filter[m|m.state == ON]  // alle eingeschalteten Lichter
Hauslichter2.members.filter[m|m.state == OFF] // alle ausgeschalteten Lichter 
filtern, um nur solche Items einzuschalten, die ausgeschaltet sind (und umgekehrt)
Random.nextInt(Wert) liefert ein pseudozufälliges Integer in den Grenzen von 0 bis Wert. Wie die Verteilung der Zufallswerte aussieht, weiß ich nicht, zumindest ist der Wert nur pseudozufällig.

Allgemein halte ich das zufällige Schalten für ungeeignet, vor allem wenn man die Möglichkeiten bedenkt, die openHAB bietet. Sinnvoller erscheint mir da, die Schaltzeiten ausgewählter Leuchten mitzuschreiben (Persistence) und dann im Ferienfall auf alte Schaltzeiten zurückzugreifen. Damit ist dann sichergestellt, dass Lichter nicht untypisch lang oder kurz geschaltet werden. In openHAB1 gab es dazu sogar extra die gcal Persistence, die direkt Schaltbefehle in den Google Calendar eingetragen hat. Man musste dann nur dem System sagen, dass es die Schaltereignisse von vor 3 Wochen abspielen soll.
Google Calendar hat dann eine andere Art der Authentifizierung eingeführt, womit das Binding lange Zeit nicht zurecht kam. Soweit ich weiß, funktioniert das ganze aber inzwischen wieder. Schau mal unter https://www.openhab.org/addons/integrat ... simulation

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 19. Mär 2019 11:40
von trigan
Hallo,

vielen Dank für die erhellenden Worte im Bezug auf "members"
Ich glaube ich werde dann auch auf die Methode mit persistence wechseln.
Mir ging es aber auch darum, etwas mit der Programmierung rumzuspielen. Wieder was dazugelernt.
Deinen Ansatz werde ich deshalb auch mal versuchen umzusetzen, also den Filter zum Einsatz bringen.


Vielen Dank und Grüße

Trigan :)

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 7. Apr 2019 19:38
von D3ltorohd
Hallo Com,

ich bin durch google auf dieses Thema gestoßen. Vllt könnt ihr mir hier weiterhelfen. Vorneweg, ich bin Anfänger was das ganze mit OpenHab angeht.

Ich wollte fragen ob das mit den Random Zeiten auch für Rollos umgesetzt werden kann. Ich habe Funkrollos, die habe ich nun alle in OH eingegeben, Gruppen erstellt und über die BasiUI lassen sie sich steuern, soweit so gut.

Nun bin ich einen Schritt weiter und lasse die Rollos per Astro Binding runterfahren, mit einem Offset Wert nach dem Sonnenuntergang, auch das klappt. Nun würde ich aber gerne zu diesem Sonnenuntergang Event eine Art Random Timer nutzen, sprich das nicht alle Rollos gleichzeitig fahren, sondern zumindest mal jedes Zimmer etwas anders fährt, getrennt von einander in einem Abstand von 1-3 min oder so.

Das ganze vllt nicht immer Steif nach 15 min Offset nach dem Sonnenuntergang Event, sondern mal mehr mal weniger und auch die Räume vllt unterschiedlich, mal zuerst SZ, am nächsten Tag EZ usw, danach folgen dann Abend Zeitversetzt andere Zimmer.

Da ich danach gesucht hatte, bin ich auf dieses Rule hier gestoßen, wenn man Ahnung davon hat, kann man das doch bestimmt auf mein Scenario anwenden ?

Momentan läuft es wie gesagt per Astro mit Offset und nach dem Offset wird der erste Raum direkt getriggert, danach werden Timer erstellt, bis eben alle Räume durch sind. Das wäre dann aber jeden Tag die gleiche Zeit und gleiche Reihenfolge.

Könntet ihr mir da vllt weiterhelfen und mich dabei Unterstützen das so zu lösen ?

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 7. Apr 2019 23:26
von udo1toni
Ja sicher, das ist kein großes Problem. Letztlich ist es egal, ob man nun Lichter flackern lässt oder Läden variabel schließt. die einzige Frage ist dann, wie man es am geschicktesten anstellt. Grundsätzlich würde ich die Rule durch das Astro Binding triggern lassen. Innerhalb der Rule müsste man dann per Zufall die Timerzeiten setzen. Das bedeutet allerdings, dass es für jede Rollladengruppe einen eigenen Timer braucht.
Die Alternative wäre, im Timer eine kleine Statemachine zu bauen. Die Statemachine sucht sich aus der Liste der Rollläden einen heraus, der noch nicht geschlossen ist (per Zufall), fährt diesen herunter und plant sich selbst nach einer zufälligen Zeitspanne neu ein. Z.B. so:

Code: Alles auswählen

var Timer tLaeden = null
val java.util.concurrent.ThreadLocalRandom random = (new java.util.concurrent.ThreadLocalRandom)

rule "Läden schließen"
when
    Channel 'astro:sun:home:sunset#event' triggered START                 // oder so ähnlich...
then
    tLaeden?.cancel                                                       // falls ein Timer existiert, weg damit
    val int randomTime = random.nextInt(60) + 20
    tLaeden = createTimer(now.plusSeconds(randomTime),[ |
        val iGroup = gLaeden.members.filter[r|(r.state as Number) < 100]
        if(iGroup.size > 0) {                                             // solange noch Läden übrig sind
            val int randomTime = random.nextInt(60) + 20                  // mindestens 20 Sekunden Abstand, höchstens 80 Sekunden
            val int randomLaden = random.nextInt(iGroup.size -1) +1 
            iGroup.get(randomLaden).sendCommand(DOWN)                     // wahlweise auch 100 für direkte Positionsfahrt
            iGroup.get(randomLaden).postUpdate(100)                       // siehe Text
            tLaeden.reschedule(now.plusSeconds(randomTime))               // der nächste Laden
        }
    ])
end
Falls ein Laden länger als 20 Sekunden braucht, um zu schließen, und das System ist so eingerichtet, dass es auf Rückmeldung des Aktors wartet, könnte der Fall eintreten, dass der selbe Laden zweimal hintereinander angesteuert wird (also solange er noch fährt: nächster Timer nach 20 Sekunden, die Gruppe hat sich nicht geändert, gleicher Laden selektiert). Um das zu verhindern, steht das postUpdate mit drin, welches in diesem Fall den neuen Status erzwingt.
Soweit ich mich erinnere, ist der Parameter für get() ein Integer größer 0, dementsprechend muss die Zufallszahl also 1 bis Anzahl geöffneter Läden sein.
Falls ein Laden hartnäckig offen bleiben sollte, habe ich mich geirrt und Du kannst das -1 +1 aus der Definition randomLaden entfernen.

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 8. Apr 2019 12:28
von D3ltorohd
Wow vielen Dank. Schaue ich mir heut Abend mal an. Ob ich das hinbekomme. Was ist hier nun für ein Zeitversatz drin zwischen den einzelnen Räumen? 60 sek. + 20 ? Also immer ne gute Minute ? Oder wie läuft das ab ? Beim Event Sonnenuntergang wird random einer ausgesucht und fährt dann runter danach ist der nächste dran ?

Rückmeldung geben die Rollos leider keine. Da müsste man dann mit der Zeit Spielen. Ich kann ja mal stoppen wie lang einer braucht hab dann noch bodentiefe Fenster die brauchen dann länger.

Könnte man am Ende noch was mit einbauen das er einfach nicht zwei Mal einen Befehl für alle Rollos gibt falls eben einer nicht gefahren ist.

Wie es im Basic ui aussieht setzt er halt gleich auf 100% ob der Rollo gefahren ist oder nicht spielt keine Rolle . Oder man lässt dieses random rule ein weiteres mal triggern nach 15 min oder so ?

Bevor das Rule läuft muss ich aber dieses Java lib installieren in Open hab oder auf dem Server ?

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 8. Apr 2019 14:01
von udo1toni
Der Zeitversatz setzt sich aus einer zufälligen Komponente (0 - 60) und einem Mindestwert (20) zusammen, das heißt, die Rolläden fahren im Abstand zwischen 20 und 80 Sekunden.
Wenn Du eh keine Rückmeldung hast, kannst Du das mit dem .postUpdate weg lassen, das erledigt openHAB bei Dir dann ja offensichtlich eh selbst. Da Du keine Positionsmeldung hast, werden Deine Läden auch keine Positionsfahrten erlauben, also bleibt nur der Befehl DOWN (wie schon im Script vorgesehen)
Einen zusätzlichen Befehl um alle Läden zuzufahren musst Du nicht einbauen, die Rule sollte zuverlässig arbeiten. Falls wider Erwarten Läden offen bleiben, liegt die Ursache im Zweifel in der Kommunikation mit den Aktoren. Da wäre dann die Frage, welche Aktoren Du verwendest.

Du musst nichts weiter installieren, man muss nur den Teil der Library in den Rules bekannt machen, um die Funktion bequem nutzen zu können. Das passiert in diesem Fall durch Zuweisung an eine Variable.

Die Rule berücksichtigt nicht, Rollläden eines Raumes gemeinsam (oder alle Läden eines Raumes hintereinander) zu fahren. Momentan fällt mir auch kein einfacher Weg ein, das zu realisieren.

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 8. Apr 2019 15:30
von D3ltorohd
Ich würde einfach noch mal nen Rule mit dem Astro Event setzten Offset 15 min oder so und diese Startet dann den Commander down für die Gruppe alle Rolläden so ist sollten dann die fahren die nicht schon unten sind.

Ich weiß nicht wie zuverlässig dieses Gateway und der Sketch dazu laufen oder wie gut die Rollos das umsetzten. Ich habe die original Timer vom Hersteller auch so eingestellt das 2-3 x hintereinander getriggert wird weil hier und da mal einer nicht beim ersten mal reagiert

Das ganze Gateway basiert auf einem ESP 8266 und nem CC1101. Vom Hersteller selber gab es da nicht. Rollos sind von Jarolift die TDEF.
Die Rule berücksichtigt nicht, Rollläden eines Raumes gemeinsam (oder alle Läden eines Raumes hintereinander) zu fahren.
Das verwirrt mich jetzt ein wenig. Ich hatte es so verstanden das genau diese Rule sich einen Raum also eine Gruppe aus der Gruppenliste aussucht und diese dann runterfährt ?

EDIT::
So ich hab das jetzt mal so in die Rules geschrieben, passt das so ? So sieht meine Items aus, mit den Gruppen ? Bleibt das so muss ich noch was ändern ?
Screenshot (926).png
Screenshot (927).png
Hm ich sehe gerade, ich habe auch eine Gruppe, alle Jalousien, das ist blöd, wenn er sich die schnappt, fahren alle gleichzeitig. Könnte man das irgendwie ausgrenzen ? Alle Gruppen bis auf Jalousien ?

Diese würde ich wiederum am Ende wenn er die Liste abgearbeitet hat, noch mal zum Schluss Triggern lassen, damit falls mal nicht alle runter sind die letzten fahren. Könnte man da am Ende des Rules noch was einbauen, oder ein neues Rule, was durch das andere Rule nach dem letzten Rollo getriggert wird ?

Re: Anwesenheitssimulation durch zufälliges Schalten der Lichter

Verfasst: 8. Apr 2019 18:39
von udo1toni
Die Rule greift sich einzelne Rollläden einer Gruppe, in der alle Läden drin sind (also Deine Jalousien). Man könnte das Ganze anders gestalten, so dass jeweils eine Gruppe gesteuert wird. Das ist aber wesentlich aufwändiger.

Die Fragen an dieser Stelle sind also erst mal: Sollen die Läden raumweise verfahren werden? Sollen die Läden innerhalb eines Raums versetzt oder gemeinsam verfahren werden?

Ich sehe da eine ordentliche Menge Fehler in der Rule.
  • Der erste Fehler ist mir erst mal nicht erklärbar, keine Ahnung, ob die Erzeugung von Zufallszahlen dann nicht funktioniert, oder ob das nur ein interner Fehler ist.
  • Der zweite Fehler ist das Group Item gLaeden, das müsste natürlich in Deine Fall durch das Group Item Jalousien ersetzt werden.
  • Der dritte Fehler wird vermutlich (hoffentlich) mit Beseitigung des zweiten Fehlers verschwinden.
  • Der vierte Fehler mault die doppelte Definition der Konstanten an, unterschlägt dabei aber, dass die zweite Definition in einem anderen Kontext geschieht, in dem die erste Definition ungültig sein müsste. Zur Sicherheit kannst Du die erste Definition auch ändern (oder durch eine fixe Verzögerung für den ersten Laden ersetzen, das ist eh nur der erste Laden, der ohnehin durch den Sonnenuntergang getriggert ist).