Zufallsgenerator Skript für Anwesenheitssimulation, Lampen..

Problemlösungen und Hinweise von allgemeinem Interesse zur Haussteuerung mit HomeMatic

Moderator: Co-Administratoren

Benutzeravatar
funkleuchtturm
Beiträge: 1322
Registriert: 13.06.2011, 16:42

Zufallsgenerator Skript für Anwesenheitssimulation, Lampen..

Beitrag von funkleuchtturm » 01.06.2014, 15:50

Auf meiner Homepage gibt´s hierzu evtl. weitere Informationen: http://www.stall.biz/?project=zufallsge ... ion-lampen

Für die Simulation der Anwesenheit werden gerne die Lampen oder die Rolladen oder was auch immer möglichst zufällig ein und ausgeschaltet. In den meisten Programmiersprachen gibt es für die Programmierung geeignete Algorithmen sog. Randomfunktionen, die beispielsweise gleichverteilte Zahlen zwischen 0.0 und 1.0 erzeugen. Obwohl so eine Funktion für die Hausautomation eine relativ sinnvolle Funktionalität bietet, ist keinerlei Randomfunktion in der HM-Skriptsprache abgebildet. Hiermit soll diesem Mangel mit einem HM-Skript abgeholfen werden.

Der gewählte Lösungsansatz ist sicher etwas ungewöhnlich, was dem doch sehr beschränkten Befehlssatz der Homemaic-Skriptsprache geschuldet ist:
In der Elektronik verwendet man gerne für die Rauscherzeugung sog. Pseudo-Rauschgeneratoren; Herzstück sind dafür mit XOR-Gattern rückgekoppelte Schieberegister. Wer mehr darüber wissen will: http://de.wikipedia.org/wiki/Linear_r%C ... beregister
Dieser eigentlich hardwarenahe Lösungsansatz wird im Folgenden für die softwaremässige Erzeugung von gleichverteilten Zahlen verwendet. Dahinter sind komplizierte Theorien, die aber hier nicht weiter erläutert werden. Deshalb für den reinen Anwender hier mein...

Kochrezept:
1. Zwei Systemvariable "random_zahl" und "random_tp" vom Variablentyp Zahl anlegen, Wertebereich -2.0 bis 2.0 !
Dabei ist "random_zahl" eine bei jedem Skriptaufruf neu berechnete Zufallszahl zwischen 0.0 und 1.0 Die Systemvariable "random_tp" ist eine gemitteltes oder "geglättetes" Abbild von "random_zahl" im gleichen Wertebereich.
2. Ein WebUI-Programm anlegen, in dem zyklisch beispielsweise alle 3 Minuten folgendes HM-Skript aufgerufen wird:

Code: Alles auswählen

