########################################################################################################################################################################################## ############################################################################################################################## # $Id: 10_KOPP_FC.pm 10511 2016-01-15 09:09:04Z betateilchen $ # # Kopp Free Control protocol module for FHEM # (c) Claus M. # # This modul is currenly under construction and will only work if you flashed your CCD device with hexfile from: # svn+ssh://raspii@svn.code.sf.net/p/culfw/code/branches/raspii/culfw/Devices/CCD/CCD.hex # which includes support for "K" command # # Published under GNU GPL License, v2 # # Date Who Comment # ---------- ------------- ------------------------------------------------------------------------------------------------------------------------------- # 2016-01-30 RaspII Now also Blinds and Switches are implemented (all actuators I have). # 2016-01-12 RaspII Implemented Dimmer Commands for 1&3 key remote, removed toggle # 2015-06-02 RaspII Now can also Handle multiple devices with same code, next step: implement all commands (on, off, toggle... for KOPP_FC_Parse) # Missing is also 2 key commands (e.g. key1=on Key2=off for Dimmmers, key1=up key2=down for blinds) # 2015-05-21 RaspII Beim FS20 Modul sind die möglichen Set Commands abhängig vom "model" Attribute !! hier weitersuchen # Seit die Return SerExtensions eingebaut ist, lässt sich bei Taste2Rad4 dass Commando Off nicht mehr absetzen (hat was mit dem Modul SerExtensions zu tun) # 2015-05-02 RaspII Try now to receive Kopp Messages, also # 2015-04-13 RaspII Modified some typos (help section) # 2015-02-01 RaspII use small "k" to start Kopp FW, "K" was already used for raw data # 2014-12-21 RaspII V6 (fits to my FHEM.cfg V6) Removed timeout from define command, will add later to set command (best guess yet). # 2014-12-13 RaspII first version with command set: "on, off, toggle, dim, stop". Added new Parameter ("N" for do not print) # 2014-12-08 RaspII direct usage of set command @ FHEM.cfg works fine, but buttoms on/off do not appear, seems to be a setup/initialize issue in this routine # 2014-09-01 RaspII first Version # ########################################################################################################################################################################################## package main; use strict; use warnings; use SetExtensions; # 2015-05-21 Wird vermutlich benötig um später die möglichen "Set" Commandos zu definieren sub KOPP_FC_Initialize($); ##### Claus evt. nicht nötig sub KOPP_FC_Parse($$); ##### Claus evt. nicht nötig my %codes = ( # This Sheet contains all allowed codes, indevpendtly from Model type "01" => "on", "02" => "off", "03" => "toggle", "04" => "dimm", "05" => "stop", "06" => "up", "07" => "down", "08" => "top", "09" => "bottom", ); my %sets = ( # Do not know whether this list is needed (guess: no) "on" => "", "off" => "", "stop" => "", "toggle" => "", "dimm" => "", "up" => "", "down" => "", "top" => "", "bottom" => "" ); my %models = ( Switch_8080_01 => 'Switch', Switch_8080_01_2Key => 'Switch_2KeyMode', Blind_8080_02 => 'Blind', Timer_8080_04 => 'TimerSwitch', Dimm_8011_00 => 'Dimmer', Dimm_8011_00_3Key => 'Dimmer_3KeyMode', ); my %kopp_fc_c2b; # DEVICE_TYPE->hash (reverse of device_codes), ##Claus what does that mean? ############################# sub KOPP_FC_Initialize($) { my ($hash) = @_; foreach my $k (keys %codes) { ## Claus needed if we wanna have the codes via commands $kopp_fc_c2b{$codes{$k}} = $k; # both lines not needed yet } # $hash->{Match} = "^kr.................."; # evt. später nehmen, damit nur genau 19 Zeichen akzeptiert werden $hash->{Match} = "^kr.*"; $hash->{SetFn} = "KOPP_FC_Set"; $hash->{DefFn} = "KOPP_FC_Define"; $hash->{UndefFn} = "KOPP_FC_Undef"; $hash->{ParseFn} = "KOPP_FC_Parse"; $hash->{AttrFn} = "KOPP_FC_Attr"; # aus SOMFY Beispiel abgeleitet $hash->{AttrList} = "IODev ". "model:".join(",", sort keys %models); # . " symbol-length" # . " enc-key" # . " rolling-code" # . " repetition" # . " switch_rfmode:1,0" # . " do_not_notify:1,0" # . " ignore:0,1" # . " dummy:1,0" # . " model:somfyblinds" # . " loglevel:0,1,2,3,4,5,6"; } ############################# sub KOPP_FC_Define($$) { my ( $hash, $def ) = @_; my @a = split( "[ \t][ \t]*", $def ); my $name = $hash->{NAME};## neu 14.5. my $u = "wrong syntax: define KOPP_FC keycode(Byte) transmittercode1(2Byte) transmittercode2(Byte)"; my $keycode2 = ""; my $keycode3 = ""; # fail early and display syntax help if ( int(@a) < 4 ) { return $u; } # check keycode format (2 hex digits) if ( ( $a[2] !~ m/^[a-fA-F0-9]{2}$/i ) ) { return "Define $a[0]: wrong keycode format: specify a 2 digit hex value " } my $keycode = $a[2]; $hash->{KEYCODE} = uc($keycode); # check transmittercode1 format (4 hex digits) if ( ( $a[3] !~ m/^[a-fA-F0-9]{4}$/i ) ) { return "Define $a[0]: wrong transmittercode1 format: specify a 4 digit hex value " } my $transmittercode1 = $a[3]; $hash->{TRANSMITTERCODE1} = uc($transmittercode1); # check transmittercode2 format (2 hex digits) if ( ( $a[4] !~ m/^[a-fA-F0-9]{2}$/i ) ) { return "Define $a[0]: wrong transmittercode2 format: specify a 2 digit hex value " } my $transmittercode2 = $a[4]; $hash->{TRANSMITTERCODE2} = uc($transmittercode2); # check keycode2 (optional) format (2 hex digits) if (defined $a[5]){ if ( ( $a[5] !~ m/^[a-fA-F0-9]{2}$/i ) ) { #Default: Keycode2 is empty } else { $keycode2 = $a[5]; $hash->{KEYCODE2} = uc($keycode2); } } # check keycode3 (optional) format (2 hex digits) if (defined $a[6]){ if ( ( $a[5] !~ m/^[a-fA-F0-9]{2}$/i ) ) { #Default: Keycode3 is empty } else { $keycode3 = $a[6]; $hash->{KEYCODE3} = uc($keycode3); } } #Remove check for timeout # check timeout (5 dec digits) # if ( ( $a[5] !~ m/^[0-9]{5}$/i ) ) { # return "Define $a[0]: wrong timeout format: specify a 5 digits decimal value" # } # removed next lines, may be will move timeout to set command (on-for-timer) or something like that # my $timeout = $a[5]; # $hash->{TIMEOUT} = uc($timeout); $hash->{TIMEOUT} = "00000"; #Default timeout = 0 # group devices by their address my $code = uc("$transmittercode1 $keycode"); my $ncode = 1; # my $name = $a[0]; # see above, already defined $hash->{CODE}{ $ncode++ } = $code; ## 6.1.2016: Code jetzt mit Referenz verlinken # $hash->{CODE} = $code; ## dafür diese Zeile raus $modules{KOPP_FC}{defptr}{$code}{$name} = $hash; ## neu 30.5. mit name vermutlich wird hierüber das Device eindeutig identifiziert # Noch die 2te Taste definieren, falls vorhanden if ( $keycode2 ne "") { my $code = uc("$transmittercode1 $keycode2"); $hash->{CODE}{ $ncode++ } = $code; $modules{KOPP_FC}{defptr}{$code}{$name} = $hash; ## neu 30.5. mit name vermutlich wird hierüber das Device eindeutig identifiziert } # Noch die 3te Taste definieren, falls vorhanden if ( $keycode3 ne "") { my $code = uc("$transmittercode1 $keycode3"); $hash->{CODE}{ $ncode++ } = $code; $modules{KOPP_FC}{defptr}{$code}{$name} = $hash; ## neu 30.5. mit name vermutlich wird hierüber das Device eindeutig identifiziert } # Noch so, der "Stop Code" = "F7" nach langem Tastendruck bekommt auch noch einen Eintrag $code = uc("$transmittercode1 F7"); $hash->{CODE}{"stop"} = $code; $modules{KOPP_FC}{defptr}{$code}{$name} = $hash; ## neu 30.5. mit name vermutlich wird hierüber das Device eindeutig identifiziert Log3 $name, 2, "KOPP_FC_Define: Modules: $modules{KOPP_FC}{defptr}{$code}{$name} Name: $name a[0]: $a[0] Transmittercode1: $transmittercode1 Keycode: $keycode Keycode2: $keycode2 $keycode Keycode3: $keycode3 Hash: $hash"; # kann wieder Raus !!!! ### Claus # $hash->{move} = 'on'; # ohne die folgende Zeile gibts beim Speichern von FHEM.cfg die Fehlermeldung Dimmer2 (wenn Dimmer2 als Name festgelegt werden soll) AssignIoPort($hash); } ############################# sub KOPP_FC_Undef($$) { my ($hash, $name) = @_; foreach my $c (keys %{ $hash->{CODE} } ) { $c = $hash->{CODE}{$c}; # As after a rename the $name my be different from the $defptr{$c}{$n} # we look for the hash. foreach my $dname (keys %{ $modules{KOPP_FC}{defptr}{$c} }) { if($modules{KOPP_FC}{defptr}{$c}{$dname} == $hash) { my $m=$modules{KOPP_FC}{defptr}{$c}{$dname}; Log3 $name, 3, "KOPP_FC_Undef: Name: $name, Device: $m deleted"; } delete($modules{KOPP_FC}{defptr}{$c}{$dname}) if($modules{KOPP_FC}{defptr}{$c}{$dname} == $hash); } } return undef; } ############################## sub KOPP_FC_Attr(@) { # write new Attributes to global $attr variable if attribute name is model my ($cmd,$name,$aName,$aVal) = @_; my $hash = $defs{$name}; return "\"KOPP_FC Attr: \" $name does not exist" if (!defined($hash)); # $cmd can be "del" or "set" # $name is device name # aName and aVal are Attribute name and value if ($cmd eq "set") { if ($aName eq 'model') { $attr{$name}{$aName} = $aVal; } } return undef; } ##################################### sub KOPP_FC_SendCommand($@) { my ($hash, @args) = @_; my $ret = undef; my $keycodehex = $args[0]; my $cmd = $args[1]; my $message; my $name = $hash->{NAME}; my $numberOfArgs = int(@args); my $io = $hash->{IODev}; # return $keycodehex $message = "s" . $keycodehex . $hash->{TRANSMITTERCODE1} . $hash->{TRANSMITTERCODE2} . $hash->{TIMEOUT} . "N"; # N for do not print messages (FHEM will write error messages to log files if CCD/CUL sends status info ## Send Message to IODev using IOWrite IOWrite( $hash, "k", $message ); return $ret; } # end sub KOPP_FC_SendCommand ############################# ############################# sub KOPP_FC_Set($@) { my ( $hash, $name, @args ) = @_; # Aufbau hash: Name, Command my $numberOfArgs = int(@args); my $keycodedez; my $keycodehex; my $lh; my $modl; # my $message; if ( $numberOfArgs < 1 ) { return "no set value specified" ; } my $cmd = lc($args[0]); my $c = $kopp_fc_c2b{$args[0]}; if(!defined($c)) # if set command was not yet defined in %codes provide command list # $c contains the first argument of %codes, "01" for "on", "02" for "off" .. { my $list; if(defined($attr{$name}) && defined($attr{$name}{"model"})) { my $mt = $models{$attr{$name}{"model"}}; # Model specific set arguments will be defined here (maybe move later to variable above) $list = "dimm stop on off" if($mt && $mt eq "Dimmer"); # -------------------------------------------------------------------------------------- $list = "dimm stop on off" if($mt && $mt eq "Dimmer_3KeyMode"); # "$mt &&...", damit wird Inhalt von $mt nur geprüft wenn $mt initialisiert ist $list = "on off short" if($mt && $mt eq "TimerSwitch"); # on means long key presure $list = "top bottom up down stop" if($mt && $mt eq "Blind"); # up/down means long key presure $list = "on off" if($mt && $mt eq "Switch"); # (no difference between long/short preasure) $list = "on off" if($mt && $mt eq "Switch_2KeyMode"); # (no difference between long/short preasure) } $list = (join(" ", sort keys %kopp_fc_c2b) . " Claus") if(!defined($list)); # if list not defined model specific, allow whole default list return "[Kopp_FC_Set] unknown command <$cmd>, choose one of " . join(" ", $list); # no more text after "choose one of " allowed } if(defined($attr{$name}) && defined($attr{$name}{"model"})) # Falls Model spezifiziert ist, Model ermitteln -> $mt { # ---------------------------------------------------- $modl = $models{$attr{$name}{"model"}}; # Log3 $name, 2, "KOPP_FC_Set: Device Name: $name Index auf codes: $c Model: $modl"; # kann wieder Raus !!!! ### Claus } # readingsSingleUpdate($hash, "state","$cmd", 1); # update also Readings # $hash->{STATE} = $cmd; # update device state # Look for all devices with the same code, and update readings (state), (timestamp, not yet) # ------------------------------------------------------------------------------------------------------ # some hints: if same code is used within config file for differen models update of state makes no sense # and may fail because command is not available for a different model. So we only update devices which are # of the same model as the original one. # # my $tn = TimeNow(); # my $defptr = $modules{KOPP_FC}{defptr}{transmittercode1}{keycode}; # foreach my $n (keys %{ $defptr }) # { # readingsSingleUpdate($defptr->{$n}, "state","$cmd", 1); # } my $code = $hash->{CODE}{1}; # Load Devices code1 (typically key code short preasure) my $rhash = $modules{KOPP_FC}{defptr}{$code}; # Load Hash of Devices with same code # my @list; # Do (Why) I need this @lists (incl. return @list)? foreach my $n (keys %{ $rhash }) { $lh = $rhash->{$n}; $n = $lh->{NAME}; # It may be renamed, n now contains name of defined device, e.g. Dimmer.... # return "" if(IsIgnored($n)); # Little strange. if(defined ($modl) && defined($attr{$n}) && defined($attr{$n}{"model"})) { my $m=$models{$attr{$n}{"model"}}; Log3 $name, 3, "KOPP_FC_Set: Device Name: $n, command: $cmd, Model: $m, Transm.-/KeyCode: $code"; # Falls auch dieses Model spezifiziert ist und Modell identisch dem Model aus Originalaufruf, if($m eq $modl) # ------------------------------------------------------------------------------------------ { # dann den Status dieses Devices ebenfalls updaten # Log3 $name, 2, "KOPP_FC_Set: Orig Model: $modl, Status Update also for Model: $m"; # kann wieder Raus !!!! ### Claus $lh->{STATE} = $cmd; # update device state readingsSingleUpdate($lh, "state", $cmd, 1); # update also Readings } else { # Log3 $name, 2, "KOPP_FC_Set: Orig Model: $modl, wrong model: $m no Status Update done"; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, " dont define same remote key for different actuators models"; # kann wieder Raus !!!! ### Claus } } # push(@list, $n); } # return @list; # return""; if($cmd eq 'stop') # command = stop { # -------------- $keycodehex = "F7"; # Stop means F7 will be sent several times } # (e.g. to end "dimm" end or "up" / "down" ) elsif($cmd eq 'dimm') # independent of Dimmer Type { # --------------------------- $keycodehex = $hash->{KEYCODE}; # use Keycode+0x80 for long key pressure = dimmer up/down $keycodedez = hex $keycodehex ; # without moving to $keycodehex and addition in second line it does not work !? $keycodedez = $keycodedez + 128; # $keycodehex = uc sprintf "%x", $keycodedez; # } elsif($modl && $modl eq "Dimmer") # if model defined and equal Dimmer { # --------------------------------- if($cmd eq 'on'||$cmd eq 'off') # { # $keycodehex = $hash->{KEYCODE}; # -> use Keycode to send "on" or "off" command (=toggle) } } elsif($modl && $modl eq "Dimmer_3KeyMode") # if model defined and equal 3-key Dimmer { # --------------------------------------- if($cmd eq 'on' && $hash->{KEYCODE2} ne "") # Command = on { # $keycodehex = $hash->{KEYCODE2}; # -> use Keycode 2 to send "on" command } # if($cmd eq 'off' && $hash->{KEYCODE3} ne "") # Command = off { # $keycodehex = $hash->{KEYCODE3}; # -> use Keycode 3 to send "on" command } } elsif($modl && $modl eq "Switch") # if model defined and equal Switch { # --------------------------------- if($cmd eq 'on' || $cmd eq 'off') # { # $keycodehex = $hash->{KEYCODE}; # -> use Keycode to send "on" or "off" command (=toggle) } # } elsif($modl && $modl eq "Switch_2KeyMode") # if model defined and equal Switch controlled by 2 Keys { # ------------------------------------------------------ if($cmd eq 'on') # { # $keycodehex = $hash->{KEYCODE}; # -> use Keycode to send "on" or "off" command (=toggle) } # elsif($cmd eq 'off' && $hash->{KEYCODE2} ne "") # { # $keycodehex = $hash->{KEYCODE2}; # -> use Keycode to send "on" or "off" command (=toggle) } } elsif($modl && $modl eq "Blind") # if model defined and equal Blind: # { # ---------------------------------------- if($cmd eq 'top') # { # -> use Keycode to send "top" command $keycodehex = $hash->{KEYCODE}; # } # elsif($cmd eq 'bottom' && $hash->{KEYCODE2} ne "") # { # -> use Keycode2 to send "bottom" command $keycodehex = $hash->{KEYCODE2}; # } # elsif($cmd eq 'up') # { # $keycodehex = $hash->{KEYCODE}; # $keycodedez = hex $keycodehex ; # -> use Keycode+0x80 to send "up" command $keycodedez = $keycodedez + 128; # $keycodehex = uc sprintf "%x", $keycodedez; # # } # elsif($cmd eq 'down' && $hash->{KEYCODE2} ne "") # { # -> use Keycode2+0x80 to send "dowm" command $keycodehex = $hash->{KEYCODE2}; # $keycodedez = hex $keycodehex ; # $keycodedez = $keycodedez + 128; # $keycodehex = uc sprintf "%x", $keycodedez; # } } elsif($cmd eq 'on'|| 'off' || 'toggle') # If model not known just allow on, off, toggle { # --------------------------------------------- $keycodehex = $hash->{KEYCODE}; # -> use Keycode } else # should never happen :-) { # ----------------------- return "unknown command" ; } KOPP_FC_SendCommand($hash, $keycodehex, @args); # KOPP_FC_SendCommand($hash, @args); # $hash->{STATE} = 'off'; #return SetExtensions($hash,'toggle', @a); return undef; } # end sub Kopp_FC_setFN ############################### ############################# # sub KOPP_FC_Parse($$) { # wird von fhem.pl dispatch getriggert # Example receive Message: kr07FA5E7114CC0F02AD # 07: block length; FA5E: Transmitter Code 1; 71: Key counter(next key pressed); 14: Key Code; # CC0F: unknown, but always the same; # 02: Transmiter Code 2; (content depends on transmitter, changed value seems not to change anything; AD: Checksum) my ($hash, $msg) = @_; my $name = $hash->{NAME}; # Here: Device Hash (e.g. to CUL), e.g. $name = "CUL_0" my $state; # means receive command = new state my $keycodedez; my $specialkey = "short"; # Default: short key my $code; my $devicefound; if( $msg =~ m/^kr/ ) { # if first two char's are "kr" then we are right here (KOPP Message received) # Msg format: # kr.. rest to be defined later # if (substr($msg, 0, 16) eq "krS-ReceiveStart" || substr($msg, 0, 14) eq "krE-ReceiveEnd") if (substr($msg, 0, 2) eq "kr") { # get Transtmitter Code 1 my $transmittercode1 = uc(substr($msg, 4, 4)); # Example above: FA5E # get Transtmitter Code 2 my $transmittercode2 = uc(substr($msg, 16, 2)); # Example above: 02 # get Key Code my $keycode = uc(substr($msg, 10, 2)); # Example above: 14 $keycodedez = hex $keycode ; # If Keycode > 128 and not equal "long key end" (F7) then Long Key pressure if ($keycode eq "F7") # If end of long keypressure (stop) we need special handling { # ---------------------------------------------------------- $code = uc("$transmittercode1 F7"); $specialkey = "stop"; } else { if ($keycodedez >= 128 && $keycode ne "F7") { # If long key pressure: $keycodedez = ($keycodedez - 128); # --------------------- $specialkey = "long"; $keycode = uc sprintf "%02x", $keycodedez; # %02 damit auch eine "0"... zweistellig wird } $code = uc("$transmittercode1 $keycode"); } my $rhash = $modules{KOPP_FC}{defptr}{$code}; # neu 30.5. rhash war nicht eindeutig # my $rname = $rhash->{NAME}; # $rhash is hash to corresponding device as calculated from receive data Log3 $name, 2, "KOPP_FC_Parse: name: $name code: $code Specialkey:$specialkey"; # kann wieder Raus !!!! ### Claus rname wird müll, da Hash mehrere Namen verlinkt? # rname funktioniert nur wenn $name in Zeile 149/150 nicht angehängt ist # my $tn = TimeNow(); # Look for all devices with the same code, and set state, (timestamp, not yet) # ---------------------------------------------------------------------------- if($rhash) { my @list; foreach my $n (keys %{ $rhash }) { my $lh = $rhash->{$n}; $n = $lh->{NAME}; # It may be renamed, n now contains name of defined device, e.g. Dimmer.... return "" if(IsIgnored($n)); # Little strange. my $oldstate = ReadingsVal($n, "state",""); # # Je nach Model die Aktion triggern. # 3 Key Dimmer: #============== $devicefound=1; # Default: wir kennen das Device if ($attr{$n}{model} && ($attr{$n}{model} eq 'Dimm_8011_00_3Key')) # Wenn Device = 3 Key Dimmer { # ========================== if ($specialkey eq 'short' && $keycode eq $lh->{KEYCODE}) # Taste 1 kurz gedrückt: dann toggeln { # ----------------------------------- if($oldstate eq 'off') {$state = "on";} # off -> on elsif($oldstate eq 'on') {$state = "off";} # on -> off elsif($oldstate eq 'stop') {$state = "off";} # stop -> off else {$state = "on";} # Weder noch? dann Neuer Zustand = on (wird dann wohl aus gewesen sein) } elsif ($specialkey eq "long" && $keycode eq $lh->{KEYCODE}) # Taste 1 lang gedrückt: dann dimmen { # ---------------------------------- $state = "dimm"; } elsif ($specialkey eq "stop") # Ende der lang gedrückten Taste dann dimmen stoppen { # -------------------------------------------------- $state = "stop" if($oldstate eq 'dimm' || $oldstate eq 'stop'); # falls dimmen aktiv war oder bereits gestoppt wurde } elsif ($keycode eq $lh->{KEYCODE2}) {$state = "on";} # Taste 2: (kurz oder lang) -> On elsif ($keycode eq $lh->{KEYCODE3}) {$state = "off";} # Taste 3: (kurz oder lang) -> Off else {} } # 1 Key Dimmer: #============== elsif ($attr{$n}{model} && ($attr{$n}{model} eq 'Dimm_8011_00')) # Wenn Device = 1 Key Dimmer { # ========================== if ($specialkey eq 'short' && $keycode eq $lh->{KEYCODE}) # Taste 1 kurz gedrückt: dann toggeln { # ----------------------------------- if($oldstate eq 'off') {$state = "on";} # off -> on elsif($oldstate eq 'on') {$state = "off";} # on -> off elsif($oldstate eq 'stop') {$state = "off";} # stop -> off else {$state = "on";} # Weder noch? dann Neuer Zustand = on (wird dann wohl aus gewesen sein) } elsif ($specialkey eq "long" && $keycode eq $lh->{KEYCODE}) # Taste 1 lang gedrückt: dann dimmen { # ---------------------------------- $state = "dimm"; } elsif ($specialkey eq "stop") # Ende der lang gedrückten Taste dann dimmen stoppen { # -------------------------------------------------- $state = "stop" if($oldstate eq 'dimm' || $oldstate eq 'stop'); # falls dimmen aktiv war oder bereits gestoppt wurde } } # Blind: #======= elsif ($attr{$n}{model} && ($attr{$n}{model} eq 'Blind_8080_02')) # Wenn Device = Blind/Rolladen { # ============================ if ($specialkey eq 'short' && $keycode eq $lh->{KEYCODE}) # Taste 1 kurz gedrückt: dann Endzustand top/oben anfahren { # -------------------------------------------------------- $state = "top"; # } elsif ($specialkey eq "long" && $keycode eq $lh->{KEYCODE}) # Taste 1 lang gedrückt: dann nach oben fahren (bis zu stop) { # ---------------------------------------------------------- $state = "up"; } if ($specialkey eq 'short' && $keycode eq $lh->{KEYCODE2}) # Taste 2 kurz gedrückt: dann Endzustand bottom/unten anfahren { # ------------------------------------------------------------ $state = "bottom"; # } elsif ($specialkey eq "long" && $keycode eq $lh->{KEYCODE2}) # Taste 2 lang gedrückt: dann nach runter fahren (bis zu stop) { # ----------------------------------------------------------- $state = "down"; } elsif ($specialkey eq "stop") # Ende der lang gedrückten Taste dann Fahrt stoppen { # -------------------------------------------------- $state = "stop" if($oldstate eq 'up' || $oldstate eq 'down' || $oldstate eq 'stop'); # falls fahrt aktiv war oder bereits gestoppt wurde } else {} } # 2 Key Switch: #============== elsif ($attr{$n}{model} && ($attr{$n}{model} eq 'Switch_8080_01_2Key')) # Wenn Device = 2 Key Switch { # ============================== if ($keycode eq $lh->{KEYCODE}) # Taste 1 gedrückt (no matter if short or long) -> State = on { # ----------------------------------------------------------- $state = "on"; # } elsif ($keycode eq $lh->{KEYCODE2}) # Taste 2 gedrückt (no matter if short or long) -> State = off { # ------------------------------------------------------------ $state = "off"; # } else {} } # Für 1 Key Switch und alle anderen Modelle gilt: egal ob kurz oder langer Tastendruck: toggeln zwischen on und off ! # =================================================================================================================== elsif ($specialkey ne 'stop') # Bei Ende der lang gedrückten Taste: nothing to do in this case { if($oldstate eq 'off') {$state = "on";} # off -> on elsif($oldstate eq 'on') {$state = "off";} # on -> off else {$state = "on";} # Weder noch? dann Neuer Zustand = on (wird dann wohl aus gewesen sein) } else # Bei unbekanntem Device/Aktion keine weitere Aktion { $devicefound=0; # das Device ist nicht bekannt } if ($devicefound == 1) # Update Readings if Device/Action found { # Log3 $name, 2, "KOPP_FC_Parse: Model $attr{$n}{model} gefunden "; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, "KOPP_FC_Parse: Code1: $lh->{CODE}{1} "; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, "KOPP_FC_Parse: Code2: $lh->{CODE}{2} "; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, "KOPP_FC_Parse: Code3: $lh->{CODE}{3} "; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, "KOPP_FC_Parse: KeyCode1: $lh->{KEYCODE} "; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, "KOPP_FC_Parse: KeyCode2: $lh->{KEYCODE2} "; # kann wieder Raus !!!! ### Claus # Log3 $name, 2, "KOPP_FC_Parse: KeyCode3: $lh->{KEYCODE3} "; # kann wieder Raus !!!! ### Claus readingsSingleUpdate($lh, "state", $state, 1); # $state mit "" oder ohne? # Log3 $name, 2, "KOPP_FC_Parse lh: $lh n: $n oldstate: $oldstate state: $state"; # kann wieder Raus !!!! ### Claus push(@list, $n); } } return @list; } else { Log3 $name, 2, "KOPP_FC_Parse: Device not defined for message $msg"; } } else { Log3 $name, 2, "$name: KOPP_FC_Parse: nicht gefunden 01 $msg"; # kann wieder Raus !!!! ### Claus return "KOPP_Parse: Command not known"; } } else { DoTrigger($name, "UNKNOWNCODE $msg"); Log3 $name, 2, "$name: KOPP_FC.PM Kopp nicht gefunden 02 $msg"; # kann wieder Raus !!!! ### Claus Log3 $name, 3, "$name: Unknown code $msg, help me [KOPP_FC]!"; return undef; } } # end sub Kopp_FC_Parse ############################### 1; =pod =begin html

Kopp Free Control protocol

=end html =cut