############################################## package main; use strict; use warnings; my %eib_c2b1 = ( "alloff" => "00", "off" => "01", "on" => "00", "up" => "01", "down" => "00", "up-for-timer" => "01", "down-for-timer" => "00", ); 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] alloff"; CommandDefine(undef, $a[0] . "_timer at +$to set $a[0] alloff"); } ########################## # 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;