!Version  2014.06.02 ;  Verfasser :Eugen Stall
!zwei Systemvariablen "random_zahl"  und "random_tp" als Zahl mit Wertebereich -2.0 bis 2.0 anlegen
!Skript speichert  Zufallszahl zwischen 0.0 und 1.0 ungefiltert auf "random_zahl und gemittelt auf "random_tp"
!##############################################  
real zahl = 65536.0 * dom.GetObject("random_zahl").State();
zahl = zahl.ToInteger();
if ((zahl <1) || (zahl > 65535)) {zahl= 3757;} !um saubere Startposition sicherzustellen
integer zahl_alt = zahl;
!##############################################
string dualzahl = "";
integer xor ;
integer x;
!hier wird ein 16bit-Schieberegister mit XOR-Rückkopplungen simuliert
if (zahl > 32767) {dualzahl = dualzahl + "1"; zahl = zahl - 32768; x = 1;} else    {dualzahl = dualzahl + "0";  x = 0;}
xor = x;   
if (zahl > 16383) {dualzahl = dualzahl + "1"; zahl = zahl - 16384;} else    {dualzahl = dualzahl + "0";}
if (zahl > 8191) {dualzahl = dualzahl + "1";  zahl = zahl - 8192; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 4095) {dualzahl = dualzahl + "1"; zahl = zahl - 4096; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 2047) {dualzahl = dualzahl + "1"; zahl = zahl - 2048 ;} else    {dualzahl = dualzahl + "0";}
if (zahl > 1023) {dualzahl = dualzahl + "1"; zahl = zahl - 1024 ; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
!niedrigstes neues bit einschieben
zahl = zahl_alt * 2;
if (zahl > 65535) {zahl = zahl - 65536;}
zahl = zahl + xor;
!auf 1 normieren und auf Systemvariable random_zahl  speichern  ############
zahl = 0.0000152590219* zahl;  !zahl / 65536
dom.GetObject("random_zahl").State(zahl);
!Mittelwertbildung : der Faktor 0.2 bestimmt die Mittelungsstärke. ###########
!Je kleiner, desto "ruhiger" das Rauschsignal  ########################
real tp_random = dom.GetObject("random_tp").State();
tp_random =  tp_random + (0.2 * (zahl - tp_random));
dom.GetObject("random_tp").State(tp_random);
tp_random = dom.GetObject("random_tp").State();
!####################################################
3. Jeweils ein WebUI-Programm für die zufällige Steuerung einer Lampe, Rollade oder was auch immer anlegen.

Hier ein Beispiel für die Zufallsteuerung einer Lampe abends zwischen 18 und 23H:
random1.jpg
Das Einschaltverhältnis (Lampe EIN zu Lampe AUS) kann man mit dem Schaltwert für "random_tp" beliebig nach den individuellen Wünschen festlegen. Ich habe in den o.a. Beispiel einen Wert von 0.5 gewählt, was bedeutet, dass die Lampe in dem gewählten Zeitraum für etwa 50% der Zeit leuchtet.
Die Zeitdauer von Eingeschaltet und Pause hängt u.a. vom gewählten Aktualisierungsintervall des Skriptes ab. Kleine Zeiten ( 1 bis 2 Minuten) bedeutet häufiges Schalten, große Intervalle das Gegenteil.
Zur Zeit versuche ich noch die für mich geeigneten Einstellparameter zu ermitteln. Ansonsten läuft das Skript sehr schnell durch, aber trotzdem sollte man im Hinblick auf CCU-Belastung nicht zu häufig die Randomfunktion abfragen.
Viel Spass beim "zufälligen" Steuern und Regeln :D

Changelog:
01.06.2014: fehlende Programmzeile im Skript ergänzt
02.06.2014: Programm verkürzt, Durchlaufzeit verbessert
Zuletzt geändert von funkleuchtturm am 19.07.2014, 11:15, insgesamt 5-mal geändert.
Viele Gruesse
Eugen
________________________________________________
Homematic-CCU2-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI und den WEATHERMAN
mit vielen Kochrezepten für den ambitionierten Homematiker

Benutzeravatar
Homoran
Beiträge: 8583
Registriert: 02.07.2013, 15:29
Wohnort: Köln

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von Homoran » 01.06.2014, 15:56

Das ist mal wieder ein typischer Eugen!
geht nicht gibt's für ihn nicht und was wirklich gebraucht wird, liefert er nach!

Klasse,
danach habe ich schon lange gesucht. Werde es direkt wieder ausprobieren.

Danke
Rainer

EDIT: Der Generator läuft schon, jetzt müssen die Programme dran glauben
Alle meine Hinweise sind auf eigene Gefahr umzusetzen. Immer einen Fachmann zu Rate ziehen!

tomcon
Beiträge: 28
Registriert: 11.04.2014, 12:58

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von tomcon » 01.06.2014, 16:55

...sehr cool!

Kurze Verständnisfrage:

1. wenn ich mehrere Lampen zu zufälligen und unterschiedlichen Zeiten an- und ausschalten möchte, brauche ich dann verschiedene Skripte (also für jede Lampe ein eigenes Skript)? Denn wenn ich für jede zu schaltende Lampe die gleiche Variable (random_tp) auslese, dann schalten doch alle Lampen gleich, oder?

2. wie kann ich die Astro-Funktion "nachts" so einbinden, daß die Lampen so gegen 24 Uhr alle ausschalten und nicht wieder an?


thx

Benutzeravatar
Homoran
Beiträge: 8583
Registriert: 02.07.2013, 15:29
Wohnort: Köln

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von Homoran » 01.06.2014, 17:02

Meine random_tp bleibt auf 0
im Skript steht auch tp_random ;-)

