diff --git a/fhem/FHEM/38_Broadlink.pm b/fhem/FHEM/38_Broadlink.pm new file mode 100644 index 000000000..e6470ea90 --- /dev/null +++ b/fhem/FHEM/38_Broadlink.pm @@ -0,0 +1,765 @@ +#original script by https://github.com/mjg59/python-broadlink +#some parts by 31_LightScene.pm +# $Id$ +package main; +use strict; +use warnings; +use integer; +use Time::Local; +use IO::Socket::INET; +use IO::Select; + +#use Crypt::CBC; +#use Crypt::OpenSSL::AES; +#use MIME::Base64; +#use Data::Dump qw(dump); + +my $broadlink_hasJSON = 1; +my $broadlink_hasDataDumper = 1; +my $broadlink_hasCBC = 1; +my $broadlink_hasAES = 1; +my $broadlink_hasBase64 = 1; + +sub Broadlink_Initialize($) { + my ($hash) = @_; + + $hash->{DefFn} = 'Broadlink_Define'; + $hash->{UndefFn} = 'Broadlink_Undef'; + $hash->{SetFn} = 'Broadlink_Set'; + + $hash->{AttrList} = 'socket_timeout:0.5,1,1.5,2,2.5,3,4,5,10 ' . $readingFnAttributes; + eval "use JSON"; + $broadlink_hasJSON = 0 if($@); + + eval "use Data::Dumper"; + $broadlink_hasDataDumper = 0 if($@); + + eval "use Crypt::CBC"; + $broadlink_hasCBC = 0 if($@); + + eval "use Crypt::OpenSSL::AES"; + $broadlink_hasAES = 0 if($@); + + eval "use MIME::Base64"; + $broadlink_hasBase64 = 0 if($@); + +} + +sub Broadlink_Define($$) { + my ($hash, $def) = @_; + my @param = split('[ \t]+', $def); + + return "install Crypt::CBC to use Broadlink" if( !$broadlink_hasCBC); + return "install Crypt::OpenSSL::AES to use Broadlink" if( !$broadlink_hasAES); + return "install MIME::Base64 to use Broadlink" if( !$broadlink_hasBase64); + return "install JSON (or Data::Dumper) to use Broadlink" if( !$broadlink_hasJSON && !$broadlink_hasDataDumper ); + + if(int(@param) <= 4) { + return "wrong syntax: define Broadlink "; + } + + $hash->{ip} = $param[2]; + $hash->{mac} = $param[3]; + $hash->{devtype} = $param[4]; + $hash->{'.key'} = pack('C*', 0x09, 0x76, 0x28, 0x34, 0x3f, 0xe9, 0x9e, 0x23, 0x76, 0x5c, 0x15, 0x13, 0xac, 0xcf, 0x8b, 0x02); + $hash->{'.iv'} = pack('C*', 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58); + $hash->{'.id'} = pack('C*', 0, 0, 0, 0); + $hash->{counter} = 1; + $hash->{isAuthenticated} = 0; + if ($hash->{devtype} eq 'sp3') { #steckdose + Broadlink_auth($hash); + if ($hash->{isAuthenticated} != 0) { + Broadlink_sp3_getStatus($hash, 1); + } + } else { + $hash->{commandList} = (); + Broadlink_Load($hash); + } + + return undef; +} + +sub Broadlink_Undef($$) { + my ($hash, $arg) = @_; + # nothing to do + return undef; +} + +sub Broadlink_Get($@) { + my ($hash, @param) = @_; + + return undef; +} + +sub Broadlink_Set(@) { + my ($hash, $name, $cmd, @args) = @_; + if ($hash->{devtype} eq 'sp3') { #steckdose + if ($cmd eq 'on') { + Broadlink_auth($hash); + if ($hash->{isAuthenticated} != 0) { + Broadlink_sp3_setPower($hash, 1); + } + return undef; + } elsif ($cmd eq 'off') { + Broadlink_auth($hash); + if ($hash->{isAuthenticated} != 0) { + Broadlink_sp3_setPower($hash, 0); + } + return undef; + } elsif ($cmd eq 'toggle') { + Broadlink_auth($hash); + if ($hash->{isAuthenticated} != 0) { + if ($hash->{STATE} eq 'unknown') { + Broadlink_sp3_getStatus($hash); + } + if ($hash->{STATE} eq 'on') { + Broadlink_sp3_setPower($hash, 0); + } else { + Broadlink_sp3_setPower($hash, 1); + } + } + return undef; + } elsif ($cmd eq 'getStatus') { + Broadlink_auth($hash); + if ($hash->{isAuthenticated} != 0) { + Broadlink_sp3_getStatus($hash); + } + return undef; + } else { + return "Unknown argument $cmd, choose one of on off toggle getStatus"; + } + return "$cmd. Try to get it."; + } else { #rmpro rmmini etc. + if ($cmd eq 'recordNewCommand') { + Broadlink_auth($hash); + my $cmdname = $args[0]; + if ($cmdname eq "") { + return "Please specify commandname to record set recordNewCommand "; + } + #if ($cmdname =~ /#|'|"|\/|\\|,/) { + # return "it is not allowed to use #,',\",\/,\\ or comma in commandname"; + #} + if ($cmdname =~ /^[A-Z_a-z0-9\+\-]+$/) { + $hash->{STATE} = "learning new command"; + if ($hash->{isAuthenticated} != 0) { + Broadlink_enterLearning($hash, $cmdname); + } + } else { + return "only A-Z, a-z, 0-9, _, +, - are allowed in commandname"; + } + return undef; + } elsif ($cmd eq 'commandSend') { + Broadlink_auth($hash); + my $cmdname = $args[0]; + if(!$hash->{commandList}{$cmdname}) { + return "Unknown command $cmdname, choose an existing one or record a new one"; + } + $hash->{STATE} = "send command:" . $cmdname; + if ($hash->{isAuthenticated} != 0) { + Broadlink_send_data($hash, decode_base64($hash->{commandList}{$cmdname}), $cmdname); + } + return undef; + } elsif ($cmd eq 'rename') { + my $cmdname = $args[0]; + my $newCmdname = $args[1]; + if ($cmdname eq "" or $newCmdname eq "") { + return "Command wrong use set rename "; + } + if(!$hash->{commandList}{$cmdname}) { + return "Unknown command $cmdname, choose an existing one"; + } + if ($newCmdname =~ /^[A-Z_a-z0-9\+\-]+$/) { + Broadlink_Load($hash); + $hash->{commandList}{$newCmdname} = $hash->{commandList}{$cmdname}; + delete($hash->{commandList}{$cmdname}); + Broadlink_Save($hash); + } else { + return "only A-Z, a-z, 0-9, _, +, - are allowed in commandname"; + } + return undef; + } elsif ($cmd eq 'remove') { + my $cmdname = $args[0]; + if(!$hash->{commandList}{$cmdname}) { + return "Unknown command $cmdname, choose an existing one"; + } + Broadlink_Load($hash); + delete($hash->{commandList}{$cmdname}); + Broadlink_Save($hash); + return undef; + } else { + #sort with ignore case + my $commandList = join(",", sort { + lc $a cmp lc $b + || $a cmp $b + } keys %{$hash->{commandList}}); + #return "Unknown argument $cmd, choose one of learnNewCommand sendCommand sendCommandBase64 sendCommandHex createCommandBase64 createCommandHex"; + return "Unknown argument $cmd, choose one of recordNewCommand rename remove:" . $commandList . " commandSend:". $commandList; + } + return "$cmd. Try to get it."; + } +} + +sub Broadlink_send_data(@) { + my ($hash, $dataToSend, $cmdname) = @_; + my @broadlink_payload = ((0) x 4); + $broadlink_payload[0] = 2; + my @values = split(//,$dataToSend); + foreach my $val (@values) { + push @broadlink_payload, unpack("C*", $val); + } + my $msg = "Try to send a command: " . $cmdname; + Log3 $hash->{NAME}, 5, $msg; + my $response = Broadlink_send_packet($hash, 0x6a, @broadlink_payload); + if (length($response) > 0 && $response ne "xxx") { + readingsSingleUpdate ( $hash, "lastCommandSend", $cmdname, 1 ); + my $msg = $cmdname ." send"; + Log3 $hash->{NAME}, 5, $msg; + } else { + readingsSingleUpdate ( $hash, "connectionErrorOn", "sendCommand: " . $cmdname, 1 ); + my $msg = $cmdname . " command send failed - device not connected?"; + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = $msg; + } +} + +sub Broadlink_check_data(@) { + my ($hash) = @_; + my @broadlink_payload = ((0) x 16); + $broadlink_payload[0] = 4; + my $msg = "check for new command"; + Log3 $hash->{NAME}, 5, $msg; + my $data = Broadlink_send_packet($hash, 0x6a, @broadlink_payload); + #length must be bigger than 0x38, if not, cant get substring with data + if (length($data) > 0x38 && $data ne "xxx") { + my $err = unpack("C*", substr($data, 0x22, 1)) | (unpack("C*", substr($data, 0x23, 1)) << 8); + if ($err == 0) { + my $msg = "new command found"; + Log3 $hash->{NAME}, 5, $msg; + my $enc_payload = substr($data, 0x38); + my $cipher = Broadlink_getCipher($hash); + my $decodedData = $cipher->decrypt($enc_payload); + $hash->{STATE} = "new Command learned: " . $hash->{'.newcommandname'}; + readingsSingleUpdate ( $hash, "lastRecordedCommand", $hash->{'.newcommandname'}, 1 ); + #frist load it again, if more than one device is defined + Broadlink_Load($hash); + $hash->{commandList}{$hash->{'.newcommandname'}} = encode_base64(substr($decodedData, 4)); + Broadlink_Save($hash); + return substr($decodedData, 4); + } else { + my $msg = "Error receiving command"; + Log3 $hash->{NAME}, 5, $msg; + } + } else { + my $msg = "no new command data found - data length: " . length($data); + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = $msg; + } + $hash->{'.broadlink_checkCommands'}++; + if ($hash->{'.broadlink_checkCommands'} < 15) { + my $msg = "no command recorded. retry count:" . $hash->{'.broadlink_checkCommands'}; + Log3 $hash->{NAME}, 5, $msg; + InternalTimer(gettimeofday()+2, "Broadlink_check_data", $hash); + } else { + my $msg = "no command recorded even after a lot of retries. Try to learn again"; + Log3 $hash->{NAME}, 3, $msg; + $hash->{STATE} = $msg; + readingsSingleUpdate ( $hash, "lastFailedRecordedCommand", $hash->{'.newcommandname'}, 1 ); + } +} + + +sub Broadlink_sp3_getStatus(@) { + my ($hash) = @_; + my @broadlink_payload = ((0) x 16); + $broadlink_payload[0] = 1; + my $msg = "sp3_status request"; + Log3 $hash->{NAME}, 5, $msg; + my $data = Broadlink_send_packet($hash, 0x6a, @broadlink_payload); + #length must be bigger than 0x38, if not, cant get substring with data + if (length($data) > 0x38 && $data ne "xxx") { + my $err = unpack("C*", substr($data, 0x22, 1)) | (unpack("C*", substr($data, 0x23, 1)) << 8); + if ($err == 0) { + my $msg = "sp3 receiving status - data length: " . length($data); + Log3 $hash->{NAME}, 1, $msg; + my $enc_payload = substr($data, 0x38); + my $cipher = Broadlink_getCipher($hash); + my $decodedData = $cipher->decrypt($enc_payload); + if (unpack("C*", substr($decodedData, 4, 1)) eq 0) { + $hash->{STATE} = "off"; + } else { + $hash->{STATE} = "on"; + } + } else { + my $msg = "Error receiving status"; + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = "unknown"; + readingsSingleUpdate ( $hash, "connectionErrorOn", "geStatusWithData", 1 ); + } + } else { + my $msg = "no new command data found - data length: " . length($data); + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = "unknown"; + readingsSingleUpdate ( $hash, "connectionErrorOn", "geStatus", 1 ); + } +} + + +sub Broadlink_sp3_setPower(@) { + my ($hash, $on) = @_; + my @broadlink_payload = ((0) x 16); + $broadlink_payload[0] = 2; + if ($on == 1) { + $broadlink_payload[4] = 1; + } else { + $broadlink_payload[4] = 0; + } + my $msg = "sp3_status request"; + Log3 $hash->{NAME}, 5, $msg; + my $data = Broadlink_send_packet($hash, 0x6a, @broadlink_payload); + if (length($data) > 0 && $data ne "xxx") { + if ($on == 1) { + $hash->{STATE} = "on"; + } else { + $hash->{STATE} = "off"; + } + } else { + readingsSingleUpdate ( $hash, "connectionErrorOn", "powerChange", 1 ); + my $msg = "powerChange - device not connected?"; + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = "unkown"; + } +} + +sub Broadlink_enterLearning(@) { + my ($hash, $cmdname) = @_; + my @broadlink_payload = ((0) x 16); + $broadlink_payload[0] = 3; + my $msg = "learn new commadn for " . $cmdname; + Log3 $hash->{NAME}, 5, $msg; + my $data = Broadlink_send_packet($hash, 0x6a, @broadlink_payload); + if (length($data) > 0 && $data ne "xxx") { + $hash->{'.broadlink_checkCommands'} = 0; + $hash->{'.newcommandname'} = $cmdname; + my $msg = "start polling for " . $cmdname; + Log3 $hash->{NAME}, 5, $msg; + InternalTimer(gettimeofday()+2, "Broadlink_check_data", $hash); + } else { + readingsSingleUpdate ( $hash, "connectionErrorOn", "enterLearning", 1 ); + my $msg = "command learn failed - device not connected?"; + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = $msg; + } +} + +sub Broadlink_auth(@) { + my ($hash) = @_; + #never authenticate again, if not needed + if ($hash->{isAuthenticated} == 0) { + my @broadlink_payload = ((0) x 80); + $broadlink_payload[0x04] = 0x31; + $broadlink_payload[0x05] = 0x31; + $broadlink_payload[0x06] = 0x31; + $broadlink_payload[0x07] = 0x31; + $broadlink_payload[0x08] = 0x31; + $broadlink_payload[0x09] = 0x31; + $broadlink_payload[0x0a] = 0x31; + $broadlink_payload[0x0b] = 0x31; + $broadlink_payload[0x0c] = 0x31; + $broadlink_payload[0x0d] = 0x31; + $broadlink_payload[0x0e] = 0x31; + $broadlink_payload[0x0f] = 0x31; + $broadlink_payload[0x10] = 0x31; + $broadlink_payload[0x11] = 0x31; + $broadlink_payload[0x12] = 0x31; + $broadlink_payload[0x1e] = 0x01; + $broadlink_payload[0x2d] = 0x01; + $broadlink_payload[0x30] = ord('T'); + $broadlink_payload[0x31] = ord('e'); + $broadlink_payload[0x32] = ord('s'); + $broadlink_payload[0x33] = ord('t'); + $broadlink_payload[0x34] = ord(' '); + $broadlink_payload[0x35] = ord(' '); + $broadlink_payload[0x36] = ord('1'); + + my $msg = "try to authenticate"; + Log3 $hash->{NAME}, 5, $msg; + my $response = Broadlink_send_packet($hash, 0x65, @broadlink_payload); + if (length($response) > 0x38 && $response ne "xxx") { + my $enc_payload = substr($response, 0x38); + my $cipher = Broadlink_getCipher($hash); + my $broadlink_payload = $cipher->decrypt($enc_payload); + #authentication worked + $hash->{'.key'} = substr($broadlink_payload, 0x04, 16); + $hash->{'.id'} = substr($broadlink_payload, 0, 4); + $hash->{isAuthenticated} = 1; + } else { + readingsSingleUpdate ( $hash, "lastAuthenticationFailed", "", 1 ); + my $msg = "authentication failed - device not connected? - response length: " . length($response); + Log3 $hash->{NAME}, 4, $msg; + $hash->{STATE} = $msg; + } + } +} + +sub Broadlink_getCipher(@) { + my ($hash) = @_; + return Crypt::CBC->new( + -key => $hash->{'.key'}, + -cipher => "Crypt::OpenSSL::AES", + -header => "none", + -iv => $hash->{'.iv'}, + -literal_key => 1, + -keysize => 16, + -padding => 'space' + ); +} + +sub Broadlink_send_packet(@) { + my ($hash,$command,@broadlink_payload) = @_; + + #prepare header of packet + $hash->{counter} = ($hash->{counter} + 1) & 0xffff; + + my @broadlink_id = split(//,$hash->{'.id'}); + my @broadlink_mac = split ':', $hash->{mac}; + + my @packet = (0) x 56; + $packet[0x00] = 0x5a; + $packet[0x01] = 0xa5; + $packet[0x02] = 0xaa; + $packet[0x03] = 0x55; + $packet[0x04] = 0x5a; + $packet[0x05] = 0xa5; + $packet[0x06] = 0xaa; + $packet[0x07] = 0x55; + $packet[0x24] = 0x2a; + $packet[0x25] = 0x27; + $packet[0x26] = $command; + $packet[0x28] = $hash->{counter} & 0xff; + $packet[0x29] = $hash->{counter} >> 8; + $packet[0x2a] = unpack('H', $broadlink_mac[0]); + $packet[0x2b] = unpack('H', $broadlink_mac[1]); + $packet[0x2c] = unpack('H', $broadlink_mac[2]); + $packet[0x2d] = unpack('H', $broadlink_mac[3]); + $packet[0x2e] = unpack('H', $broadlink_mac[4]); + $packet[0x2f] = unpack('H', $broadlink_mac[5]); + + $packet[0x30] = unpack('C', $broadlink_id[0]); + $packet[0x31] = unpack('C', $broadlink_id[1]); + $packet[0x32] = unpack('C', $broadlink_id[2]); + $packet[0x33] = unpack('C', $broadlink_id[3]); + + #calculate payload checksum of original data + my $checksum = 0xbeaf; + my $arrSize = @broadlink_payload; + for(my $i = 0; $i < $arrSize; $i++) { + $checksum += $broadlink_payload[$i]; + $checksum = $checksum & 0xffff; + } + #put the checksum of payload in the header info + $packet[0x34] = $checksum & 0xff; + $packet[0x35] = $checksum >> 8; + + #crypt payload + my $cipher = Broadlink_getCipher($hash); + my $payloadCrypt = $cipher->encrypt(pack('C*', @broadlink_payload)); + + #add the crypted data to packet + my @values = split(//,$payloadCrypt); + foreach my $val (@values) { + push @packet, unpack("C*", $val); + } + + #create checksum of whole packet + $checksum = 0xbeaf; + $arrSize = @packet; + for(my $i = 0; $i < $arrSize; $i++) { + $checksum += $packet[$i]; + $checksum = $checksum & 0xffff; + } + #put the checksum of whole packet in the header info + $packet[0x20] = $checksum & 0xff; + $packet[0x21] = $checksum >> 8; + + #errorvalue if no data received + my $data = "xxx"; + my $timeout = AttrVal($hash->{NAME}, 'socket_timeout', 3.0); + eval { + local $SIG{ALRM} = sub { die 'Timed Out'; }; + alarm $timeout; + + #send udp packet + my $socket = IO::Socket::INET->new( + Proto => 'udp', + PeerAddr => $hash->{ip}, + PeerPort => '80', + ReuseAddr => 1, + Timeout => $timeout, + #Blocking => 0 + ) or Log3 $hash->{NAME}, 5, "Problem with socket"; + + my $select = IO::Select->new($socket) if $socket; + + + #$socket->autoflush; + $socket->send(pack('C*',@packet)); + #IO::Select->select($select, undef, undef, 3); + if ($select->can_read($timeout)) { + $socket->recv($data, 1024); + } else { + Log3 $hash->{NAME}, 5, "can't read"; + } + $socket->close(); + alarm 0; + }; + alarm 0; # race condition protection + Log3 $hash->{NAME}, 3, 'Error Timout' if ( $@ && $@ =~ /Timed Out/ ); + Log3 $hash->{NAME}, 3, "Error: Eval corrupted: $@" if $@; + Log3 $hash->{NAME}, 5, length($data) . " bytes received from socket"; + return $data; +} + +#lightscene Copy +sub Broadlink_statefileName() { + my $statefile = $attr{global}{statefile}; + $statefile = substr $statefile,0,rindex($statefile,'/')+1; + return $statefile ."broadlink.save" if( $broadlink_hasJSON ); + return $statefile ."broadlink.dd.save" if( $broadlink_hasDataDumper ); +} + +sub Broadlink_Save(@) { + my ($hash) = @_; + my $time_now = TimeNow(); + + return "No statefile specified" if(!$attr{global}{statefile}); + my $statefile = Broadlink_statefileName(); + + my $commandList = $hash->{commandList}; + + if(open(FH, ">$statefile")) { + my $t = localtime; + print FH "#$t\n"; + + if( $broadlink_hasJSON ) { + print FH encode_json($commandList) if( defined($commandList) ); + } elsif( $broadlink_hasDataDumper ) { + my $dumper = Data::Dumper->new([]); + $dumper->Terse(1); + + $dumper->Values([$commandList]); + print FH $dumper->Dump; + } + + close(FH); + } else { + + my $msg = "Broadlink_Save: Cannot open $statefile: $!"; + Log3 $hash->{NAME}, 1, $msg; + } + + return undef; +} + +sub Broadlink_Load(@) { + my ($hash) = @_; + + return "No statefile specified" if(!$attr{global}{statefile}); + my $statefile = Broadlink_statefileName(); + + if(open(FH, "<$statefile")) { + my $encoded; + while (my $line = ) { + chomp $line; + next if($line =~ m/^#.*$/); + $encoded .= $line; + } + close(FH); + + return if( !defined($encoded) ); + + my $decoded; + if( $broadlink_hasJSON ) { + $decoded = decode_json( $encoded ); + } elsif( $broadlink_hasDataDumper ) { + $decoded = eval $encoded; + } + $hash->{commandList} = $decoded; + } else { + my $msg = "Broadlink_Load: Cannot open $statefile: $!"; + Log3 $hash->{NAME}, 1, $msg; + } + return undef; +} + +1; + +=pod +=item device +=item summary implements a connection to Broadlink devices +=item summary_DE implementiert die Verbindung zu Broadlink Geräten +=begin html + + +

