##################################################################### # $Id$ # # The file is part of the SIGNALduino project. # SIGNALduino RSL Modul. Modified version of FHEMduino Modul by Wzut # # 2019 - Ralf9 & Sidey79 # # Supports following devices: # - Conrad RSL ##################################################################### package main; use strict; use warnings; use SetExtensions; my %sets = ( "on" => sub { return $_[0]->{OnCode}; }, "off" => sub { return $_[0]->{OffCode}; } ); my @RSLCodes; # Schiebeschalter/Kanal [I - IV] , Tastenpaar [1 - 4] , an-aus [1 - 0] $RSLCodes[0][0][0] = 0xBE; # ? / ? off $RSLCodes[0][0][1] = 0xB6; # ? / ? on $RSLCodes[1][1][0] = 0x81; # I 1 / off $RSLCodes[1][1][1] = 0x8E; # I 1 / on $RSLCodes[1][2][0] = 0xAE; # I 2 / off $RSLCodes[1][2][1] = 0xA6; # I 2 / on $RSLCodes[1][3][0] = 0x9E; # I 3 / off $RSLCodes[1][3][1] = 0x96; # I 3 / on $RSLCodes[1][4][0] = 0xB5; # I 4 / off - nicht auf 12 Kanal FB $RSLCodes[1][4][1] = 0xB9; # I 4 / on - nicht auf 12 Kanal FB $RSLCodes[2][1][0] = 0x8D; # II 1 / off $RSLCodes[2][1][1] = 0x85; # II 1 / on $RSLCodes[2][2][0] = 0xA5; # II 2 / off $RSLCodes[2][2][1] = 0xA9; # II 2 / on $RSLCodes[2][3][0] = 0x95; # II 3 / off $RSLCodes[2][3][1] = 0x99; # II 3 / on $RSLCodes[2][4][0] = 0xB8; # II 4 / off - nicht auf 12 Kanal FB $RSLCodes[2][4][1] = 0xB0; # II 4 / on - nicht auf 12 Kanal FB $RSLCodes[3][1][0] = 0x84; # III 1 / off $RSLCodes[3][1][1] = 0x88; # III 1 / on $RSLCodes[3][2][0] = 0xA8; # III 2 / off $RSLCodes[3][2][1] = 0xA0; # III 2 / on $RSLCodes[3][3][0] = 0x98; # III 3 / off $RSLCodes[3][3][1] = 0x90; # III 3 / on $RSLCodes[3][4][0] = 0xB2; # III 4 / off - nicht auf 12 Kanal FB $RSLCodes[3][4][1] = 0xBC; # III 4 / on - nicht auf 12 Kanal FB $RSLCodes[4][1][0] = 0x8A; # IV 1 / off $RSLCodes[4][1][1] = 0x82; # IV 1 / on $RSLCodes[4][2][0] = 0xA2; # IV 2 / off $RSLCodes[4][2][1] = 0xAC; # IV 2 / on $RSLCodes[4][3][0] = 0x92; # IV 3 / off $RSLCodes[4][3][1] = 0x9C; # IV 3 / on $RSLCodes[4][4][0] = 0xA3; # IV 4 / off All $RSLCodes[4][4][1] = 0x93; # IV 4 / on All sub SD_RSL_Initialize($) { my ($hash) = @_; $hash->{Match} = "^P1#[A-Fa-f0-9]+"; $hash->{SetFn} = "SD_RSL_Set"; $hash->{DefFn} = "SD_RSL_Define"; $hash->{UndefFn} = "SD_RSL_Undef"; $hash->{AttrFn} = "SD_RSL_Attr"; $hash->{ParseFn} = "SD_RSL_Parse"; $hash->{AttrList} = "IODev RSLrepetition ignore:0,1 ".$readingFnAttributes; $hash->{AutoCreate}= { "RSL.*" => { GPLOT => "", FILTER => "%NAME", autocreateThreshold => "2:30"} }; } ##################################### sub SD_RSL_Define($$) { my ($hash, $def) = @_; my @a = split("[ \t][ \t]*", $def); return "wrong syntax: define SD_RSL " if(int(@a) < 3 || int(@a) > 5); my $name = $a[0]; my ($device,$channel,$button) = split("_",$a[2]); if ($channel eq "ALL") { $channel = 4; $button = 4; } return "wrong syntax: use channel 1 - 4" if(($channel > 4)); # || ($channel < 1 )); return "wrong syntax: use button 1 - 4" if(($button > 4)); # || ($button < 1)); return "wrong syntax: use code 000000 - FFFFFF" if (length($device) != 6); return "wrong Device Code $device , please use 000000 - FFFFFF" if ((hex($device) < 0) || (hex($device) > 16777215)); my $code = uc($a[2]); $hash->{DEF} = $code; $modules{SD_RSL}{defptr}{$code} = $hash; $modules{SD_RSL}{defptr}{$code}{$name} = $hash; # code auf 32Bit umrechnen int 16777216 = 0x1000000 #$hash->{OnCode} = ($RSLCodes[$channel][$button][1]*16777216) + hex($device); #$hash->{OffCode} = ($RSLCodes[$channel][$button][0]*16777216) + hex($device); $hash->{OnCode} = sprintf('%02X', ($RSLCodes[$channel][$button][1])); $hash->{OffCode} = sprintf('%02X', ($RSLCodes[$channel][$button][0])); my $iodevice; $iodevice = $a[3] if($a[3]); $iodevice = $modules{SD_RSL}{defptr}{ioname} if (exists $modules{SD_RSL}{defptr}{ioname} && not $iodevice); AssignIoPort($hash, $iodevice); return undef; } ########################################################## sub SD_RSL_Set($@) { my ($hash, $name, @a) = @_; my $cmd = $a[0]; return "\"set $name\" needs at least one argument" unless(defined($cmd)); my $cmdList= join(" ", map { "$_:noArg" } sort keys %sets); if (exists($sets{$cmd})) { my $ioHash = $hash->{IODev}; my $ioName = $ioHash->{NAME}; my $device = substr($hash->{DEF},0,6); my $c= $sets{$cmd}->($hash,@a); my $message = 'P1#0x' . $c . $device . '#R' . AttrVal($name, "RSLrepetition", 6); Log3 $name, 3, "$ioName RSL_set: $name $cmd -> sendMsg: $message"; IOWrite($hash, 'sendMsg', $message); readingsSingleUpdate($hash,"state",$cmd,1); } else { return SetExtensions($hash, $cmdList, $name, @a) } return undef; } ################################################################### sub RSL_getButtonCode($$) { my ($hash,$msg) = @_; my $name = $hash->{NAME}; my $DeviceCode = "undef"; my $receivedButtonCode = "undef"; my $receivedActionCode = "undef"; my $parsedButtonCode = "undef"; my $action = "undef"; my $button = -1; my $channel = -1; ## Groupcode $DeviceCode = substr($msg,2,6); $receivedButtonCode = substr($msg,0,2); Log3 $hash, 4, "$name: SD_RSL_getButtonCode Message Devicecode: $DeviceCode Buttoncode: $receivedButtonCode"; if ((hex($receivedButtonCode) & 0xc0) != 0x80) { Log3 $hash, 4, "$name: SD_RSL_getButtonCode Message Error: received Buttoncode $receivedButtonCode begins not with bin 10"; return ""; } $parsedButtonCode = hex($receivedButtonCode); # & 63; # nur 6 Bit bitte Log3 $hash, 5, "$name: SD_RSL_getButtonCode Message parsed Devicecode: $DeviceCode Buttoncode: $parsedButtonCode"; for (my $i=0; $i<5; $i++) { for (my $j=0; $j<5; $j++) { next if ($i == 0 && $j != 0); next if ($i != 0 && $j == 0); if ($RSLCodes[$i][$j][0] == $parsedButtonCode) {$action ="off"; $button = $j; $channel = $i;} if ($RSLCodes[$i][$j][1] == $parsedButtonCode) {$action ="on"; $button = $j; $channel = $i;} } } if (($button >-1) && ($channel > -1)) { Log3 $hash, 4, "$name: SD_RSL_getButtonCode button return/result: ID: $DeviceCode $receivedButtonCode DEVICE: $DeviceCode $channel $button ACTION: $action"; if ($channel == 4 && $button == 4) { return $DeviceCode."_ALL ".$action; } else { return $DeviceCode."_".$channel."_".$button." ".$action; } } return ""; } ######################################################## sub SD_RSL_Parse($$) { my ($hash,$msg) = @_; my $name = $hash->{NAME}; my (undef ,$rawData) = split("#",$msg); Log3 $hash, 4, "$name: SD_RSL_Parse - Message: $rawData"; my $result = RSL_getButtonCode($hash,$rawData); if ($result ne "") { my ($deviceCode,$action) = split m/ /, $result, 2; Log3 $hash, 4, "$name: SD_RSL_Parse - Device: $deviceCode Action: $action"; $modules{SD_RSL}{defptr}{ioname} = $name; my $def = $modules{SD_RSL}{defptr}{$hash->{NAME} . "." . $deviceCode}; $def = $modules{SD_RSL}{defptr}{$deviceCode} if(!$def); if(!$def) { Log3 $hash, 3, "$name: SD_RSL_Parse UNDEFINED Remotebutton send to define: $deviceCode"; return "UNDEFINED RSL_$deviceCode SD_RSL $deviceCode"; } $hash = $def; my $name = $hash->{NAME}; return "" if(IsIgnored($name)); if(!$action) { Log3 $name, 5, "$name: SD_RSL_Parse - can't decode $msg"; return ""; } Log3 $name, 5, "$name: SD_RSL_Parse - actioncode: $action"; #if (($action eq "on") && ($hash->{STATE} eq "off")){$action = "stop";} #if (($action eq "off") && ($hash->{STATE} eq "on")) {$action = "stop";} #$hash->{CHANGED}[0] = $action; #$hash->{STATE} = $action; readingsSingleUpdate($hash,"state",$action,1); return $name; } return ""; } ######################################################## sub SD_RSL_Undef($$) { my ($hash, $name) = @_; SetExtensionsCancel($hash); delete($modules{SD_RSL}{defptr}{$hash->{DEF}}) if($hash && $hash->{DEF}); return undef; } ######################################################## sub SD_RSL_Attr(@) { my @a = @_; # Make possible to use the same code for different logical devices when they # are received through different physical devices. return if($a[0] ne "set" || $a[2] ne "IODev"); my $hash = $defs{$a[1]}; my $iohash = $defs{$a[3]}; my $cde = $hash->{DEF}; delete($modules{SD_RSL}{defptr}{$cde}); $modules{SD_RSL}{defptr}{$iohash->{NAME} . "." . $cde} = $hash; return undef; } 1; =pod =item summary devices communicating using the Conrad RSL protocol =item summary_DE Anbindung von Conrad RSL Geräten =begin html