Gruß
Rainer
Alle meine Hinweise sind auf eigene Gefahr umzusetzen. Immer einen Fachmann zu Rate ziehen!

Benutzeravatar
funkleuchtturm
Beiträge: 1322
Registriert: 13.06.2011, 16:42

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von funkleuchtturm » 01.06.2014, 17:56

Homoran hat geschrieben:Meine random_tp bleibt auf 0
... versteh ich nicht. Hab gerade nochmal das Skript überprüft, ob beim copy&paste was schief gegangen ist. War aber nicht, das zurückgeladene Skript läuft bei mir einwandfrei !
Mach mal einen Favoriten auf und löse das Skript auf Tastendruck aus und überprüfe dann nochmal "random_zahl" und "random_tp" nach jedem Tastendruck.
tomcon hat geschrieben:1. wenn ich mehrere Lampen zu zufälligen und unterschiedlichen Zeiten an- und ausschalten möchte, brauche ich dann verschiedene Skripte (also für jede Lampe ein eigenes Skript)? Denn wenn ich für jede zu schaltende Lampe die gleiche Variable (random_tp) auslese, dann schalten doch alle Lampen gleich, oder?
Das ist richtig und das kannst Du auch machen! Aber ich würde aus Einfachheitsgründen die Schaltschwelle für die Lampen etwas unterschiedlich wählen. Das hat zwar den Nachteil, dass die mittleren Einschaltzeiten unterschiedlich sind, aber das kann zur Anwesenheitssimulation ja auch sinnvoll sein.
tomcon hat geschrieben:wie kann ich die Astro-Funktion "nachts" so einbinden, daß die Lampen so gegen 24 Uhr alle ausschalten und nicht wieder an?
Ich würde nicht das Tageszeitenskript verwenden, sondern den Sonnenstand: http://homematic-forum.de/forum/viewtop ... 31&t=17514
.. und dort den Azimutwinkel abfragen: So etwa..
wenn (sonne_azimut > 200) UND (random_tp >0.5) DANN Lampe EIN SONST AUS.
Viele Gruesse
Eugen
________________________________________________
Homematic-CCU2-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI und den WEATHERMAN
mit vielen Kochrezepten für den ambitionierten Homematiker

Benutzeravatar
Homoran
Beiträge: 8583
Registriert: 02.07.2013, 15:29
Wohnort: Köln

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von Homoran » 01.06.2014, 18:37

Hallo Eugen,
random_zahl ändert sich fleißig, random_tp bleibt auf 0!
Welche Wertebereiche müssen für die SysVar eingegeben werden?
Ich habe zuerst für beide 0-1, jetzt habe ich für random_tp: 0-64000 eingegeben - ohne Erfolg.

Der Timestamp ändert sich ebenfalls regelmäßig - ca. 10-20 Sekunden nach random_zahl

Gruß
Rainer
Alle meine Hinweise sind auf eigene Gefahr umzusetzen. Immer einen Fachmann zu Rate ziehen!

Benutzeravatar
funkleuchtturm
Beiträge: 1322
Registriert: 13.06.2011, 16:42

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von funkleuchtturm » 01.06.2014, 18:44

... beide Variablen auf Wertebereich 0 bis 70000 setzen.
Viele Gruesse
Eugen
________________________________________________
Homematic-CCU2-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI und den WEATHERMAN
mit vielen Kochrezepten für den ambitionierten Homematiker

tomcon
Beiträge: 28
Registriert: 11.04.2014, 12:58

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von tomcon » 01.06.2014, 19:16

...also so wie ich das verstehe, wird am Ende des Prags der Stage der Variablen tp_random an random_tp übergeben - vielleicht daher die Verwirrung.

Frage: wenn ich die Scripte abändere, um verschiedene Lampen zu schalten, dann habe ich per "suchen und ersetzen" die geien Variablen random_tp und random_zahl ersetzt - richtig? Siehe nachfolgendes Script:

!Version 2014.06.01 ; Verfasser :Eugen Stall
!zwei Systemvariablen "random_zahl_Büro" und "random_tp_Büro" als Zahl anlegen (für Simulation im Büro)
!Skript erzeugt Real-Zufallszahl zwischen 0 und 1 ungefiltert auf "random_zahl_Büro und gemittelt auf "random_tp_Büro"

real random = 65536.0 * dom.GetObject("random_zahl_Büro").Value();
integer zahl = random.ToInteger();
if ((zahl == 0) || (zahl > 65535)) {zahl= 33757;} !um saubere Startposition sicherzustellen
integer zahl_alt = zahl;
string dualzahl = "";
integer xor ;
integer x;
string messwert;
real m_wert =0.0;

!hier wird ein 16bit-Schieberegister mit XOR-Rückkopplungen simuliert
if (zahl > 32767) {dualzahl = dualzahl + "1"; zahl = zahl - 32768; x = 1;} else {dualzahl = dualzahl + "0"; x = 0;}
xor = x;
if (zahl > 16383) {dualzahl = dualzahl + "1"; zahl = zahl - 16384; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 8191) {dualzahl = dualzahl + "1"; zahl = zahl - 8192; x = 1;} else {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 4095) {dualzahl = dualzahl + "1"; zahl = zahl - 4096; x = 1;} else {dualzahl = dualzahl + "0"; x = 0;}
if (zahl > 2047) {dualzahl = dualzahl + "1"; zahl = zahl - 2048 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 1023) {dualzahl = dualzahl + "1"; zahl = zahl - 1024 ; x = 1;} else {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 511) {dualzahl = dualzahl + "1"; zahl = zahl - 512 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 255) {dualzahl = dualzahl + "1"; zahl = zahl - 256 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 127) {dualzahl = dualzahl + "1"; zahl = zahl - 128 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 63) {dualzahl = dualzahl + "1"; zahl = zahl - 64 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 31) {dualzahl = dualzahl + "1"; zahl = zahl - 32 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 15) {dualzahl = dualzahl + "1"; zahl = zahl - 16 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 7) {dualzahl = dualzahl + "1"; zahl = zahl - 8 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 3) {dualzahl = dualzahl + "1"; zahl = zahl - 4 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 1) {dualzahl = dualzahl + "1"; zahl = zahl - 2 ; x = 1;} else {dualzahl = dualzahl + "0";}
if (zahl > 0) {dualzahl = dualzahl + "1"; zahl = zahl - 1 ; x = 1;} else {dualzahl = dualzahl + "0";}
!if ((xor + 1) ==1) {xor = 1;} else {xor = 0;}
zahl = zahl_alt * 2;
if (zahl > 65535) {zahl = zahl - 65536;}
zahl = zahl + xor;

!Ergebnis ausgeben:
random = 0.0000153055 * zahl; !random auf Wertebereich 0.0 bis 1.0 normieren
dom.GetObject("random_zahl_Büro").State(random);

!Mittelwertbildung :
!der Faktor 0.4 bestimmt die Mittelungsstärke. Je kleiner, desto "ruhiger" das Rauschsignal
real tp_random = dom.GetObject("random_tp_Büro").Value();
tp_random = tp_random + (0.4 * (random - tp_random));
!WriteLine("tp_random :" +tp_random);
dom.GetObject("random_tp_Büro").State(tp_random);

Benutzeravatar
funkleuchtturm
Beiträge: 1322
Registriert: 13.06.2011, 16:42

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von funkleuchtturm » 01.06.2014, 19:24

tomcon hat geschrieben:Variablen random_tp und random_zahl ersetzt - richtig?
Ja. So müsste es gehen. Du hast dann mehrere Skripte mit jeweils einem individuellen Systemvariablen-Pärchen, die aber dann möglichst getrennt zu etwas unterschiedlichen Intervallen aufgerufen werden sollten.
... damit die "Rauschsignale" nicht parallel verlaufen!
Viele Gruesse
Eugen
________________________________________________
Homematic-CCU2-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI und den WEATHERMAN
mit vielen Kochrezepten für den ambitionierten Homematiker

Benutzeravatar
Homoran
Beiträge: 8583
Registriert: 02.07.2013, 15:29
Wohnort: Köln

Re: Zufallsgenerator Skript für Anwesenheitssimulation, Lamp