Broadlink

+
    + Broadlink implements a connection to Broadlink devices - currently tested with Broadlink RM Pro, which is able to send IR and 433MHz commands. It is also able to record this commands. +
    + It requires AES encryption please install on Windows:
    + ppm install Crypt-CBC
    + ppm install Crypt-OpenSSL-AES

    + or Linux/Raspberry: + sudo apt-get install libcrypt-cbc-perl
    + sudo apt-get install libcrypt-rijndael-perl
    + sudo cpan Crypt/OpenSSL/AES.pm
    +

    + + Define +
      + define <name> Broadlink <ip/host> <mac> <type=rmpro or sp3> +

      + Example: define broadlinkWZ Broadlink 10.23.11.85 34:EA:34:F4:77:7B rmpro +

      + The mac of the device have to be set in format: xx:xx:xx:xx:xx
      + The type is in current development state optional. +
    +
    + + + Set for rmpro
    +
      +
    • set <name> <commandSend> <command name> +

      + Send a previous recorded command. +
    • +
    • set <name> recordNewCommand <command name> +

      + Records a new command. You have to specify a commandname +
    • +
    • + set <name> remove <command name> +

      + Removes a recored command. +
    • +
    • + set <name> rename <old command name> <new command name> +

      + Renames a recored command. +
    • +
    +
    + Set for sp3
    +
      +
    • set <name> on +

      + Set the device on +
    • +
    • set <name> off +

      + Set the device off +
    • +
    • set <name> toggle +

      + Toggle the device on and off +
    • +
    • set <name> getStatus +

      + Get the device on/off status +
    • +
    +
    + + Attributes for all Broadlink Devices
    +
      +
    • socket_timeout +

      + sets a timeout for the device communication +
    • +
    +
    +
