|
From: <pf...@us...> - 2012-05-11 22:17:07
|
Revision: 811
http://openautomation.svn.sourceforge.net/openautomation/?rev=811&view=rev
Author: pfry
Date: 2012-05-11 22:17:00 +0000 (Fri, 11 May 2012)
Log Message:
-----------
Edits betr. Zeitansage und cool=>....-Klausel
Modified Paths:
--------------
wiregate/plugin/generic/Ansagen.pl
wiregate/plugin/generic/Logikprozessor.pl
wiregate/plugin/generic/conf.d/Logikprozessor.conf
Modified: wiregate/plugin/generic/Ansagen.pl
===================================================================
--- wiregate/plugin/generic/Ansagen.pl 2012-05-11 19:12:49 UTC (rev 810)
+++ wiregate/plugin/generic/Ansagen.pl 2012-05-11 22:17:00 UTC (rev 811)
@@ -7,6 +7,7 @@
# $plugin_info{$plugname.'_cycle'}=0; return 'deaktiviert';
use POSIX qw(floor);
+use feature "switch"; # aktiviert given...when-Struktur von Perl 5.10
# Defaultkonfiguration
my $speechdir='/var/lib/mpd/music/Ansagen';
@@ -52,9 +53,10 @@
delete $plugin_info{$k};
}
- for my $ga (keys %eibgaconf)
+ # Rueckwaertskompatible Behandlung von eibgaconf
+ for my $ga (grep /^[0-9\/]+$/, keys %eibgaconf)
{
- my $name=$eibgaconf{$ga}{'name'};
+ my $name=$eibgaconf{$ga}{name};
next unless defined $name;
for my $pat (keys %channels)
@@ -79,14 +81,14 @@
return join ' ', map $_.'->'.$gas{$_}, keys %gas;
}
-elsif($event=~/bus/ && $msg{'apci'} eq 'A_GroupValue_Write')
+elsif($event=~/bus/ && $msg{apci} eq 'A_GroupValue_Write')
{
- my $ga=$msg{'dst'};
- my $val=$msg{'value'};
- my $dpt=$eibgaconf{$ga}{'DPTSubId'};
+ my $ga=$msg{dst};
+ my $val=$msg{value};
+ my $dpt=$eibgaconf{$ga}{DPTSubId};
$dpt=1.017 unless defined $dpt; # = Trigger, bedeutet Textansage ohne Daten
- my $name=$eibgaconf{$ga}{'name'};
+ my $name=$eibgaconf{$ga}{name};
my $channel=$channels{default};
my $pattern=$name;
@@ -122,9 +124,11 @@
{ push(@statement, 'Zahlen/'.($val?'hoch':'runter').'.wav'); }
when(1.009) # Auf/Zu
{ push(@statement, 'Zahlen/'.($val?'auf':'zu').'.wav'); }
+ when(2.007) # Auf/Ab/Stop
+ { push(@statement, 'Zahlen/'.($val==1?'auf':($val==-1?'ab':'stop')).'.wav'); }
when([5.010,7.001,12.001]) # Ordinalzahl
{ push(@statement, number(\@speech, $val, -1)); }
- when([6.010,8.001,13.001]) # Kardinalzahl
+ when([3.007,6.010,8.001,13.001]) # Kardinalzahl
{ push(@statement, number(\@speech, $val)); }
when([5.001,6.001]) # Prozent
{
@@ -176,13 +180,13 @@
push(@statement, "Wochentage/$1.wav");
push(@statement, number(\@speech, $2));
push(@statement, "Zeiten/Uhr.wav");
- push(@statement, number(\@speech, $3));
+ push(@statement, number(\@speech, $3)) if $3;
}
- elsif($val=~/^([0-9][0-9])\:([0-9][0-9])}\:([0-9][0-9])/)
+ elsif($val=~/^([0-9][0-9])\:([0-9][0-9])/)
{
- push(@statement, number(\@speech, $2));
+ push(@statement, number(\@speech, $1));
push(@statement, "Zeiten/Uhr.wav");
- push(@statement, number(\@speech, $3)) if $3;
+ push(@statement, number(\@speech, $2)) if $2;
}
else
{
@@ -224,9 +228,9 @@
# Konstruiere die abzuspielenden File(s) aus dem GA-Kuerzel
# erster Versuch: eine Datei passt komplett auf das Muster im Kuerzel
my $pat1=$pattern;
- $pat1=~s/[_\s]+/.*?/g; # allgemeine Fassung
-# $pat1=~s/\s+.*$//; # meine spezielle GA-Struktur
-# $pat1=~s/_+/.*?/g; # meine spezielle GA-Struktur
+# $pat1=~s/[_\s]+/.*?/g; # allgemeine Fassung
+ $pat1=~s/\s+.*$//; # meine spezielle GA-Struktur
+ $pat1=~s/_+/.*?/g; # meine spezielle GA-Struktur
$pat1='.*'.$pat1.'.*\.wav$';
my @hits=();
@@ -236,8 +240,8 @@
unless(@hits)
{
$pattern='_'.$pattern;
- $pattern=~s/\s+/_/g; # allgemeine Fassung
-# $pattern=~s/\s+.*$//; # meine spezielle GA-Struktur
+# $pattern=~s/\s+/_/g; # allgemeine Fassung
+ $pattern=~s/\s+.*$//; # meine spezielle GA-Struktur
# zweiter Versuch: aus Kuerzeln die Bausteine zusammenbauen
while($pattern=~s/^_([^_]+)//)
@@ -441,11 +445,11 @@
system "$mpc update"; # Aktualisierung verfuegbarer Soundclips
# wird momentan noch was gespielt?
- my $playing = grep /playing/, `$mpc`;
-
- system "$mpc clear" unless $playing; # aufraeumen
+ system "$mpc clear" unless `$mpc`=~/playing/s; # leeren falls abgespielt
system "$mpc add \"".(join "\" \"", @_)."\"";
- system "$mpc play" unless $playing; # nur dann noetig
+# plugin_log($plugname, "$mpc add \"".(join "\" \"", @_)."\"");
+# plugin_log($plugname, "$mpc play") unless `$mpc`=~/playing/s;
+ system "$mpc play" unless `$mpc`=~/playing/s; # starten falls noch nicht aktiv
# $playing=`$mpc; $mpc outputs`;
# $playing=~s/\s+/ /sg;
Modified: wiregate/plugin/generic/Logikprozessor.pl
===================================================================
--- wiregate/plugin/generic/Logikprozessor.pl 2012-05-11 19:12:49 UTC (rev 810)
+++ wiregate/plugin/generic/Logikprozessor.pl 2012-05-11 22:17:00 UTC (rev 811)
@@ -8,6 +8,7 @@
#$plugin_info{$plugname.'_cycle'}=0; return 'deaktiviert';
my $use_short_names=1; # 1 fuer GA-Kuerzel (erstes Wort des GA-Namens), 0 fuer die "nackte" Gruppenadresse
+my $stime=time(); # Stoppuhr zum Nachverfolgen der Reaktionsgeschwindigkeit der Logikengine
# eibgaconf fixen falls nicht komplett indiziert
if($use_short_names && !exists $eibgaconf{ZV_Uhrzeit})
@@ -80,7 +81,7 @@
{
$plugin_info{$plugname.'_configtime'}=(24*60*60*(-M $conf)-time());
- # alle Variablen loeschen und neu initialisieren, alle GAs abonnieren
+ # alle Variablen loeschen
for my $k (grep /^$plugname\_/, keys %plugin_info)
{
delete $plugin_info{$k};
@@ -92,6 +93,7 @@
for my $t (keys %logic)
{
next if $t eq 'debug';
+ $t=~s/^_//g;
# Debuggingflag gesetzt
my $debug = $logic{debug} || $logic{$t}{debug};
@@ -172,6 +174,7 @@
for my $t (keys %logic)
{
next if $t eq 'debug';
+ $t=~s/^_//g;
my $transmit=groupaddress($logic{$t}{transmit});
my $transmit_ga = ($ga eq $transmit);
@@ -208,7 +211,9 @@
my $result=$plugin_info{$plugname.'_'.$t.'_result'};
if(defined $result)
{
- plugin_log($plugname, "$ga:Lesetelegramm -> \$logic{$t}{transmit}(memory) -> $ga:$result gesendet") if $debug;
+ plugin_log($plugname, "$ga:Lesetelegramm -> \$logic{$t}{transmit}(memory) -> $ga:$result gesendet ("
+ .sprintf("%0.1f",time()-$stime)."s)") if $debug;
+ $stime=time();
knx_write($ga, $result);
}
next;
@@ -232,26 +237,34 @@
# Nebenbei berechnen wir noch zwei Flags, die Zirkelkommunikation verhindern sollen
# (Logik antwortet auf sich selbst in einer Endlosschleife)
- # war Wiregate der Sender des Telegramms?
- my $sender_is_wiregate = $msg{src} eq $eibd_backend_address;
+ # Cool-Periode definiert und noch nicht abgelaufen?
+ if(defined $plugin_info{$plugname.'__'.$t.'_cool'} && $plugin_info{$plugname.'__'.$t.'_cool'}>time())
+ {
+ plugin_log($plugname, "$ga:$in -> \$logic{$t}{receive}(Cool)") if $debug;
+ next;
+ }
# Aufruf der Logik-Engine
my $result=execute_logic($t, $receive, $ga, $in);
- # Zirkelaufruf ausschliessen
+ # war Wiregate der Sender des Telegramms?
+ # Zirkelaufruf mit wiederholt gleichen Ergebnissen ausschliessen
+ my $sender_is_wiregate = $msg{src} eq $eibd_backend_address;
next if $sender_is_wiregate && $transmit_ga && $in == $result;
# In bestimmten Sonderfaellen nichts schicken
unless(defined $result) # Resultat undef => nichts senden
{
- plugin_log($plugname, "$ga:$in -> \$logic{$t}{receive}(Logik) -> nichts zu senden") if $debug;
+ plugin_log($plugname, "$ga:$in -> \$logic{$t}{receive}(Logik) -> nichts zu senden (".sprintf("%0.1f",time()-$stime)."s)") if $debug;
+ $stime=time();
next;
}
if($logic{$t}{transmit_only_on_request})
{
- plugin_log($plugname, "$ga:$in -> \$logic{$t}{receive}(Logik) -> $transmit:$result gespeichert")
+ plugin_log($plugname, "$ga:$in -> \$logic{$t}{receive}(Logik) -> $transmit:$result gespeichert (".sprintf("%0.1f",time()-$stime)."s)")
if $debug;
+ $stime=time();
next;
}
@@ -259,13 +272,20 @@
if($logic{$t}{delay})
{
$plugin_info{$plugname.'__'.$t.'_timer'}=$systemtime+$logic{$t}{delay};
- plugin_log($plugname, "$msg{src} $ga:$in -> \$logic{$t}{receive}(Logik) -> $transmit:$result, zu senden in ".$logic{$t}{delay}."s")
- if $debug;
+ $plugin_info{$plugname.'__'.$t.'_cool'}=time()+$logic{$t}{delay}+$logic{$t}{cool} if defined $logic{$t}{cool};
+ plugin_log($plugname, "$msg{src} $ga:$in -> \$logic{$t}{receive}(Logik) -> $transmit:$result, zu senden in ".$logic{$t}{delay}."s ("
+ .sprintf("%0.1f",time()-$stime)."s)") if $debug;
+ $stime=time();
}
else
{
knx_write($transmit, $result);
- plugin_log($plugname, "$msg{src} $ga:$in -> \$logic{$t}{receive}(Logik) -> $transmit:$result gesendet") if $debug;
+ plugin_log($plugname, "$msg{src} $ga:$in -> \$logic{$t}{receive}(Logik) -> $transmit:$result gesendet ("
+ .sprintf("%0.1f",time()-$stime)."s)") if $debug;
+ $stime=time();
+
+ # Cool-Periode starten
+ $plugin_info{$plugname.'__'.$t.'_cool'}=time()+$logic{$t}{cool} if defined $logic{$t}{cool};
}
}
@@ -298,7 +318,9 @@
# zu sendendes Resultat = zuletzt berechnetes Ergebnis der Logik
$result=$plugin_info{$plugname.'_'.$t.'_result'};
plugin_log($plugname, "\$logic{$t} -> $transmit:".
- (defined $result?$result.($toor?" gespeichert":" gesendet"):"nichts zu senden")." (delayed)") if $debug;
+ (defined $result?$result.($toor?" gespeichert":" gesendet"):"nichts zu senden")." (delayed) ("
+ .sprintf("%0.1f",time()-$stime)."s)") if $debug;
+ $stime=time();
}
else
{
@@ -306,7 +328,9 @@
# Aufruf der Logik-Engine
$result=execute_logic($t, groupaddress($logic{$t}{receive}), undef, undef);
plugin_log($plugname, "\$logic{$t} -> $transmit:".
- (defined $result?$result.($toor?" gespeichert":" gesendet"):"nichts zu senden")." (Timer)") if $debug;
+ (defined $result?$result.($toor?" gespeichert":" gesendet"):"nichts zu senden")." (Timer) ("
+ .sprintf("%0.1f",time()-$stime)."s)") if $debug;
+ $stime=time();
}
# Timer loeschen bzw. neu setzen
@@ -315,6 +339,9 @@
if(defined $result && !$toor)
{
knx_write($transmit, $result);
+
+ # Cool-Periode starten
+ $plugin_info{$plugname.'__'.$t.'_cool'}=time()+$logic{$t}{cool} if defined $logic{$t}{cool};
}
}
else # noch nicht faelliger Timer
@@ -400,7 +427,7 @@
# Schedule-Form standardisieren (alle Eintraege in Listenform setzen und Wochentage durch Zahlen ersetzen)
# dabei gleich schauen, ob HEUTE noch ein Termin ansteht
$schedule=[$schedule] if ref $schedule eq 'HASH';
- my %weekday=(Mo=>1,Di=>2,Mi=>3,Do=>4,Fr=>5,Sa=>6,So=>7);
+ my %weekday=(Mo=>1,Mo=>1,Mon=>1,Di=>2,Tu=>2,Tue=>2,Mi=>3,We=>3,Wed=>3,Do=>4,Th=>4,Thu=>4,Fr=>5,Fri=>5,Sa=>6,Sat=>6,So=>7,Su=>7,Sun=>7);
for my $s (@{$schedule})
{
Modified: wiregate/plugin/generic/conf.d/Logikprozessor.conf
===================================================================
--- wiregate/plugin/generic/conf.d/Logikprozessor.conf 2012-05-11 19:12:49 UTC (rev 810)
+++ wiregate/plugin/generic/conf.d/Logikprozessor.conf 2012-05-11 22:17:00 UTC (rev 811)
@@ -3,13 +3,14 @@
# Logikprozessor.pl - Konfiguration
#
-$eibd_backend_address='1.1.254'; # eigene Adresse zur Vermeidung von Zirkellogiken
+$eibd_backend_address='1.1.254'; # eigene Adresse zur Vermeidung von Zirkellogiken '0.0.0';
%logic=(
# 1. Alle Werte, die auf einer GA gesendet werden, werden mit 2 multipliziert auf einer anderen GA weitergegeben
mal2 => { receive=>'9/5/201', transmit=>'9/5/202', translate => sub { 2*$input; }, },
# das "undef" steht da einfach, weil uns der letzte Ergebniswert nicht interessiert
-
+ # Namen von Logiken (hier "mal2" sind voellig frei, duerfen aber nicht mit einem "_" beginnen.
+
# 2. Die Werte auf der ersten GA werden aufsummiert, das Ergebis auf der anderen GA gesendet.
# Damit kann man bspw aus einem relativen Dimmwert einen absoluten Dimmwert machen.
sum => { receive=>'9/5/207', transmit=>'9/5/208', translate => sub { $state+$input; }, },
@@ -18,7 +19,15 @@
# 3. Wie oben, aber das Ergebnis limitiert auf den Bereich 0-100
lsum => { receive=>'1/2/7', transmit=>'1/2/8', translate => sub { limit(0,$state+$input,100); }, },
- # 4. Hier eine "Treppenlichtfunktion". Auf jeden Schreibzugriff auf die receive-Adresse wird 10min spaeter eine 0 an
+ # 4. Memory-Funktion. Fuer KNX-Ger\xE4te, die kein Auslesen ihres Statuswerts zulassen (z.B. MDT DaliControl
+ # bei Einzel-EVG-Ansteuerung). Sehr einfach:
+ memory => { transmit=>'1/2/9' },
+ # Hier wird folgende Eigenschaft der Logik ausgenutzt: Wenn ein Write-Telegramm auf die Transmit-Adresse kommt,
+ # speichert der Logikprozessor den Wert immer automatisch ab. Eine Leseanfrage auf der transmit-GA hingegen wird
+ # immer mit dem letzten Wert (hier also dem gespeicherten) beantwortet. Eine receive-Adresse oder translate-Logik
+ # werden hier gar nicht gebraucht.
+
+ # 5. Hier eine "Treppenlichtfunktion". Auf jeden Schreibzugriff auf die receive-Adresse wird 10min spaeter eine 0 an
# die transmit-Adresse (hier gleich) geschickt. Verzoegert wird uebrigens nur das Senden, nicht das Ausfuehren der
# translate-Routine. Neu ist hier der "delay"-Parameter, ausserdem der Spezialfall, dass translate einfach eine Konstante als
# Rueckgabewert spezifiziert.
@@ -26,35 +35,41 @@
# Verzoegert wird uebrigens nur das Senden, nicht das Ausfuehren der translate-Routine.
# Neu ist hier der "delay"-Parameter, ausserdem der Spezialfall, dass translate einfach eine Konstante
# als Rueckgabewert spezifiziert.
-
+
# Weitere Bemerkungen:
# * translate darf nur entweder eine Konstante oder ausf\xFChrbarer Code (sub {...}) sein.
# * Damit im Fall transmit==receive der Translator nicht auf sein eigenes Schreibtelegramm immer wieder antwortet,
- # wird nur dann gesendet, wenn Ergebnis!=Input oder Sender des empfangenen Telegramms!=0 (Wiregate).
+ # wird nur dann gesendet, wenn Ergebnis!=Input oder Sender des empfangenen Telegramms!=$eibd_backend_address (Wiregate).
+ # * Wenn waehrend der delay-Zeit erneut ein Receive-Telegramm empfangen wird, wird die Logik erneut ausgefuehrt und
+ # die delay-Zeit beginnt von vorne (wie bei einem Treppenlicht die Leuchtzeit bei erneutem Druecken verlaengert wird).
- # Damit im Fall transmit != receive der Logikprozessor nicht auf sein eigenes Schreibtelegramm immer wieder antwortet,
- # wird nur dann gesendet, wenn Ergebnis != Input oder Sender des empfangenen Telegramms!=0 (Wiregate).
+ # Als weitere Sicherheit vor Zirkellogiken (die ja auch im Zusammenwirken mehrerer Logiken entstehen koennen) gibt es
+ # die Klausel "cool=>...", die eine Logik nur dann zur Ausfuehrung zulaesst, wenn seit der letzten Ausfuehrung
+ # die spezifizierte Zahl von Sekunden verstrichen ist. Im obigen Beispiel also zB
+ stair2 => { receive=>'1/2/9', transmit=>'1/2/9', delay=>600, translate => 0, cool=>650 },
+ # So werden Zirkelschluesse komplett unmoeglich.
+ # Hinweise zu cool:
+ # * bei gesetztem "cool=>..." wird die Ausfuehrung der Logik auf receive-Telegramme (nicht aber die Reaktion auf
+ # Schreib/Lesetelegramme wie in Bsp 4) fuer die definierte Zeit verhindert.
+ # * Falls gleichzeitig "delay=>..." spezifiziert ist, so wird die erneute Ausfuehrung der Logik bereits waehrend
+ # der delay-Zeit verhindert bis zum folgenden Schreibvorgang UND danach noch fuer die in cool=>... spezifizierte
+ # Anzahl Sekunden.
+ # * Ein Setzen von cool=>0 und delay=>10 hat den Effekt, dass die Ausfuehrung der Logik sofort nach Senden des
+ # transmit-Telegramms wieder erlaubt ist, aber NICHT waehrend der delay-Zeit (hier 10s).
+
# 5. Hier eine Logik, die den Input bei Eintreffen mit 2 multipliziert, das Resultat aber nur speichert und erst
# spaeter auf ein explizites Lesetelegramm hin auf der transmit-Adresse sendet.
req => { receive=>'1/2/9', transmit=>'1/2/9', transmit_on_request=>1, translate => sub { 2*$input; }, },
# 6. Eine Logik, die einem Lichtanschalten gleich einen Dimmwert hinterherfeuert, und zwar tags und nachts einen verschiedenen:
- dim => { receive=>'2/2/9', transmit=>'2/3/9', translate => sub { return unless $input; $day ? 80 : 3; }, },
- # Die Variablen $day_of_week (Mo...So), $day_of_month (01-31), $month (01-12), $year (2012),
+ dim => { receive=>'2/2/9', transmit=>'2/3/9', translate => sub { return unless $input; $day ? 80 : 3; } },
+ # Die Variablen $day_of_week (Mo...So), $calendar_week, $day_of_month (01-31), $month (01-12), $year (2012),
# $weekend (0 oder 1), $weekday (= nicht $weekend), $time_of_day ("08:34:02"),
# $hour ("08"), $day (1 falls zwischen 7 und 23 Uhr, 0 sonst) und $night (entsprechend umgekehrt)
# sind f\xFCr diese Logiken vorbesetzt (bitte nicht darauf schreiben, koennte unverhergesehene Auswirkungen
# auf andere Logiken haben).
- # 7. Memory-Funktion. Fuer KNX-Ger\xE4te, die kein Auslesen ihres Statuswerts zulassen (z.B. MDT DaliControl
- # bei Einzel-EVG-Ansteuerung). Sehr einfach:
- memory => { transmit=>'1/2/9' },
- # Hier wird folgende Eigenschaft der Logik ausgenutzt: Wenn ein Write-Telegramm auf die Transmit-Adresse kommt,
- # speichert der Logikprozessor den Wert immer automatisch ab. Eine Leseanfrage auf der transmit-GA hingegen wird
- # immer mit dem letzten Wert (hier also dem gespeicherten) beantwortet. Eine receive-Adresse oder translate-Logik
- # werden hier gar nicht gebraucht.
-
# 8. Eine einfache UND-Logik mit zwei Eingaengen. Falls ein Telegramm auf einer der beiden receive-GAs empfangen wird,
# wird die andere Adresse noch ausgelesen, die Logik angewendet und das Ergebnis auf der transmit-GA uebermittelt
und => { receive=>['1/2/12','1/2/13'], transmit=>'1/2/14', translate => sub { $input->[0] && $input->[1]; }, debug=>1 },
@@ -76,13 +91,14 @@
# Dienstag jedes Monats eine 1 auf Transmit sendet
wecker => { transmit=>'10/1/15', timer=>{ time=>['08:00','10:00'], day_of_month=>[(8..14)], day_of_week=>'Di' }, translate => 1 },
# Logiken mit timer-Klausel weichen in mehreren Punkten von den bisherigen Logiken ab:
- # * sie ignorieren die delay-Klausel und senden sofort, aber transmit_only_on_request funktioniert
+ # * sie ignorieren die delay-Klausel und die cool-Klausel
+ # * transmit_only_on_request funktioniert
# * jeglicher Bustraffic auf receive-Adressen wird ignoriert. (Diese werden aber beim Timer-Aufruf abgefragt,
# um das input-Array vorzubesetzen).
# Als timer-Eintrag geht entweder ein einzelnes Hash timer=>{...} wie oben oder eine Liste solcher Eintraege
# time=>[{...},{...},{...},...]. Jeder Eintrag MUSS eine Spezifikation time=>'XX:XX' enthalten (auch das darf wieder
- # eine Liste sein) und DARF zusaetzliche, die Geltungstage einschraenkende Klauseln wie year, month, day_of_month,
- # day_of_week, calendar_week enthalten.
+ # eine Liste sein) und DARF zusaetzliche, die Geltungstage einschraenkende Klauseln wie year, month, day_of_month,
+ # calendar_week, day_of_week (Mo...So oder Mon...Sun oder 1...7) enthalten.
# 11. Schlussendlich wieder mal Werbung fuer die GA-Kurznamen. Setzt man im Skript Logikprozessor.pl $use_short_names=1
# und verwendet GA-Namen mit eindeutigem Kuerzel (=erstes Wort des Namens), so funktioniert auch das folgende:
@@ -92,5 +108,3 @@
# in einen absoluten Wert umgewandelt
);
-
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|