Nicht die erste Simu dieser Art, aber eine mit etwas realistischerer Zufallssteuerung.
- Global ein/aus
- Bestimmbare Übergangswahrscheinlichkeiten für ein-/auschalten, damit z.B.
- Optional Bedingung pro Lampe, z.B. kein Einschalten wenn Rollade unten
- Definierte Schaltung wenn Simu gestartet und gestoppt wird.
Unten ein Diagramm, wo einige Konstanten für die Wahrscheinlichkeit eingetragen sind. Man orientiert sich sinnvollerweise an der 50% Marke.
- Global ein/aus
- Bestimmbare Übergangswahrscheinlichkeiten für ein-/auschalten, damit z.B.
- selten an, schnell wieder aus (Badezimmer)
- schnell an, selten und nur kurz aus (Wohnraum)
- oft an, aber schnell wieder aus (Treppenhaus)
- Zufälliger Zyklus, kein Schalten in festem Raster- schnell an, selten und nur kurz aus (Wohnraum)
- oft an, aber schnell wieder aus (Treppenhaus)
- Optional Bedingung pro Lampe, z.B. kein Einschalten wenn Rollade unten
- Definierte Schaltung wenn Simu gestartet und gestoppt wird.
Code:
# Anwesenheitssimulation # License: GPL (v2) #################### ###Einstellungen:### #################### my $AbwesenheitGA = '0/0/15'; # GA Simu global ein/aus my $AbwesenheitValue = 1; # Simu ein, wenn erfuellt my $AbwesenheitDPT = 1; # name eindeutiger Bezeichner # ga GA Lampe # DPT DPT Lampe (1: normal, '5.004' Szene) # Wert1, Wert0 Werte für ein und aus # prob1, prob0 Uebergangswahrscheinlichkeiten fuer ein/aus probx = p*1000 fuer p=0..1 # defstart, defstop Zu schaltender Zustand bei Anwesenheitsimu ein/aus # ga_lock* individuelle Bedingung fuer Schaltung (optional) my @Schaltzeiten; push @Schaltzeiten, { name => "Klo", ga => '9/0/20', DPT => 1, Wert1 => 1, prob1 => 25, Wert0 => 0, prob0 => 500, defstart => 0, defstop => 0 }; push @Schaltzeiten, { name => "Treppe", ga => '9/0/21', DPT => 1, Wert1 => 1, prob1 => 50, Wert0 => 0, prob0 => 50, defstart => 0, defstop => 0 }; push @Schaltzeiten, { name => "Kueche", ga => '9/1/22', DPT => '5.004', Wert1 => 3, prob1 => 100, Wert0 => 2, prob0 => 20, defstart => 0, defstop => 0, ga_lock => '1/1/21', ga_lock_dpt => 3, ga_lock_val => 1 }; # Resultierende Wkt p0, daß bei Einzel-Wkt p nach n Zyklen Schaltung erfolgt ist: p0=1-(1-p)^n # Durchschnittliche Zyklen n, bis p0=50%: n=log(1/2) / log(p) # Zyklen normiert auf 60 / ($cyclemin+$cyclemax) * 2, damit Zyklen=Minuten # z.B. prob=200 -> 4 min, prob=100 -> 7 min, prob=50 -> 14 min, prob=25 -> 28 min my $cyclemin = 40; # Zyklus minimal (s) my $cyclemax = 80; # Zyklus maximal (s) my $cycleinactive = 120; # Zykus wenn Anwesenheitssimulation aus ###################### ##ENDE Einstellungen## ###################### use POSIX; my $active=(knx_read($AbwesenheitGA,0,$AbwesenheitDPT) == $AbwesenheitValue); if (!$active) { $plugin_info{$plugname.'_cycle'} = $cycleinactive; } else { my $cycle=int(rand($cyclemax-$cyclemin)+$cyclemin); # Zufaelliger Zyklus im Bereich cyclemin..cyclemax $plugin_info{$plugname.'_cycle'} = $cycle; } my @activeList=split ';', $plugin_info{$plugname.'_activeItem'}; # read active #plugin_log($plugname, "Test: " . $active . "-" . $plugin_info{$plugname.'_active'} ); if ($active && ($active != $plugin_info{$plugname.'_active'})) { # start Simulation plugin_log($plugname,"Init"); foreach my $element (@Schaltzeiten) { # Anfangszustand knx_write($element->{ga},$element->{defstart},$element->{DPT}); } } elsif ((!$active) && ($active != $plugin_info{$plugname.'_active'})) { # stop Simulation my $num = @activeList; #anzahl elemente plugin_log($plugname,"Restore"); $plugin_info{$plugname.'_active'}=0; foreach my $s (@activeList) { foreach my $element (@Schaltzeiten) { # Endzustand if ($element->{name} eq $s) { knx_write($element->{ga},$element->{defstop},$element->{DPT}); } } } $plugin_info{$plugname.'_activeItem'}=""; # keine mehr aktiv } $plugin_info{$plugname.'_active'}=$active; # aktuellen Zustand merken if (!$active) { return 0; # nichts zu tun } foreach my $element (@Schaltzeiten) { my $zahl=int(rand(1000 * 60 / ($cyclemin+$cyclemax) * 2)+1); my $idx=-1; my $i=0; my $skip=0; #plugin_log($plugname,"Name: " . $element->{name} . $zahl ); if (exists $element->{ga_lock} && ($element->{ga_lock} ne '')) { # lock Bedindung? if (knx_read($element->{ga_lock},0,$element->{ga_lock_dpt}) == $element->{ga_lock_val}) { $skip = 1; # Bedingung nicht erfuellt } } foreach my $s (@activeList) { # Ist Licht bereits aktiv? if ($element->{name} eq $s) { # Suche in Liste $idx=$i; } $i=$i+1; } #plugin_log($plugname," " . join(';', @activeList) . " " . $i . " " . $idx); if ($idx == -1) { # nicht aktiv, einschalten? if (($zahl < $element->{prob1}) && ($skip == 0)) { knx_write($element->{ga},$element->{Wert1},$element->{DPT}); plugin_log($plugname,"Name: " . $element->{name} . " Ein: " . $element->{Wert1} ); push(@activeList,$element->{name}); # merken in Liste } } else { # aktiv, ausschalten? if (($zahl < $element->{prob0}) || ($skip == 1)) { # Licht an, aber Bedindung nicht mehr erfuellt knx_write($element->{ga},$element->{Wert0},$element->{DPT}); plugin_log($plugname,"Name: " . $element->{name} . " Aus: " . $element->{Wert0} ); splice(@activeList,$idx,1); # rausnehmen aus Liste } } } #plugin_log($plugname,"Name: " . "Hinterher " . join(';', @activeList)); $plugin_info{$plugname.'_activeItem'} = join(';', @activeList); # Liste aktive Lampen return 0;