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;

