diff --git a/fhem/contrib/90_EIBUPDOWN.pm b/fhem/contrib/90_EIBUPDOWN.pm new file mode 100644 index 000000000..2eda69912 --- /dev/null +++ b/fhem/contrib/90_EIBUPDOWN.pm @@ -0,0 +1,210 @@ +############################################## +package main; + +use strict; +use warnings; + +my %eib_c2b1 = ( + "alloff" => "00", + "off" => "01", + "on" => "00", + "up" => "01", + "down" => "00", + "up-for-timer" => "01", +); + +my %eib_c2b2 = ( + "alloff" => "00", + "off" => "00", + "on" => "01", + "up" => "00", + "down" => "01", + "up-for-timer" => "00", + "down-for-timer" => "01", +); + + +my %readonly = ( + "dummy" => 1, +); + +my $eib_simple ="alloff off on up down up-for-timer down-for-timer"; +my %models = ( +); + +sub +EIBUPDOWN_Initialize($) +{ + my ($hash) = @_; + + $hash->{Match} = "^B.*"; + $hash->{SetFn} = "EIBUPDOWN_Set"; + $hash->{StateFn} = "EIBUPDOWN_SetState"; + $hash->{DefFn} = "EIBUPDOWN_Define"; + $hash->{UndefFn} = "EIBUPDOWN_Undef"; + $hash->{ParseFn} = "EIBUPDOWN_Parse"; + $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 dummy:1,0 showtime:1,0 model:EIB loglevel:0,1,2,3,4,5,6"; + +} + + +############################# +sub +EIBUPDOWN_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + my $u = "wrong syntax: define EIBUPDOWN "; + + return $u if(int(@a) < 4); + return "Define $a[0]: wrong up group name format: specify as 0-255/0-255/0-255" + if( ($a[2] !~ m/^[0-9]{1,3}\/[0-9]{1,3}\/[0-9]{1,3}$/i)); + + return "Define $a[0]: wrong down group name format: specify as 0-255/0-255/0-255" + if( ($a[3] !~ m/^[0-9]{1,3}\/[0-9]{1,3}\/[0-9]{1,3}$/i)); + + my $groupname_up = eibupdown_name2hex($a[2]); + my $groupname_down = eibupdown_name2hex($a[3]); + + $hash->{GROUP_UP} = lc($groupname_up); + $hash->{GROUP_DOWN} = lc($groupname_down); + + my $code = "$groupname_up$groupname_down"; + my $ncode = 1; + my $name = $a[0]; + + $hash->{CODE}{$ncode++} = $code; + $modules{EIB}{defptr}{$code}{$name} = $hash; + + AssignIoPort($hash); +} + +############################# +sub +EIBUPDOWN_Undef($$) +{ + my ($hash, $name) = @_; + + foreach my $c (keys %{ $hash->{CODE} } ) { + $c = $hash->{CODE}{$c}; + + # As after a rename the $name may be different from the $defptr{$c}{$n} + # we look for the hash. + foreach my $dname (keys %{ $modules{EIB}{defptr}{$c} }) { + delete($modules{EIB}{defptr}{$c}{$dname}) + if($modules{EIB}{defptr}{$c}{$dname} == $hash); + } + } + return undef; +} + +##################################### +sub +EIBUPDOWN_SetState($$$$) +{ + my ($hash, $tim, $vt, $val) = @_; + + $val = $1 if($val =~ m/^(.*) \d+$/); + return "Undefined value $val" if(!defined($eib_c2b1{$val})); + return undef; +} + +################################### +sub +EIBUPDOWN_Set($@) +{ + my ($hash, @a) = @_; + my $ret = undef; + my $na = int(@a); + + return "no set value specified" if($na < 2 || $na > 3); + return "Readonly value $a[1]" if(defined($readonly{$a[1]})); + + my $c_off = $eib_c2b1{"alloff"}; + my $c_up = $eib_c2b1{$a[1]}; + my $c_down = $eib_c2b2{$a[1]}; + if(!defined($c_off) || !defined($c_up) || !defined($c_down)) { + return "Unknown argument $a[1], choose one of " . + join(" ", sort keys %eib_c2b1); + } + + my $v = join(" ", @a); + Log GetLogLevel($a[0],2), "EIB set $v"; + (undef, $v) = split(" ", $v, 2); # Not interested in the name... + + # first of all switch off all channels + # just for being sure + IOWrite($hash, "B", "w" . $hash->{GROUP_UP} . $c_off); + select(undef,undef,undef,0.5); + IOWrite($hash, "B", "w" . $hash->{GROUP_DOWN} . $c_off); + select(undef,undef,undef,0.5); + + # now switch on the right channel + if($c_up ne $c_off) { + IOWrite($hash, "B", "w" . $hash->{GROUP_UP} . $c_up); + } + elsif($c_down ne $c_off) { + IOWrite($hash, "B", "w" . $hash->{GROUP_DOWN} . $c_down); + } + + ########################################### + # Delete any timer for on-for_timer + if($modules{EIB}{ldata}{$a[0]}) { + CommandDelete(undef, $a[0] . "_timer"); + delete $modules{EIB}{ldata}{$a[0]}; + } + + ########################################### + # Add a timer if any for-timer command has been chosen + if($a[1] =~ m/for-timer/ && $na == 3) { + my $dur = $a[2]; + my $to = sprintf("%02d:%02d:%02d", $dur/3600, ($dur%3600)/60, $dur%60); + $modules{EIB}{ldata}{$a[0]} = $to; + Log 4, "Follow: +$to set $a[0] off"; + CommandDefine(undef, $a[0] . "_timer at +$to set $a[0] off"); + } + + ########################## + # Look for all devices with the same code, and set state, timestamp + my $code = "$hash->{GROUP_UP}$hash->{GROUP_DOWN}"; + my $tn = TimeNow(); + foreach my $n (keys %{ $modules{EIB}{defptr}{$code} }) { + + my $lh = $modules{EIB}{defptr}{$code}{$n}; + $lh->{CHANGED}[0] = $v; + $lh->{STATE} = $v; + $lh->{READINGS}{state}{TIME} = $tn; + $lh->{READINGS}{state}{VAL} = $v; + } + return $ret; +} + +sub +EIBUPDOWN_Parse($$) +{ + my ($hash, $msg) = @_; + + Log(5,"EIBUPDOWN_Parse is not defined. msg: $msg"); + +} + +############################# +sub +eibupdown_name2hex($) +{ + my $v = shift; + my $r = $v; + Log(5, "name2hex: $v"); + if($v =~ /^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{1,3})$/) { + $r = sprintf("%01x%01x%02x",$1,$2,$3); + } + elsif($v =~ /^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{1,3})$/) { + $r = sprintf("%01x%01x%02x",$1,$2,$3); + } + + return $r; +} + + +1;