From 9ede1c33113be07fe4cd973ae2419f3662f36d64 Mon Sep 17 00:00:00 2001 From: odroegehorn <> Date: Wed, 12 Oct 2011 12:53:35 +0000 Subject: [PATCH] CUL_IR; Infrared support for CUN/CUNO/TuxRadio git-svn-id: https://svn.fhem.de/fhem/trunk@1069 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/10_CUL_IR.pm | 316 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 fhem/FHEM/10_CUL_IR.pm diff --git a/fhem/FHEM/10_CUL_IR.pm b/fhem/FHEM/10_CUL_IR.pm new file mode 100644 index 000000000..d765a30e8 --- /dev/null +++ b/fhem/FHEM/10_CUL_IR.pm @@ -0,0 +1,316 @@ +###################################################### +# CUL InfraRed handler as FHM-Module +# +# (c) Olaf Droegehorn / DHS-Computertechnik GmbH +# +# Published under GNU GPL License +###################################################### +package main; + +use strict; +use warnings; + +sub CUL_IR_Define($$); +sub CUL_IR_Undef($$); +sub CUL_IR_Initialize($); +sub CUL_IR_Parse($$); +#sub CUL_IR_SendCmd($$$$); +sub CUL_IR_Set($@); +sub CUL_IR_Attr(@); + + +my %sets = ( + "irLearnForSec" => "" +); + + +sub +CUL_IR_Initialize($) +{ + my ($hash) = @_; + + $hash->{Match} = "^I............"; + $hash->{DefFn} = "CUL_IR_Define"; + $hash->{UndefFn} = "CUL_IR_Undef"; + $hash->{ParseFn} = "CUL_IR_Parse"; + $hash->{SetFn} = "CUL_IR_Set"; + $hash->{AttrFn} = "CUL_IR_Attr"; + $hash->{AttrList} = "do_not_notify:1,0 ignore:0,1 " . + "loglevel:0,1,2,3,4,5,6 learnprefix learncount " . + "Button.* Group.* irReceive:OFF,ON,ON_NR"; +} + + +############################# +sub +CUL_IR_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $testhash = ""; + + my $u = "wrong syntax: define CUL_IR "; + + return $u if(int(@a) < 3); + + #Assign CUL/CUN within definition as IODev + for my $p (sort { $defs{$b}{NR} <=> $defs{$a}{NR} } keys %defs) { + + my $cl = $defs{$p}{Clients}; + $cl = $modules{$defs{$p}{TYPE}}{Clients} if(!$cl); + + if((defined($cl) && $cl =~ m/:CUL_IR:/) && + $defs{$p}{NAME} eq $a[2]) { + $hash->{IODev} = $defs{$p}; + last; + } + } + if(!$hash->{IODev}) { + Log 3, "No I/O device found for $hash->{NAME}"; + return "Wrong IODev specified or IODev doesn't support CUL_IR"; + } + + #Check if we have already an CUL_IR Device for IODEV + foreach my $name (keys %{ $modules{CUL_IR}{defptr} }) { + $testhash = ($modules{CUL_IR}{defptr}{$name}) + if($modules{CUL_IR}{defptr}{$name}->{IODev} == $hash->{IODev}); + } + if ($testhash) { #found another CUL_IR for this IODEV!! + Log 2, "CUL_IR already defined for this I/O device"; + return "CUL_IR already defined for this I/O device, it's: $testhash->{NAME}"; + } + + #Everything is fine, let's finish definition + $modules{CUL_IR}{defptr}{("IR_" . $a[2])} = $hash; + $hash->{STATE} = "Initialized"; + if (!$attr{$hash->{NAME}}{'learnprefix'}) { + $attr{$hash->{NAME}}{'learnprefix'} = "A"; + } + if (!$attr{$hash->{NAME}}{'learncount'}) { + $attr{$hash->{NAME}}{'learncount'} = 0; + } + + Log 4, "Sending $hash->{IODev}->{NAME}: Ir"; + my $msg = CallFn($hash->{IODev}->{NAME}, "GetFn", $hash->{IODev}, (" ", "raw", "Ir")); + Log 4, "Answer from $hash->{IODev}->{NAME}: $msg"; + + if ($msg =~ m/raw => 00/) { + $hash->{irReceive} = "OFF"; + } elsif ($msg =~ m/raw => 01/) { + $hash->{irReceive} = "ON"; + } elsif ($msg =~ m/raw => 02/) { + $hash->{irReceive} = "ON_NR"; + } elsif ($msg =~ m/No answer/) { + $hash->{irReceive} = "NoAnswer"; + } else { + Log 2, "CUL_IR IODev device didn't answer Ir command correctly: $msg"; + $hash->{irReceive} = "UNKNOWN"; + } + + return undef; +} + +############################# +sub +CUL_IR_Undef($$) +{ + my ($hash, $name) = @_; + + # As after a rename the $name my be different from the $defptr{$n} + # we look for the hash. + foreach my $name (keys %{ $modules{CUL_IR}{defptr} }) { + delete($modules{CUL_IR}{defptr}{$name}) + if($modules{CUL_IR}{defptr}{$name} == $hash); + } + + return undef; +} + + +############################# +sub +CUL_IR_Parse($$) +{ + my ($iohash, $msg) = @_; + my $myhash = ""; + my $found = 0; + + foreach my $name (keys %{ $modules{CUL_IR}{defptr} }) { + $myhash = ($modules{CUL_IR}{defptr}{$name}) + if($modules{CUL_IR}{defptr}{$name}->{IODev} == $iohash); + } + + if(!$myhash) { + Log 4, "IR-Message from $iohash->{NAME}: $msg"; + Log 2, "No CUL_IR device found for $iohash->{NAME}, please define a new one"; + return "UNDEFINED CUL_IR_$iohash->{NAME} CUL_IR $iohash->{NAME}"; + } + + Log 4, "IR-Reception: $msg"; + + # Search for Button-Group + foreach my $name (keys %{ $attr{$myhash->{NAME}} }) { + if ($name =~ m/^Group.*/) { + my ($ir, $cmd) = split("[ \t]", $attr{$myhash->{NAME}}{$name}, 2); + if ($msg =~ m/$ir.*/) { + if (!$cmd) { + Log 5, "Group found; IR:$ir Def:-"; + } else { + Log 5, "Group found; IR:$ir Def:$cmd"; + AnalyzeCommandChain(undef, $cmd); + } + } + } + } + + # Search for single Button(s) + foreach my $name (keys %{ $attr{$myhash->{NAME}} }) { + if ($name =~ m/^Button.*/) { + my ($ir, $cmd) = split("[ \t]", $attr{$myhash->{NAME}}{$name}, 2); + if ($msg eq $ir) { + $found++; + if (!$cmd) { + Log 5, "Button found; IR:$ir Def:-"; + } else { + Log 5, "Button found; IR:$ir Def:$cmd"; + AnalyzeCommandChain(undef, $cmd); + } + } + } + } + + if (!$found) { # No Button identified yet !! + if (!$myhash->{irLearn}) { # OK, No Learning, then leave + return ""; + } else { # Let's learn Buttons + my $buttonname = ""; + if (!$attr{$myhash->{NAME}}{'learncount'}) { + $attr{$myhash->{NAME}}{'learncount'} = 0; + } + if (!$attr{$myhash->{NAME}}{'learnprefix'}) { # is the learnprefix there? + $buttonname = sprintf("Button%03d", $attr{$myhash->{NAME}}{'learncount'}); + } else { + $buttonname = sprintf("Button%s%03d", $attr{$myhash->{NAME}}{'learnprefix'}, $attr{$myhash->{NAME}}{'learncount'}); + } + $attr{$myhash->{NAME}}{'learncount'}++; + $attr{$myhash->{NAME}}{$buttonname} = $msg; + } + } + + return ""; +} + +sub +CUL_IR_RemoveIRLearn($) +{ + my $hash = shift; + delete($hash->{irLearn}); +} + +################################### +sub +CUL_IR_Set($@) +{ + my ($hash, @a) = @_; + + return "\"set CUL_IR\" needs at least one parameter" if(@a < 2); + return "Unknown argument $a[1], choose one of " . join(" ", sort keys %sets) + if(!defined($sets{$a[1]})); + + my $name = shift @a; + my $type = shift @a; + my $arg = join("", @a); + my $ll = GetLogLevel($name,3); + my $ret = ""; + my $reccommand = ""; + + if($type eq "irLearnForSec") { #################################### + return "Usage: set $name irLearnForSec " + if(!$arg || $arg !~ m/^\d+$/); + $hash->{irLearn} = 1; + InternalTimer(gettimeofday()+$arg, "CUL_IR_RemoveIRLearn", $hash, 1); + } + + return $ret; +} + + +################################### +#sub +#CUL_IR_SendCmd($$$$) +#{ +# my ($hash, $cmd, $sleep, $waitforack) = @_; +# my $io = $hash->{IODev}; +# my $l4 = GetLogLevel($hash->{NAME},4); +# +# select(undef, undef, undef, 0.1*$sleep) if($sleep); +# +# $cmd =~ m/^(..)(.*)$/; +# my ($mn, $cmd2) = ($1, $2); +# +# if($mn eq "++") { +# $mn = $io->{HM_CMDNR} ? ($io->{HM_CMDNR} +1) : 1; +# $mn = 0 if($mn > 255); + +# } else { +# $mn = hex($mn); + +# } + +# $io->{HM_CMDNR} = $mn; +# $cmd = sprintf("As%02X%02x%s", length($cmd2)/2+1, $mn, $cmd2); +# Log $l4, "CUL_IR SEND $cmd"; +# IOWrite($hash, "", $cmd); +# if($waitforack) { +# $hash->{ackWaiting} = $cmd; +# $hash->{ackCmdSent} = 1; +# InternalTimer(gettimeofday()+0.4, "CUL_IR_Resend", $hash, 0); +# } +#} + +sub +CUL_IR_Attr(@) +{ + my @a = @_; + + if($a[2] eq "irReceive") { + + my $name = $a[1]; + my $hash = $defs{$name}; + my $reccommand = ""; + + if($a[3] eq "OFF") { + $reccommand = "00"; + } elsif ($a[3] eq "ON") { + $reccommand = "01"; + } else { + $reccommand = "02"; + } + + my $io = $hash->{IODev}; + + Log 4, "Sending $io->{NAME}: Ir$reccommand"; + my $msg = CallFn($io->{NAME}, "GetFn", $io, (" ", "raw", "Ir".$reccommand)); + Log 4, "Answer from $io->{NAME}: $msg"; + + if ($msg =~ m/raw => 00/) { + $hash->{irReceive} = "OFF"; + } elsif ($msg =~ m/raw => 01/) { + $hash->{irReceive} = "ON"; + } elsif ($msg =~ m/raw => 02/) { + $hash->{irReceive} = "ON_NR"; + } elsif ($msg =~ m/No answer/) { + $hash->{irReceive} = "NoAnswer"; + } else { + Log 2, "CUL_IR IODev device didn't answer Ir command correctly: $msg"; + $hash->{irReceive} = "UNKNOWN"; + } + + Log 2, "Switched $name irReceive to $hash->{irReceive}"; + + } + + return undef; +} + +1;