+ +=end html +=begin html_DE + + +

Broadlink

+
    + Broadlink implementiert die Verbindung zu Broadlink Geräten - aktuell mit Broadlink RM Pro, welcher sowohl Infrarot als auch 433MHz aufnehmen und anschließend versenden kann. +
    + Das Modul benötigt AES-Verschlüsslung.
    + In Windows installiert man die Untersützung mit:
    + ppm install Crypt-CBC
    + ppm install Crypt-OpenSSL-AES

    + Auf Linux/Raspberry: + sudo apt-get install libcrypt-cbc-perl
    + sudo apt-get install libcrypt-rijndael-perl
    + sudo cpan Crypt/OpenSSL/AES.pm
    +

    + + Define +
      + define <name> Broadlink <ip/host> <mac> <type=rmpro or sp3> +

      + Beispiel: define broadlinkWZ Broadlink 10.23.11.85 34:EA:34:F4:77:7B rmpro +

      + Die mac-Adresse des Gerätes muss im folgenden Format eingegeben werden: xx:xx:xx:xx:xx
      + Der Typ sp3 wird für schaltbare Steckdosen genutzt. rmpro für alle anderen Geräte. +
    +
    + + + Set für rmpro
    +
      +
    • set <name> <commandSend> <command name> +

      + Sendet ein vorher aufgenommenen Befehl +
    • +
    • set <name> recordNewCommand <command name> +

      + Nimmt ein neuen Befehl auf. Man muss einen Befehlnamen angeben. +
    • +
    • + set <name> remove <command name> +

      + Löscht einen vorher aufgezeichneten Befehl. +
    • +
    • + set <name> rename <old command name> <new command name> +

      + Benennt einen vorher aufgezeichneten Befehl um. +
    • +
    +
    + Set für sp3
    +
      +
    • set <name> on +

      + Schaltet das Gerät an. +
    • +
    • set <name> off +

      + Schaltet das Gerät aus. +
    • +
    • set <name> toggle +

      + Schaltet das Gerät entweder ein oder aus. +
    • +
    • set <name> getStatus +

      + Ermittelt den aktuellen Status des Gerätes. +
    • +
    +
    + + Attribute für alle Broadlink Gräte
    +
      +
    • socket_timeout +

      + Setzt den Timeout für die Gerätekommunikation. +
    • +
    +
    +
+ +=end html_DE +=cut \ No newline at end of file