SD_RSL

The SD_RSL module decrypts and creates Conrad RSL messages sent / received by a SIGNALduino device.
If autocreate is used, a device "<code>_ALL" like RSL_74A400_ALLis created instead of channel and button = 4.

Define

    define <name> SD_RSL <code>_<channel>[_<button>] <optional IODEV>

    <name> is any name assigned to the device. For a better overview it is recommended to use a name in the form "RSL_B1A800_1_2"

    <code> The code is 00000-FFFFFF

    <channel> The channel is 1-4 or ALL

    <button> The button is 1-4

Set
    set <[on|off|toggle]>
    Switches the device on or off.

    set <[on-for-timer|off-for-timer|on-till|off-till|blink|intervals]>
    Switches the socket for a specified duration. For Details see set extensions.



Get
    N/A

Attribute =end html =begin html_DE

SD_RSL

Das SD_RSL-Modul decodiert und erstellt Conrad-RSL-Nachrichten, die vom SIGNALduino gesendet bzw. empfangen werden.
Beim Verwendung von Autocreate wird bei der Taste All anstatt channel und button = 4 "<code>_ALL" angelegt, z.B. RSL_74A400_ALL

Define

    define <name> SD_RSL <code>_<channel>[_<button>] <optional IODEV>

    <name> ist ein Name, der dem Gerät zugewiesen ist. Zur besseren Übersicht wird empfohlen, einen Namen in dieser Form zu verwenden "RSL_B1A800_1_2"

    <code> Der Code ist 00000-FFFFFF

    <channel> Der Kanal ist 1-4 oder ALL

    <button> Der Knopf ist 1-4

Set
    set <[on|off|toggle]>

    set <[on-for-timer|off-for-timer|on-till|off-till|blink|intervals]>
    Schaltet das Gerät für einen bestimmten Zeitraum. Weitere Infos hierzu unter set extensions.



Get
    N/A

Attribute =end html_DE =cut