Beitrag von Homoran » 01.06.2014, 19:28

Hallo Eugen,
ich habe mal folgendes unter Skript testen geprüft:

Code: Alles auswählen

!Zufallszahl erzeugen
!Version  2014.06.01 ;  Verfasser :Eugen Stall
!zwei Systemvariablen "random_zahl"  und "random_tp" als Zahl anlegen
!Skript erzeugt Real-Zufallszahl zwischen 0 und 1 ungefiltert auf "random_zahl und gemittelt auf "random_tp"

real random = 65536.0 * dom.GetObject("random_zahl").Value(); 
integer zahl = random.ToInteger();
if ((zahl == 0) || (zahl > 65535)) {zahl= 33757;} !um saubere Startposition sicherzustellen
integer zahl_alt = zahl;
string dualzahl = "";
integer xor  ; 
integer x;
string messwert;
real m_wert =0.0;

!hier wird ein 16-bit-Schieberegister mit XOR-Rückkopplungen simuliert
if (zahl > 32767) {dualzahl = dualzahl + "1"; zahl = zahl - 32768; x = 1;} else    {dualzahl = dualzahl + "0";  x = 0;}
xor = x;   
if (zahl > 16383) {dualzahl = dualzahl + "1"; zahl = zahl - 16384; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 8191) {dualzahl = dualzahl + "1";  zahl = zahl - 8192; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;} 
if (zahl > 4095) {dualzahl = dualzahl + "1"; zahl = zahl - 4096; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if (zahl > 2047) {dualzahl = dualzahl + "1"; zahl = zahl - 2048 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 1023) {dualzahl = dualzahl + "1"; zahl = zahl - 1024 ; x = 1;} else    {dualzahl = dualzahl + "0"; x = 0;}
if ((xor + x) ==1) {xor = 1;} else {xor = 0;}
if (zahl > 511) {dualzahl = dualzahl + "1"; zahl = zahl - 512 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 255) {dualzahl = dualzahl + "1"; zahl = zahl - 256 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 127) {dualzahl = dualzahl + "1"; zahl = zahl - 128 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 63) {dualzahl = dualzahl + "1"; zahl = zahl - 64 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 31) {dualzahl = dualzahl + "1"; zahl = zahl - 32 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 15) {dualzahl = dualzahl + "1"; zahl = zahl - 16 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 7) {dualzahl = dualzahl + "1"; zahl = zahl - 8 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 3) {dualzahl = dualzahl + "1"; zahl = zahl - 4 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 1) {dualzahl = dualzahl + "1"; zahl = zahl - 2 ; x = 1;} else    {dualzahl = dualzahl + "0";}
if (zahl > 0) {dualzahl = dualzahl + "1"; zahl = zahl - 1 ; x = 1;} else    {dualzahl = dualzahl + "0";}
!if ((xor + 1) ==1) {xor = 1;} else {xor = 0;}
zahl = zahl_alt * 2;
if (zahl > 65535) {zahl = zahl - 65536;}
zahl = zahl + xor;

!Ergebnis ausgeben:
random = 0.0000153055 * zahl; !random auf Wertebereich 0.0 bis 1.0 normieren 
dom.GetObject("random_zahl").State(random);


var tust = random.ToString();
WriteLine(tust);


!Mittelwertbildung : 
!der Faktor 0.4 bestimmt die Mittelungsstärke. Je kleiner, desto "ruhiger" das Rauschsignal
real tp_random = dom.GetObject("random_tp").Value(); 
tp_random =  tp_random + (0.4 * (random - tp_random)); !
dom.GetObject("random_tp").State(tp_random);
var Toast = tp_random.ToString();

WriteLine(Toast);
für die Werte wird etwas herausgegeben.
Die Variable "random_tp" ändert sich nicht!

kann es daran liegen, dass ich in einem Programm mehrere Skripts laufen lasse, u.a. auch dein Sonnenstandsskript?

Gruß
Rainer
Alle meine Hinweise sind auf eigene Gefahr umzusetzen. Immer einen Fachmann zu Rate ziehen!

Antworten

Zurück zu „HomeMatic Tipps & Tricks - keine Fragen!“