diff --git a/fhem/CHANGED b/fhem/CHANGED index 798e17780..f728b73e7 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,9 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - change: 74_AMADDevice: change to perl packages, add Meta and Installer + Support + - change: 73_AMADCommBridge: change to perl packages, add Meta and Installer + Support - change: 49_SSCam: delay FHEM shutdown as long as sessions are not terminated, add Meta.pm support - feature: 30_HUEBridge: added schedules (by PPP01) diff --git a/fhem/FHEM/73_AMADCommBridge.pm b/fhem/FHEM/73_AMADCommBridge.pm index d47564621..7808131f5 100644 --- a/fhem/FHEM/73_AMADCommBridge.pm +++ b/fhem/FHEM/73_AMADCommBridge.pm @@ -1,5 +1,5 @@ ############################################################################### -# +# # Developed with Kate # # (c) 2015-2019 Copyright: Marko Oldenburg (leongaultier at gmail dot com) @@ -36,7 +36,7 @@ # # if($@){ # Log3($SELF, 2, "$TYPE ($SELF) - error while request: $@"); -# +# # readingsSingleUpdate($hash, "state", "error", 1); # # return; @@ -58,939 +58,1157 @@ ## ## - - package main; - -my $missingModul = ""; - use strict; use warnings; +use FHEM::Meta; -use HttpUtils; -use TcpServerUtils; - -eval "use Encode qw(encode encode_utf8);1" or $missingModul .= "Encode "; -eval "use JSON;1" or $missingModul .= "JSON "; - - - -my $modulversion = "4.2.3"; -my $flowsetversion = "4.2.5"; - - - - -# Declare functions -sub AMADCommBridge_Attr(@); -sub AMADCommBridge_Open($); -sub AMADCommBridge_Read($); -sub AMADCommBridge_Define($$); -sub AMADCommBridge_Initialize($); -sub AMADCommBridge_Set($@); -sub AMADCommBridge_Write($@); -sub AMADCommBridge_Undef($$); -sub AMADCommBridge_ResponseProcessing($$); -sub AMADCommBridge_Close($); -sub AMADCommBridge_ErrorHandling($$$); -sub AMADCommBridge_ProcessRead($$); -sub AMADCommBridge_ParseMsg($$); - - - +my $modulversion = '4.4.0'; +my $flowsetversion = '4.4.0'; sub AMADCommBridge_Initialize($) { my ($hash) = @_; - # Provider - $hash->{ReadFn} = "AMADCommBridge_Read"; - $hash->{WriteFn} = "AMADCommBridge_Write"; - $hash->{Clients} = ":AMADDevice:"; - $hash->{MatchList} = { "1:AMADDevice" => '{"amad": \{"amad_id":.+}}' }; - - + $hash->{ReadFn} = 'FHEM::AMADCommBridge::Read'; + $hash->{WriteFn} = 'FHEM::AMADCommBridge::Write'; + $hash->{Clients} = ':AMADDevice:'; + $hash->{MatchList} = { "1:AMADDevice" => '{"amad": \{"amad_id":.+}}' }; + # Consumer - $hash->{SetFn} = "AMADCommBridge_Set"; - $hash->{DefFn} = "AMADCommBridge_Define"; - $hash->{UndefFn} = "AMADCommBridge_Undef"; - - $hash->{AttrFn} = "AMADCommBridge_Attr"; - $hash->{AttrList} = "fhemControlMode:trigger,setControl,thirdPartControl ". - "debugJSON:0,1 ". - "enableSubCalls:0,1 ". - "disable:1 ". - "allowfrom ". - $readingFnAttributes; - - foreach my $d(sort keys %{$modules{AMADCommBridge}{defptr}}) { - + $hash->{SetFn} = 'FHEM::AMADCommBridge::Set'; + $hash->{DefFn} = 'FHEM::AMADCommBridge::Define'; + $hash->{UndefFn} = 'FHEM::AMADCommBridge::Undef'; + + $hash->{AttrFn} = 'FHEM::AMADCommBridge::Attr'; + $hash->{AttrList} = + 'fhemControlMode:trigger,setControl,thirdPartControl ' + . 'debugJSON:0,1 ' + . 'enableSubCalls:0,1 ' + . 'disable:1 ' + . 'allowfrom ' + . 'fhemServerIP ' + . $readingFnAttributes; + + foreach my $d ( sort keys %{ $modules{AMADCommBridge}{defptr} } ) { + my $hash = $modules{AMADCommBridge}{defptr}{$d}; - $hash->{VERSIONMODUL} = $modulversion; - $hash->{VERSIONFLOWSET} = $flowsetversion; + $hash->{VERSIONMODUL} = $modulversion; + $hash->{VERSIONFLOWSET} = $flowsetversion; } + + return FHEM::Meta::InitMod( __FILE__, $hash ); } -sub AMADCommBridge_Define($$) { +package FHEM::AMADCommBridge; + +use strict; +use warnings; +use POSIX; +use FHEM::Meta; + +use GPUtils qw(GP_Import) + ; # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt + +my $missingModul = ''; + +use HttpUtils; +use TcpServerUtils; + +eval "use Encode qw(encode encode_utf8);1" or $missingModul .= 'Encode '; +eval "use JSON;1" or $missingModul .= 'JSON '; + +## Import der FHEM Funktionen +BEGIN { + GP_Import( + qw(readingsSingleUpdate + readingsBulkUpdate + readingsBeginUpdate + readingsEndUpdate + defs + modules + Log3 + CommandAttr + CommandDelete + CommandSet + attr + AttrVal + ReadingsVal + init_done + urlEncode + Dispatch + HttpUtils_NonblockingGet + TcpServer_Open + TcpServer_Close + TcpServer_Accept) + ); +} + +sub Define($$) { my ( $hash, $def ) = @_; - - my @a = split( "[ \t][ \t]*", $def ); - - return "too few parameters: define AMADCommBridge ''" if( @a < 2 and @a > 3 ); - return "Cannot define a AMADCommBridge device. Perl modul $missingModul is missing." if ( $missingModul ); - - my $name = $a[0]; - + my @a = split( '[ \t][ \t]*', $def ); + + return $@ unless ( FHEM::Meta::SetInternals($hash) ); + return 'too few parameters: define AMADCommBridge ' + if ( @a < 2 and @a > 3 ); + return + 'Cannot define a AMADCommBridge device. Perl modul ' + . $missingModul + . ' is missing.' + if ($missingModul); + + my $name = $a[0]; + my $port; - $port = $a[2] if($a[2]); - $port = 8090 if( not defined($port) and (!$port) ); - + $port = $a[2] if ( $a[2] ); + $port = 8090 if ( not defined($port) and ( !$port ) ); + $hash->{BRIDGE} = 1; $hash->{PORT} = $port; $hash->{VERSIONMODUL} = $modulversion; $hash->{VERSIONFLOWSET} = $flowsetversion; + CommandAttr( undef, $name . ' room AMAD' ) + if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); - CommandAttr(undef,"$name room AMAD") if(AttrVal($name,'room','none') eq 'none'); - - Log3 $name, 3, "AMADCommBridge ($name) - defined AMADCommBridge with Socketport $port"; + Log3( $name, 3, + "AMADCommBridge ($name) - defined AMADCommBridge with Socketport $port" + ); + + Open($hash); - AMADCommBridge_Open( $hash ); - $modules{AMADCommBridge}{defptr}{BRIDGE} = $hash; return undef; } -sub AMADCommBridge_Undef($$) { +sub Undef($$) { my ( $hash, $arg ) = @_; - - delete $modules{AMADCommBridge}{defptr}{BRIDGE} if( defined($modules{AMADCommBridge}{defptr}{BRIDGE}) and $hash->{BRIDGE} ); - TcpServer_Close( $hash ); + TcpServer_Close($hash); + delete $modules{AMADCommBridge}{defptr}{BRIDGE} + if ( defined( $modules{AMADCommBridge}{defptr}{BRIDGE} ) + and $hash->{BRIDGE} ); return undef; } -sub AMADCommBridge_Attr(@) { +sub Attr(@) { my ( $cmd, $name, $attrName, $attrVal ) = @_; my $hash = $defs{$name}; - + my $orig = $attrVal; - if( $attrName eq "disable" ) { - if( $cmd eq "set" ) { - if( $attrVal eq "0" ) { - - readingsSingleUpdate ( $hash, "state", "enabled", 1 ); - AMADCommBridge_Open($hash); - Log3 $name, 3, "AMADCommBridge ($name) - enabled"; - } else { + if ( $attrName eq 'disable' ) { + if ( $cmd eq 'set' ) { + if ( $attrVal == 0 ) { - AMADCommBridge_Close($hash); - readingsSingleUpdate ( $hash, "state", "disabled", 1 ) if( not defined($hash->{FD}) ); - Log3 $name, 3, "AMADCommBridge ($name) - disabled"; + readingsSingleUpdate( $hash, 'state', 'enabled', 1 ); + Open($hash); + Log3( $name, 3, "AMADCommBridge ($name) - enabled" ); } - - } else { + else { - readingsSingleUpdate ( $hash, "state", "enabled", 1 ); - AMADCommBridge_Open($hash); - Log3 $name, 3, "AMADCommBridge ($name) - enabled"; + Close($hash); + readingsSingleUpdate( $hash, 'state', 'disabled', 1 ) + if ( not defined( $hash->{FD} ) ); + Log3( $name, 3, "AMADCommBridge ($name) - disabled" ); + } + + } + else { + + readingsSingleUpdate( $hash, 'state', 'enabled', 1 ); + Open($hash); + Log3( $name, 3, "AMADCommBridge ($name) - enabled" ); } } - - elsif( $attrName eq "fhemControlMode" ) { - if( $cmd eq "set" ) { - - CommandSet(undef,'set TYPE=AMADDevice:FILTER=deviceState=online statusRequest'); - Log3 $name, 3, "AMADCommBridge ($name) - set fhemControlMode global Variable at Device"; - - } else { - CommandSet(undef,'set TYPE=AMADDevice:FILTER=deviceState=online statusRequest'); - Log3 $name, 3, "AMADCommBridge ($name) - set fhemControlMode global Variable NONE at Device"; + elsif ( $attrName eq 'fhemControlMode' ) { + if ( $cmd eq 'set' ) { + + CommandSet( undef, + 'set TYPE=AMADDevice:FILTER=deviceState=online statusRequest' ); + Log3( $name, 3, +"AMADCommBridge ($name) - set fhemControlMode global Variable at Device" + ); + + } + else { + + CommandSet( undef, + 'set TYPE=AMADDevice:FILTER=deviceState=online statusRequest' ); + Log3( $name, 3, +"AMADCommBridge ($name) - set fhemControlMode global Variable NONE at Device" + ); } } - + return undef; } -sub AMADCommBridge_Set($@) { - - my ($hash, $name, $cmd, @args) = @_; - my ($arg, @params) = @args; - - - if( $cmd eq 'open' ) { - - AMADCommBridge_Open($hash); - - } elsif( $cmd eq 'close' ) { - - AMADCommBridge_Close($hash); - - } elsif( $cmd eq 'fhemServerIP' ) { - - readingsSingleUpdate($hash,$cmd,$arg,1); - - } else { - my $list = "open:noArg close:noArg fhemServerIP"; +sub Set($@) { + + my ( $hash, $name, $cmd, @args ) = @_; + my ( $arg, @params ) = @args; + + if ( $cmd eq 'open' ) { + + Open($hash); + + } + elsif ( $cmd eq 'close' ) { + + Close($hash); + + } + else { + my $list = 'open:noArg close:noArg'; return "Unknown argument $cmd, choose one of $list"; } } -sub AMADCommBridge_Write($@) { +sub Write($@) { - my ($hash,$amad_id,$uri,$path,$header,$method) = @_; - my $name = $hash->{NAME}; - my $dhash = $modules{AMADDevice}{defptr}{$amad_id}; + my ( $hash, $amad_id, $uri, $path, $header, $method ) = @_; + my $name = $hash->{NAME}; + my $dhash = $modules{AMADDevice}{defptr}{$amad_id}; my $param; - my $remoteServer = AttrVal($dhash->{NAME},'remoteServer','Automagic'); + my $remoteServer = AttrVal( $dhash->{NAME}, 'remoteServer', 'Automagic' ); + Log3( $name, 4, "AMADCommBridge ($name) - Write Path: $path" ); - Log3 $name, 4, "AMADCommBridge ($name) - AMADCommBridge_Write Path: $path"; - - - if($remoteServer ne 'Automagic' and $path =~ /\?/) { - $path .= "&amad_id=$amad_id"; - } elsif($remoteServer ne 'Automagic') { - $path .= "?amad_id=$amad_id"; + if ( $remoteServer ne 'Automagic' and $path =~ /\?/ ) { + $path .= '&amad_id=' . $amad_id; + } + elsif ( $remoteServer ne 'Automagic' ) { + $path .= '?amad_id=' . $amad_id; } - return readingsSingleUpdate($dhash,'lastSetCommand',$path,1) - if( $remoteServer eq 'other' ); + return readingsSingleUpdate( $dhash, 'lastSetCommand', $path, 1 ) + if ( $remoteServer eq 'other' ); - $param = { url => "http://" . $uri . $path, timeout => 15, hash => $hash, amad_id => $amad_id, method => $method, header => $header . "\r\namadid: $amad_id", doTrigger => 1, callback => \&AMADCommBridge_ErrorHandling } if($remoteServer eq 'Automagic'); + $param = { + url => 'http://' . $uri . $path, + timeout => 15, + hash => $hash, + amad_id => $amad_id, + method => $method, + header => $header . "\r\namadid: $amad_id", + doTrigger => 1, + callback => \&ErrorHandling + } + if ( $remoteServer eq 'Automagic' ); + $param = { + url => 'http://' . $uri . '/', + data => +"{\"message\":\"AMAD=:=$path\", \"sender\":\"AMAD\", \"ttl\":60, \"communication_base_params\":{\"type\":\"Message\", \"fallback\":false, \"via\":\"Wifi\"},\"version\":\"1.62\"}", + timeout => 15, + hash => $hash, + amad_id => $amad_id, + method => $method, + header => +"agent: TeleHeater/2.2.3\r\nUser-Agent: TeleHeater/2.2.3\r\nAccept: application/json", + doTrigger => 1, + callback => \&ErrorHandling + } + if ( $remoteServer eq 'Autoremote' ); - $param = { url => "http://" . $uri . "/", - data => "{\"message\":\"AMAD=:=$path\", \"sender\":\"AMAD\", \"ttl\":60, \"communication_base_params\":{\"type\":\"Message\", \"fallback\":false, \"via\":\"Wifi\"},\"version\":\"1.62\"}", - timeout => 15, hash => $hash, amad_id => $amad_id, method => $method, - header => "agent: TeleHeater/2.2.3\r\nUser-Agent: TeleHeater/2.2.3\r\nAccept: application/json", - doTrigger => 1, callback => \&AMADCommBridge_ErrorHandling - } if($remoteServer eq 'Autoremote'); + $param = { + url => 'http://' . $uri . '/', + data => 'device=AMAD&cmd=' . urlEncode($path), + timeout => 15, + hash => $hash, + amad_id => $amad_id, + method => $method, + header => +"agent: TeleHeater/2.2.3\r\nUser-Agent: TeleHeater/2.2.3\r\nAccept: application/json", + doTrigger => 1, + callback => \&ErrorHandling + } + if ( $remoteServer eq 'TNES' ); + my $logtext = +"AMADCommBridge ($name) - Send with remoteServer: $remoteServer URL: $param->{url}, HEADER: $param->{header}, METHOD: $method"; + $logtext .= ", DATA: $param->{data}" if ( $remoteServer ne 'Automagic' ); + Log3( $name, 5, "$logtext" ); - $param = { url => "http://" . $uri . "/", - data => "device=AMAD&cmd=".urlEncode($path), - timeout => 15, hash => $hash, amad_id => $amad_id, method => $method, - header => "agent: TeleHeater/2.2.3\r\nUser-Agent: TeleHeater/2.2.3\r\nAccept: application/json", - doTrigger => 1, callback => \&AMADCommBridge_ErrorHandling - } if($remoteServer eq 'TNES'); - - - - my $logtext = "AMADCommBridge ($name) - Send with remoteServer: $remoteServer URL: $param->{url}, HEADER: $param->{header}, METHOD: $method"; - $logtext .= ", DATA: $param->{data}" if( $remoteServer ne 'Automagic' ); - Log3 $name, 5, "$logtext"; - - - HttpUtils_NonblockingGet($param) if( defined($param) ); + HttpUtils_NonblockingGet($param) if ( defined($param) ); } -sub AMADCommBridge_ErrorHandling($$$) { +sub ErrorHandling($$$) { - my ($param,$err,$data) = @_; - - my $hash = $param->{hash}; - my $dhash = $modules{AMADDevice}{defptr}{$param->{'amad_id'}}; - my $dname = $dhash->{NAME}; + my ( $param, $err, $data ) = @_; + my $hash = $param->{hash}; + my $dhash = $modules{AMADDevice}{defptr}{ $param->{'amad_id'} }; + my $dname = $dhash->{NAME}; + + if ( $param->{method} eq 'GET' ) { - - - if( $param->{method} eq 'GET' ) { - ### Begin Error Handling - if( $dhash->{helper}{infoErrorCounter} > 0 ) { - - readingsBeginUpdate( $dhash ); - readingsBulkUpdate( $dhash, "lastStatusRequestState", "statusRequest_error", 1 ); + if ( $dhash->{helper}{infoErrorCounter} > 0 ) { - if( ReadingsVal( $dname, "flow_Informations", "active" ) eq "inactive" && ReadingsVal( $dname, "flow_SetCommands", "active" ) eq "inactive" ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: CHECK THE LAST ERROR READINGS FOR MORE INFO, DEVICE IS SET OFFLINE"; - - readingsBulkUpdate( $dhash, "deviceState", "offline", 1 ); - readingsBulkUpdate ( $dhash, "state", "AMAD Flows inactive, device set offline",1); + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'lastStatusRequestState', + 'statusRequest_error', 1 ); + + if ( ReadingsVal( $dname, 'flow_Informations', 'active' ) eq + 'inactive' + && ReadingsVal( $dname, 'flow_SetCommands', 'active' ) eq + 'inactive' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: CHECK THE LAST ERROR READINGS FOR MORE INFO, DEVICE IS SET OFFLINE" + ); + + readingsBulkUpdate( $dhash, 'deviceState', 'offline', 1 ); + readingsBulkUpdate( $dhash, 'state', + 'AMAD Flows inactive, device set offline', 1 ); } - elsif( $dhash->{helper}{infoErrorCounter} > 7 && $dhash->{helper}{setCmdErrorCounter} > 4 ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: UNKNOWN ERROR, PLEASE CONTACT THE DEVELOPER, DEVICE DISABLED"; - + elsif ($dhash->{helper}{infoErrorCounter} > 7 + && $dhash->{helper}{setCmdErrorCounter} > 4 ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: UNKNOWN ERROR, PLEASE CONTACT THE DEVELOPER, DEVICE DISABLED" + ); + $attr{$dname}{disable} = 1; - readingsBulkUpdate ( $dhash, "state", "Unknown Error, device disabled", 1); - - $dhash->{helper}{infoErrorCounter} = 0; + readingsBulkUpdate( $dhash, 'state', + 'Unknown Error, device disabled', 1 ); + + $dhash->{helper}{infoErrorCounter} = 0; $dhash->{helper}{setCmdErrorCounter} = 0; - + return; } - elsif( ReadingsVal( $dname, "flow_Informations", "active" ) eq "inactive" ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: Informations Flow on your Device is inactive, will try to reactivate"; + elsif ( ReadingsVal( $dname, 'flow_Informations', 'active' ) eq + 'inactive' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: Informations Flow on your Device is inactive, will try to reactivate" + ); } - elsif( $dhash->{helper}{infoErrorCounter} > 7 ) { + elsif ( $dhash->{helper}{infoErrorCounter} > 7 ) { - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: To many Errors please check your Network or Device Configuration, DEVICE IS SET OFFLINE"; - - readingsBulkUpdate( $dhash, "deviceState", "offline", 1 ); - readingsBulkUpdate ( $dhash, "state", "To many Errors, device set offline", 1); + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: To many Errors please check your Network or Device Configuration, DEVICE IS SET OFFLINE" + ); + + readingsBulkUpdate( $dhash, 'deviceState', 'offline', 1 ); + readingsBulkUpdate( $dhash, 'state', + 'To many Errors, device set offline', 1 ); $dhash->{helper}{infoErrorCounter} = 0; } - - elsif($dhash->{helper}{infoErrorCounter} > 2 && ReadingsVal( $dname, "flow_Informations", "active" ) eq "active" ){ - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: Please check the AutomagicAPP on your Device"; + + elsif ( $dhash->{helper}{infoErrorCounter} > 2 + && ReadingsVal( $dname, 'flow_Informations', 'active' ) eq + 'active' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: Please check the AutomagicAPP on your Device" + ); } readingsEndUpdate( $dhash, 1 ); } - - if( defined( $err ) ) { - if( $err ne "" ) { - - readingsBeginUpdate( $dhash ); - readingsBulkUpdate ( $dhash, "state", "$err") if( ReadingsVal( $dname, "state", 1 ) ne "initialized" ); - $dhash->{helper}{infoErrorCounter} = ( $dhash->{helper}{infoErrorCounter} + 1 ); - readingsBulkUpdate( $dhash, "lastStatusRequestState", "statusRequest_error", 1 ); - - if( $err =~ /timed out/ ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: connect to your device is timed out. check network"; + if ( defined($err) ) { + if ( $err ne '' ) { + + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'state', $err ) + if ( ReadingsVal( $dname, 'state', 1 ) ne 'initialized' ); + $dhash->{helper}{infoErrorCounter} = + ( $dhash->{helper}{infoErrorCounter} + 1 ); + + readingsBulkUpdate( $dhash, 'lastStatusRequestState', + 'statusRequest_error', 1 ); + + if ( $err =~ /timed out/ ) { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: connect to your device is timed out. check network" + ); } - - elsif( ( $err =~ /Keine Route zum Zielrechner/ ) && $dhash->{helper}{infoErrorCounter} > 1 ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: no route to target. bad network configuration or network is down"; - - } else { - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: $err"; + elsif ( ( $err =~ /Keine Route zum Zielrechner/ ) + && $dhash->{helper}{infoErrorCounter} > 1 ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: no route to target. bad network configuration or network is down" + ); + + } + else { + + Log3( $dname, 5, + "AMADCommBridge ($dname) - statusRequestERROR: $err" ); } readingsEndUpdate( $dhash, 1 ); - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: AMADCommBridge_statusRequestErrorHandling: error while requesting AutomagicInfo: $err"; + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: statusRequestErrorHandling: error while requesting AutomagicInfo: $err" + ); return; } } - if( $data eq "" and exists( $param->{code} ) && $param->{code} ne 200 ) { - - readingsBeginUpdate( $dhash ); - readingsBulkUpdate ( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dname, "state", 1 ) ne "initialized" ); - $dhash->{helper}{infoErrorCounter} = ( $dhash->{helper}{infoErrorCounter} + 1 ); + if ( $data eq '' and exists( $param->{code} ) && $param->{code} ne 200 ) + { - readingsBulkUpdate( $dhash, "lastStatusRequestState", "statusRequest_error", 1 ); - - if( $param->{code} ne 200 ) { + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'state', $param->{code}, 1 ) + if ( ReadingsVal( $dname, 'state', 1 ) ne 'initialized' ); + $dhash->{helper}{infoErrorCounter} = + ( $dhash->{helper}{infoErrorCounter} + 1 ); - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: ".$param->{code}; + readingsBulkUpdate( $dhash, 'lastStatusRequestState', + 'statusRequest_error', 1 ); + + if ( $param->{code} ne 200 ) { + + Log3( $dname, 5, + "AMADCommBridge ($dname) - statusRequestERROR: " + . $param->{code} ); } readingsEndUpdate( $dhash, 1 ); - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: received http code ".$param->{code}." without any data after requesting AMAD AutomagicInfo"; + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: received http code " + . $param->{code} + . " without any data after requesting AMAD AutomagicInfo" ); return; } - if( ( $data =~ /Error/i ) and exists( $param->{code} ) ) { - readingsBeginUpdate( $dhash ); - readingsBulkUpdate( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dname, "state" ,0) ne "initialized" ); - $dhash->{helper}{infoErrorCounter} = ( $dhash->{helper}{infoErrorCounter} + 1 ); + if ( ( $data =~ /Error/i ) and exists( $param->{code} ) ) { + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'state', $param->{code}, 1 ) + if ( ReadingsVal( $dname, 'state', 0 ) ne 'initialized' ); + $dhash->{helper}{infoErrorCounter} = + ( $dhash->{helper}{infoErrorCounter} + 1 ); - readingsBulkUpdate( $dhash, "lastStatusRequestState", "statusRequest_error", 1 ); + readingsBulkUpdate( $dhash, 'lastStatusRequestState', + 'statusRequest_error', 1 ); - if( $param->{code} eq 404 && ReadingsVal( $dname, "flow_Informations", "inactive" ) eq "inactive" ) { + if ( $param->{code} eq 404 + && ReadingsVal( $dname, 'flow_Informations', 'inactive' ) eq + 'inactive' ) + { - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: check the informations flow on your device"; + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: check the informations flow on your device" + ); } - - elsif( $param->{code} eq 404 && ReadingsVal( $dname, "flow_Informations", "active" ) eq "active" ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: check the automagicApp on your device"; - - } else { - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: http error ".$param->{code}; + elsif ( $param->{code} eq 404 + && ReadingsVal( $dname, 'flow_Informations', 'active' ) eq + 'active' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: check the automagicApp on your device" + ); + + } + else { + + Log3( $dname, 5, + "AMADCommBridge ($dname) - statusRequestERROR: http error " + . $param->{code} ); } readingsEndUpdate( $dhash, 1 ); - - Log3 $dname, 5, "AMADCommBridge ($dname) - statusRequestERROR: received http code ".$param->{code}." receive Error after requesting AMAD AutomagicInfo"; + + Log3( $dname, 5, +"AMADCommBridge ($dname) - statusRequestERROR: received http code " + . $param->{code} + . " receive Error after requesting AMAD AutomagicInfo" ); return; } ### End Error Handling - readingsSingleUpdate( $dhash, "lastStatusRequestState", "statusRequest_done", 1 ); + readingsSingleUpdate( $dhash, 'lastStatusRequestState', + 'statusRequest_done', 1 ); $dhash->{helper}{infoErrorCounter} = 0; } - - elsif( $param->{method} eq 'POST' ) { + + elsif ( $param->{method} eq 'POST' ) { ### Begin Error Handling - if( $dhash->{helper}{setCmdErrorCounter} > 2 ) { - - readingsBeginUpdate( $dhash ); - readingsBulkUpdate( $dhash, "lastSetCommandState", "statusRequest_error", 1 ); + if ( $dhash->{helper}{setCmdErrorCounter} > 2 ) { - if( ReadingsVal( $dname, "flow_Informations", "active" ) eq "inactive" && ReadingsVal( $dname, "flow_SetCommands", "active" ) eq "inactive" ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: CHECK THE LAST ERROR READINGS FOR MORE INFO, DEVICE IS SET OFFLINE"; + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'lastSetCommandState', + 'statusRequest_error', 1 ); - readingsBulkUpdate( $dhash, "deviceState", "offline", 1 ); - readingsBulkUpdate( $dhash, "state", "AMAD Flows inactive, device set offline", 1 ); + if ( ReadingsVal( $dname, 'flow_Informations', 'active' ) eq + 'inactive' + && ReadingsVal( $dname, 'flow_SetCommands', 'active' ) eq + 'inactive' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: CHECK THE LAST ERROR READINGS FOR MORE INFO, DEVICE IS SET OFFLINE" + ); + + readingsBulkUpdate( $dhash, 'deviceState', 'offline', 1 ); + readingsBulkUpdate( $dhash, 'state', + 'AMAD Flows inactive, device set offline', 1 ); } - elsif( $dhash->{helper}{infoErrorCounter} > 7 && $dhash->{helper}{setCmdErrorCounter} > 4 ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: UNKNOWN ERROR, PLEASE CONTACT THE DEVELOPER, DEVICE DISABLED"; - + elsif ($dhash->{helper}{infoErrorCounter} > 7 + && $dhash->{helper}{setCmdErrorCounter} > 4 ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: UNKNOWN ERROR, PLEASE CONTACT THE DEVELOPER, DEVICE DISABLED" + ); + $attr{$dname}{disable} = 1; - readingsBulkUpdate( $dhash, "state", "Unknown Error, device disabled", 1 ); - $dhash->{helper}{infoErrorCounter} = 0; + readingsBulkUpdate( $dhash, 'state', + 'Unknown Error, device disabled', 1 ); + $dhash->{helper}{infoErrorCounter} = 0; $dhash->{helper}{setCmdErrorCounter} = 0; return; } - elsif( ReadingsVal( $dname, "flow_SetCommands", "active" ) eq "inactive" ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: Flow SetCommands on your Device is inactive, will try to reactivate"; + elsif ( ReadingsVal( $dname, 'flow_SetCommands', 'active' ) eq + 'inactive' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: Flow SetCommands on your Device is inactive, will try to reactivate" + ); } - elsif( $dhash->{helper}{setCmdErrorCounter} > 9 ) { - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: To many Errors please check your Network or Device Configuration, DEVICE IS SET OFFLINE"; - - readingsBulkUpdate( $dhash, "deviceState", "offline", 1 ); - readingsBulkUpdate( $dhash, "state", "To many Errors, device set offline", 1 ); + elsif ( $dhash->{helper}{setCmdErrorCounter} > 9 ) { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: To many Errors please check your Network or Device Configuration, DEVICE IS SET OFFLINE" + ); + + readingsBulkUpdate( $dhash, 'deviceState', 'offline', 1 ); + readingsBulkUpdate( $dhash, 'state', + 'To many Errors, device set offline', 1 ); $dhash->{helper}{setCmdErrorCounter} = 0; } - elsif( $dhash->{helper}{setCmdErrorCounter} > 4 && ReadingsVal( $dname, "flow_SetCommands", "active" ) eq "active" ){ - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: Please check the AutomagicAPP on your Device"; + elsif ( $dhash->{helper}{setCmdErrorCounter} > 4 + && ReadingsVal( $dname, 'flow_SetCommands', 'active' ) eq + 'active' ) + { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: Please check the AutomagicAPP on your Device" + ); } readingsEndUpdate( $dhash, 1 ); } - - if( defined( $err ) ) { - if( $err ne "" ) { - readingsBeginUpdate( $dhash ); - readingsBulkUpdate( $dhash, "state", $err, 1 ) if( ReadingsVal( $dname, "state", 0 ) ne "initialized" ); - $dhash->{helper}{setCmdErrorCounter} = ($dhash->{helper}{setCmdErrorCounter} + 1); - - readingsBulkUpdate( $dhash, "lastSetCommandState", "setCmd_error", 1 ); - - if( $err =~ /timed out/ ) { - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: connect to your device is timed out. check network"; + if ( defined($err) ) { + if ( $err ne '' ) { + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'state', $err, 1 ) + if ( ReadingsVal( $dname, 'state', 0 ) ne 'initialized' ); + $dhash->{helper}{setCmdErrorCounter} = + ( $dhash->{helper}{setCmdErrorCounter} + 1 ); + + readingsBulkUpdate( $dhash, 'lastSetCommandState', + 'setCmd_error', 1 ); + + if ( $err =~ /timed out/ ) { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: connect to your device is timed out. check network" + ); } - - elsif( $err =~ /Keine Route zum Zielrechner/ ) { - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: no route to target. bad network configuration or network is down"; + elsif ( $err =~ /Keine Route zum Zielrechner/ ) { + + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: no route to target. bad network configuration or network is down" + ); - } else { - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: $err"; } - + else { + + Log3( $dname, 5, + "AMADCommBridge ($dname) - setCommandERROR: $err" ); + } + readingsEndUpdate( $dhash, 1 ); - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: error while POST Command: $err"; + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: error while POST Command: $err" + ); return; } } - - if( $data eq "" and exists( $param->{code} ) && $param->{code} ne 200 ) { - - readingsBeginUpdate( $dhash ); - readingsBulkUpdate( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dhash, "state", 0 ) ne "initialized" ); - $dhash->{helper}{setCmdErrorCounter} = ( $dhash->{helper}{setCmdErrorCounter} + 1 ); + if ( $data eq '' and exists( $param->{code} ) && $param->{code} ne 200 ) + { - readingsBulkUpdate($dhash, "lastSetCommandState", "setCmd_error", 1 ); + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'state', $param->{code}, 1 ) + if ( ReadingsVal( $dhash, 'state', 0 ) ne 'initialized' ); + + $dhash->{helper}{setCmdErrorCounter} = + ( $dhash->{helper}{setCmdErrorCounter} + 1 ); + + readingsBulkUpdate( $dhash, 'lastSetCommandState', 'setCmd_error', + 1 ); readingsEndUpdate( $dhash, 1 ); - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: received http code ".$param->{code}; + + Log3( $dname, 5, + "AMADCommBridge ($dname) - setCommandERROR: received http code " + . $param->{code} ); return; } - - if( ( $data =~ /Error/i ) and exists( $param->{code} ) ) { - - readingsBeginUpdate( $dhash ); - readingsBulkUpdate( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dname, "state", 0 ) ne "initialized" ); - $dhash->{helper}{setCmdErrorCounter} = ( $dhash->{helper}{setCmdErrorCounter} + 1 ); + if ( ( $data =~ /Error/i ) and exists( $param->{code} ) ) { - readingsBulkUpdate( $dhash, "lastSetCommandState", "setCmd_error", 1 ); - - if( $param->{code} eq 404 ) { - - readingsBulkUpdate( $dhash, "lastSetCommandError", "", 1 ); - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: setCommands flow is inactive on your device!"; - - } else { - - Log3 $dname, 5, "AMADCommBridge ($dname) - setCommandERROR: http error ".$param->{code}; + readingsBeginUpdate($dhash); + readingsBulkUpdate( $dhash, 'state', $param->{code}, 1 ) + if ( ReadingsVal( $dname, 'state', 0 ) ne 'initialized' ); + + $dhash->{helper}{setCmdErrorCounter} = + ( $dhash->{helper}{setCmdErrorCounter} + 1 ); + + readingsBulkUpdate( $dhash, 'lastSetCommandState', 'setCmd_error', + 1 ); + + if ( $param->{code} eq 404 ) { + + readingsBulkUpdate( $dhash, 'lastSetCommandError', '', 1 ); + Log3( $dname, 5, +"AMADCommBridge ($dname) - setCommandERROR: setCommands flow is inactive on your device!" + ); + + } + else { + + Log3( $dname, 5, + "AMADCommBridge ($dname) - setCommandERROR: http error " + . $param->{code} ); } return; } - + ### End Error Handling - - readingsSingleUpdate( $dhash, "lastSetCommandState", "setCmd_done", 1 ); + + readingsSingleUpdate( $dhash, 'lastSetCommandState', 'setCmd_done', 1 ); $dhash->{helper}{setCmdErrorCounter} = 0; - + return undef; } - - + } -sub AMADCommBridge_Open($) { +sub Open($) { + my $hash = shift; - my $hash = shift; - my $name = $hash->{NAME}; - my $port = $hash->{PORT}; - + my $name = $hash->{NAME}; + my $port = $hash->{PORT}; + + if ( not defined( $hash->{FD} ) and ( !$hash->{FD} ) ) { - if( not defined($hash->{FD}) and (! $hash->{FD}) ) { # Oeffnen des TCP Sockets - my $ret = TcpServer_Open( $hash, $port, "global" ); - - if( $ret && !$init_done ) { - - Log3 $name, 3, "AMADCommBridge ($name) - $ret. Exiting."; + my $ret = TcpServer_Open( $hash, $port, 'global' ); + + if ( $ret && !$init_done ) { + + Log3( $name, 3, "AMADCommBridge ($name) - $ret. Exiting." ); exit(1); } - - readingsSingleUpdate ( $hash, "state", "opened", 1 ) if( defined($hash->{FD}) ); - Log3 $name, 3, "AMADCommBridge ($name) - Socket opened."; + + readingsSingleUpdate( $hash, 'state', 'opened', 1 ) + if ( defined( $hash->{FD} ) ); + Log3( $name, 3, "AMADCommBridge ($name) - Socket opened." ); return $ret; - - } else { - - Log3 $name, 3, "AMADCommBridge ($name) - Socket already opened"; } - + else { + + Log3( $name, 3, "AMADCommBridge ($name) - Socket already opened" ); + } + return; } -sub AMADCommBridge_Close($) { +sub Close($) { + my $hash = shift; + + my $name = $hash->{NAME}; + + TcpServer_Close($hash); + + if ( not defined( $hash->{FD} ) ) { + readingsSingleUpdate( $hash, 'state', 'closed', 1 ); + Log3( $name, 3, "AMADCommBridge ($name) - Socket closed." ); - my $hash = shift; - - my $name = $hash->{NAME}; - - delete $modules{AMADCommBridge}{defptr}{BRIDGE}; - TcpServer_Close( $hash ); - - if( not defined($hash->{FD}) ) { - readingsSingleUpdate ( $hash, "state", "closed", 1 ); - Log3 $name, 3, "AMADCommBridge ($name) - Socket closed."; - - } else { - Log3 $name, 3, "AMADCommBridge ($name) - can't close Socket."; } - + else { + Log3( $name, 3, "AMADCommBridge ($name) - can't close Socket." ); + } + return; } -sub AMADCommBridge_Read($) { +sub Read($) { - my $hash = shift; - my $name = $hash->{NAME}; + my $hash = shift; + my $name = $hash->{NAME}; - - if( $hash->{SERVERSOCKET} ) { # Accept and create a child - TcpServer_Accept( $hash, "AMADCommBridge" ); + if ( $hash->{SERVERSOCKET} ) { # Accept and create a child + TcpServer_Accept( $hash, 'AMADCommBridge' ); return; } # Read 1024 byte of data my $buf; - my $ret = sysread($hash->{CD}, $buf, 2048); - + my $ret = sysread( $hash->{CD}, $buf, 2048 ); # When there is an error in connection return - if( !defined($ret ) or $ret <= 0 ) { + if ( !defined($ret) or $ret <= 0 ) { CommandDelete( undef, $name ); - Log3 $name, 5, "AMADCommBridge ($name) - Connection closed for $name"; + Log3( $name, 5, + "AMADCommBridge ($name) - Connection closed for $name" ); return; } - - AMADCommBridge_ProcessRead($hash,$buf); + + ProcessRead( $hash, $buf ); } -sub AMADCommBridge_ProcessRead($$) { +sub ProcessRead($$) { + + my ( $hash, $buf ) = @_; + my $name = $hash->{NAME}; + + my @data = split( '\R\R', $buf ); + my $data = $data[0]; + my $json = $data[1]; + my $buffer = ''; + + Log3( $name, 4, "AMADCommBridge ($name) - process read" ); - my ($hash, $buf) = @_; - my $name = $hash->{NAME}; - - my @data = split( '\R\R', $buf ); - my $data = $data[0]; - my $json = $data[1]; - my $buffer = ''; - - - - - Log3 $name, 4, "AMADCommBridge ($name) - process read"; - - my $response; my $c; - + my $fhempath = $attr{global}{modpath}; - + if ( $data =~ /currentFlowsetUpdate.xml/ ) { - $response = qx(cat $fhempath/FHEM/lib/74_AMADautomagicFlowset_$flowsetversion.xml); + $response = +qx(cat $fhempath/FHEM/lib/74_AMADautomagicFlowset_$flowsetversion.xml); $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; - - } elsif( $data =~ /currentTaskersetUpdate.prj.xml/ ) { - - $response = qx(cat $fhempath/FHEM/lib/74_AMADtaskerset_$flowsetversion.prj.xml); + + } + elsif ( $data =~ /currentTaskersetUpdate.prj.xml/ ) { + + $response = + qx(cat $fhempath/FHEM/lib/74_AMADtaskerset_$flowsetversion.prj.xml); $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; - - } elsif ( $data =~ /installFlow_([^.]*.xml)/ ) { - if( defined($1) ){ + } + elsif ( $data =~ /installFlow_([^.]*.xml)/ ) { + + if ( defined($1) ) { $response = qx(cat /tmp/$1); - $c = $hash->{CD}; + $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; } } + if ( defined( $hash->{PARTIAL} ) and $hash->{PARTIAL} ) { - if(defined($hash->{PARTIAL}) and $hash->{PARTIAL}) { - - Log3 $name, 5, "AMADCommBridge ($name) - PARTIAL: " . $hash->{PARTIAL}; + Log3( $name, 5, + "AMADCommBridge ($name) - PARTIAL: " . $hash->{PARTIAL} ); $buffer = $hash->{PARTIAL}; - - } else { - - Log3 $name, 4, "AMADCommBridge ($name) - No PARTIAL buffer"; + + } + else { + + Log3( $name, 4, "AMADCommBridge ($name) - No PARTIAL buffer" ); } - Log3 $name, 5, "AMADCommBridge ($name) - Incoming data: " . $json; + Log3( $name, 5, "AMADCommBridge ($name) - Incoming data: " . $json ); $buffer = $buffer . $json; - Log3 $name, 4, "AMADCommBridge ($name) - Current processing buffer (PARTIAL + incoming data): " . $buffer; + Log3( $name, 4, +"AMADCommBridge ($name) - Current processing buffer (PARTIAL + incoming data): " + . $buffer ); - my ($correct_json,$tail) = AMADCommBridge_ParseMsg($hash, $buffer); + my ( $correct_json, $tail ) = ParseMsg( $hash, $buffer ); + while ($correct_json) { - while($correct_json) { - $hash->{LAST_RECV} = time(); - - Log3 $name, 5, "AMADCommBridge ($name) - Decoding JSON message. Length: " . length($correct_json) . " Content: " . $correct_json; - Log3 $name, 5, "AMADCommBridge ($name) - Vor Sub: Laenge JSON: " . length($correct_json) . " Content: " . $correct_json . " Tail: " . $tail; - - AMADCommBridge_ResponseProcessing($hash,$correct_json) - unless(not defined($tail) and not ($tail)); - - ($correct_json,$tail) = AMADCommBridge_ParseMsg($hash, $tail); - - Log3 $name, 5, "AMADCommBridge ($name) - Nach Sub: Laenge JSON: " . length($correct_json) . " Content: " . $correct_json . " Tail: " . $tail; + + Log3( $name, 5, + "AMADCommBridge ($name) - Decoding JSON message. Length: " + . length($correct_json) + . " Content: " + . $correct_json ); + Log3( $name, 5, + "AMADCommBridge ($name) - Vor Sub: Laenge JSON: " + . length($correct_json) + . " Content: " + . $correct_json + . " Tail: " + . $tail ); + + ResponseProcessing( $hash, $correct_json ) + unless ( not defined($tail) and not($tail) ); + + ( $correct_json, $tail ) = ParseMsg( $hash, $tail ); + + Log3( $name, 5, + "AMADCommBridge ($name) - Nach Sub: Laenge JSON: " + . length($correct_json) + . " Content: " + . $correct_json + . " Tail: " + . $tail ); } - $hash->{PARTIAL} = $tail; - Log3 $name, 4, "AMADCommBridge ($name) - PARTIAL lenght: " . length($tail); - - - Log3 $name, 5, "AMADCommBridge ($name) - Tail: " . $tail; - Log3 $name, 5, "AMADCommBridge ($name) - PARTIAL: " . $hash->{PARTIAL}; - + Log3( $name, 4, + "AMADCommBridge ($name) - PARTIAL lenght: " . length($tail) ); + + Log3( $name, 5, "AMADCommBridge ($name) - Tail: " . $tail ); + Log3( $name, 5, "AMADCommBridge ($name) - PARTIAL: " . $hash->{PARTIAL} ); + } -sub AMADCommBridge_ResponseProcessing($$) { +sub ResponseProcessing($$) { + + my ( $hash, $json ) = @_; + + my $name = $hash->{NAME}; + my $bhash = $modules{AMADCommBridge}{defptr}{BRIDGE}; + my $bname = $bhash->{NAME}; - my ($hash,$json) = @_; - - my $name = $hash->{NAME}; - my $bhash = $modules{AMADCommBridge}{defptr}{BRIDGE}; - my $bname = $bhash->{NAME}; - - - - #### Verarbeitung der Daten welche über die AMADCommBridge kommen #### - - Log3 $bname, 4, "AMADCommBridge ($name) - Receive RAW Message in Debugging Mode: $json"; + Log3( $bname, 4, + "AMADCommBridge ($name) - Receive RAW Message in Debugging Mode: $json" + ); my $response; my $c; + my $decode_json = eval { decode_json($json) }; + if ($@) { + Log3( $bname, 4, + "AMADCommBridge ($name) - JSON error while request: $@" ); - my $decode_json = eval{decode_json($json)}; - if($@){ - Log3 $bname, 4, "AMADCommBridge ($name) - JSON error while request: $@"; - - if( AttrVal( $bname, 'debugJSON', 0 ) == 1 ) { + if ( AttrVal( $bname, 'debugJSON', 0 ) == 1 ) { readingsBeginUpdate($bhash); - readingsBulkUpdate($bhash, 'JSON_ERROR', $@, 1); - readingsBulkUpdate($bhash, 'JSON_ERROR_STRING', $json, 1); - readingsEndUpdate($bhash, 1); + readingsBulkUpdate( $bhash, 'JSON_ERROR', $@, 1 ); + readingsBulkUpdate( $bhash, 'JSON_ERROR_STRING', $json, 1 ); + readingsEndUpdate( $bhash, 1 ); } - - $response = "header lines: \r\n AMADCommBridge receive a JSON error\r\n AMADCommBridge to do nothing\r\n"; + + $response = +"header lines: \r\n AMADCommBridge receive a JSON error\r\n AMADCommBridge to do nothing\r\n"; $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; } - my $amad_id = $decode_json->{amad}{amad_id}; - my $fhemcmd = $decode_json->{amad}{fhemcmd}; + my $amad_id = $decode_json->{amad}{amad_id}; + my $fhemcmd = $decode_json->{amad}{fhemcmd}; my $fhemDevice; - - if( defined($decode_json->{firstrun}) and ($decode_json->{firstrun}) ) { - - $fhemDevice = $decode_json->{firstrun}{fhemdevice} if( defined($decode_json->{firstrun}{fhemdevice}) ); - - } else { - - $fhemDevice = $modules{AMADDevice}{defptr}{$amad_id}->{NAME}; + + if ( defined( $decode_json->{firstrun} ) and ( $decode_json->{firstrun} ) ) + { + + $fhemDevice = $decode_json->{firstrun}{fhemdevice} + if ( defined( $decode_json->{firstrun}{fhemdevice} ) ); + + } + else { + + $fhemDevice = $modules{AMADDevice}{defptr}{$amad_id}->{NAME}; } + if ( !defined($amad_id) or !defined($fhemDevice) ) { + readingsSingleUpdate( $bhash, 'transmitterERROR', + $hash->{NAME} . ' has no correct amad_id', 1 ); + Log3( $bname, 4, +"AMADCommBridge ($name) - ERROR - no device name given. please check your global variable amad_id in automagic" + ); - - - if( !defined($amad_id) or !defined($fhemDevice) ) { - readingsSingleUpdate( $bhash, "transmitterERROR", $hash->{NAME}." has no correct amad_id", 1 ); - Log3 $bname, 4, "AMADCommBridge ($name) - ERROR - no device name given. please check your global variable amad_id in automagic"; - - $response = "header lines: \r\n AMADCommBridge receive no device name. please check your global variable amad_id in automagic\r\n FHEM to do nothing\r\n"; + $response = +"header lines: \r\n AMADCommBridge receive no device name. please check your global variable amad_id in automagic\r\n FHEM to do nothing\r\n"; $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; - + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; + return; } - - if( defined($fhemcmd) and ($fhemcmd) ) { + if ( defined($fhemcmd) and ($fhemcmd) ) { if ( $fhemcmd eq 'setreading' ) { - return Log3 $bname, 3, "AMADCommBridge ($name) - AMADCommBridge: processing receive no reading values from Device: $fhemDevice" - unless( (defined($decode_json->{payload}) and ($decode_json->{payload})) or (defined($decode_json->{firstrun}) and ($decode_json->{firstrun})) ); - - Log3 $bname, 4, "AMADCommBridge ($bname) - AMADCommBridge: processing receive reading values - Device: $fhemDevice Data: $decode_json->{payload}" - if( defined($decode_json->{payload}) and ($decode_json->{payload}) ); + return Log3( $bname, 3, +"AMADCommBridge ($name) - AMADCommBridge: processing receive no reading values from Device: $fhemDevice" + ) + unless ( + ( + defined( $decode_json->{payload} ) + and ( $decode_json->{payload} ) + ) + or ( defined( $decode_json->{firstrun} ) + and ( $decode_json->{firstrun} ) ) + ); - Dispatch($bhash,$json,undef); - Log3 $bname, 4, "AMADCommBridge ($bname) - call Dispatcher"; - readingsSingleUpdate($bhash,'fhemServerIP',$decode_json->{firstrun}{'fhemserverip'},1) if( defined($decode_json->{firstrun}{'fhemserverip'})); - - $response = "header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM was processes\r\n"; + Log3( $bname, 4, +"AMADCommBridge ($bname) - AMADCommBridge: processing receive reading values - Device: $fhemDevice Data: $decode_json->{payload}" + ) + if ( defined( $decode_json->{payload} ) + and ( $decode_json->{payload} ) ); + + Dispatch( $bhash, $json, undef ); + Log3( $bname, 4, "AMADCommBridge ($bname) - call Dispatcher" ); + CommandAttr( undef, + $bname + . ' fhemServerIP ' + . $decode_json->{firstrun}{'fhemserverip'} ) + if ( defined( $decode_json->{firstrun}{'fhemserverip'} ) ); + + $response = +"header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM was processes\r\n"; $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; } elsif ( $fhemcmd eq 'set' ) { - my $fhemCmd = encode_utf8($decode_json->{payload}{setcmd}); - AnalyzeCommandChain($bhash, 'set '.$fhemCmd) if( AttrVal( $bname, 'fhemControlMode', 'trigger' ) eq 'setControl' ); - readingsSingleUpdate( $bhash, "receiveFhemCommand", "set ".$fhemCmd, 1 ) if( AttrVal( $bname, 'fhemControlMode', 'trigger' ) eq 'trigger' ); - Log3 $bname, 4, "AMADCommBridge ($name) - AMADCommBridge_CommBridge: set reading receive fhem command"; + my $fhemCmd = encode_utf8( $decode_json->{payload}{setcmd} ); + AnalyzeCommandChain( $bhash, 'set ' . $fhemCmd ) + if ( AttrVal( $bname, 'fhemControlMode', 'trigger' ) eq + 'setControl' ); + readingsSingleUpdate( $bhash, 'receiveFhemCommand', + 'set ' . $fhemCmd, 1 ) + if ( + AttrVal( $bname, 'fhemControlMode', 'trigger' ) eq 'trigger' ); + Log3( $bname, 4, +"AMADCommBridge ($name) - CommBridge: set reading receive fhem command" + ); - $response = "header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM response\r\n"; + $response = +"header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM response\r\n"; $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; } - + elsif ( $fhemcmd eq 'voiceinputvalue' ) { - my $fhemCmd = lc(encode_utf8($decode_json->{payload}{voiceinputdata})); - - readingsBeginUpdate( $bhash); - readingsBulkUpdate( $bhash, "receiveVoiceCommand", $fhemCmd, 1 ); - readingsBulkUpdate( $bhash, "receiveVoiceDevice", $fhemDevice, 1 ); - readingsEndUpdate( $bhash, 1 ); - Log3 $bname, 4, "AMADCommBridge ($name) - AMADCommBridge_CommBridge: set reading receive voice command: $fhemCmd from Device $fhemDevice"; + my $fhemCmd = + lc( encode_utf8( $decode_json->{payload}{voiceinputdata} ) ); - $response = "header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM was processes\r\n"; + readingsBeginUpdate($bhash); + readingsBulkUpdate( $bhash, 'receiveVoiceCommand', $fhemCmd, 1 ); + readingsBulkUpdate( $bhash, 'receiveVoiceDevice', $fhemDevice, 1 ); + readingsEndUpdate( $bhash, 1 ); + Log3( $bname, 4, +"AMADCommBridge ($name) - CommBridge: set reading receive voice command: $fhemCmd from Device $fhemDevice" + ); + + $response = +"header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM was processes\r\n"; $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; - + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; + return; } - + elsif ( $fhemcmd eq 'readingsval' ) { my $fhemCmd = $decode_json->{payload}{readingsvalcmd}; my @datavalue = split( ' ', $fhemCmd ); - $response = ReadingsVal($datavalue[0],$datavalue[1],$datavalue[2]); + $response = + ReadingsVal( $datavalue[0], $datavalue[1], $datavalue[2] ); $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; return; } elsif ( $fhemcmd eq 'fhemfunc' ) { my $fhemCmd = $decode_json->{payload}{fhemsub}; - - Log3 $bname, 4, "AMADCommBridge ($name) - AMADCommBridge_CommBridge: receive fhem-function command"; - - if( AttrVal( $bname, 'enableSubCalls', 0 ) == 1 ) { - #$response = AnalyzeCommand($bhash, '{'.$fhemCmd.'}'); - $response = AnalyzePerlCommand($bhash, '{'.$fhemCmd.'}'); # AnalyzePerlCommand is new https://forum.fhem.de/index.php/topic,89619.msg820964.html#msg820964 - - } else { - - $response = "header lines: \r\n Attribut enableSubCalls is not set or value is 0\r\n FHEM to do nothing\r\n"; - Log3 $bname, 3, "AMADCommBridge ($name) - Attribut enableSubCalls is not set or value is 0, FHEM to do nothing"; + Log3( $bname, 4, +"AMADCommBridge ($name) - CommBridge: receive fhem-function command" + ); + + if ( AttrVal( $bname, 'enableSubCalls', 0 ) == 1 ) { + + $response = AnalyzePerlCommand( $bhash, '{' . $fhemCmd . '}' ) + ; # AnalyzePerlCommand is new https://forum.fhem.de/index.php/topic,89619.msg820964.html#msg820964 + } - + else { + + $response = +"header lines: \r\n Attribut enableSubCalls is not set or value is 0\r\n FHEM to do nothing\r\n"; + Log3 $bname, 3, +"AMADCommBridge ($name) - Attribut enableSubCalls is not set or value is 0, FHEM to do nothing"; + } + $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; - + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; + return; - } + } } - - - $response = "header lines: \r\n AMADCommBridge receive incomplete or corrupt Data\r\n FHEM to do nothing\r\n"; + $response = +"header lines: \r\n AMADCommBridge receive incomplete or corrupt Data\r\n FHEM to do nothing\r\n"; $c = $hash->{CD}; print $c "HTTP/1.1 200 OK\r\n", - "Content-Type: text/plain\r\n", - "Connection: close\r\n", - "Content-Length: ".length($response)."\r\n\r\n", - $response; + "Content-Type: text/plain\r\n", + "Connection: close\r\n", + "Content-Length: " . length($response) . "\r\n\r\n", + $response; } - ################## ### my little helper ################## -sub AMADCommBridge_ParseMsg($$) { +sub ParseMsg($$) { - my ($hash, $buffer) = @_; - - my $name = $hash->{NAME}; - my $open = 0; + my ( $hash, $buffer ) = @_; + + my $name = $hash->{NAME}; + my $open = 0; my $close = 0; - my $msg = ''; - my $tail = ''; - - - if($buffer) { - foreach my $c (split //, $buffer) { - if($open == $close && $open > 0) { + my $msg = ''; + my $tail = ''; + + if ($buffer) { + foreach my $c ( split //, $buffer ) { + if ( $open == $close && $open > 0 ) { $tail .= $c; - Log3 $name, 5, "AMADCommBridge ($name) - $open == $close && $open > 0"; - - } elsif(($open == $close) && ($c ne '{')) { - - Log3 $name, 5, "AMADCommBridge ($name) - Garbage character before message: " . $c; - - } else { - - if($c eq '{') { + Log3( $name, 5, + "AMADCommBridge ($name) - $open == $close && $open > 0" ); + + } + elsif ( ( $open == $close ) && ( $c ne '{' ) ) { + + Log3( $name, 5, +"AMADCommBridge ($name) - Garbage character before message: " + . $c ); + + } + else { + + if ( $c eq '{' ) { $open++; - - } elsif($c eq '}') { - + + } + elsif ( $c eq '}' ) { + $close++; } - + $msg .= $c; } } - - if($open != $close) { - + + if ( $open != $close ) { + $tail = $msg; - $msg = ''; + $msg = ''; } } - - Log3 $name, 5, "AMADCommBridge ($name) - return msg: $msg and tail: $tail"; - return ($msg,$tail); + + Log3( $name, 5, + "AMADCommBridge ($name) - return msg: $msg and tail: $tail" ); + return ( $msg, $tail ); } ##### bleibt zu Anschauungszwecken erhalten -#sub AMADCommBridge_Header2Hash($) { +#sub Header2Hash($) { # # my $string = shift; # my %hash = (); @@ -1001,19 +1219,11 @@ sub AMADCommBridge_ParseMsg($$) { # # $value =~ s/^ //; # $hash{$key} = $value; -# } -# +# } +# # return \%hash; #} - - - - - - - - 1; =pod @@ -1068,7 +1278,6 @@ sub AMADCommBridge_ParseMsg($$) {

  • JSON_ERROR - JSON Error message reported by Perl
  • JSON_ERROR_STRING - The string that caused the JSON error message
  • -
  • fhemServerIP - The IP address of the FHEM server, is set by the module based on the JSON string from the installation wizard. Can also be set by user using set command
  • receiveFhemCommand - is set the fhemControlMode attribute to trigger, the reading is set as soon as an FHEM command is sent. A notification can then be triggered.
    If set instead of trigger setControl as value for fhemControlMode, the reading is not executed but the set command executed immediately.
  • receiveVoiceCommand - The speech control is activated by AMAD (set DEVICE activateVoiceInput), the last recognized voice command is written into this reading.
  • @@ -1141,7 +1350,6 @@ sub AMADCommBridge_ParseMsg($$) {

    • JSON_ERROR - JSON Fehlermeldung welche von Perl gemeldet wird
    • JSON_ERROR_STRING - der String welcher die JSON Fehlermeldung verursacht hat
    • -
    • fhemServerIP - die Ip-Adresse des FHEM Servers, wird vom Modul auf Basis des JSON Strings vom Installationsassistenten gesetzt. Kann aber auch mittels set Befehles vom User gesetzt werden
    • receiveFhemCommand - ist das Attribut fhemControlMode auf trigger gestellt, wird das Reading gesetzt sobald ein FHEM Befehl übersendet wird. Hierauf kann dann ein Notify triggern.
      Wird anstelle von trigger setControl als Wert für fhemControlMode eingestellt, wird das Reading nicht gestzt sondern der set Befehl sofort ausgeführt.
    • receiveVoiceCommand - wird die Sprachsteuerung von AMAD aktiviert (set DEVICE activateVoiceInput) so wird der letzte erkannten Sprachbefehle in dieses Reading geschrieben.
    • @@ -1168,4 +1376,52 @@ sub AMADCommBridge_ParseMsg($$) {
    =end html_DE + +=for :application/json;q=META.json 73_AMADCommBridge.pm +{ + "abstract": "Integrates Android devices into FHEM and displays several settings", + "x_lang": { + "de": { + "abstract": "Integriert Android-Geräte in FHEM und zeigt verschiedene Einstellungen an" + } + }, + "keywords": [ + "fhem-mod-device", + "fhem-core", + "Android", + "Tablet", + "Handy", + "AMAD" + ], + "release_status": "stable", + "license": "GPL_2", + "author": [ + "Marko Oldenburg " + ], + "x_fhem_maintainer": [ + "CoolTux" + ], + "x_fhem_maintainer_github": [ + "LeonGaultier" + ], + "prereqs": { + "runtime": { + "requires": { + "FHEM": 5.00918799, + "perl": 5.016, + "Meta": 0, + "Encode": 0, + "JSON": 0, + "HttpUtils": 0, + "TcpServerUtils": 0 + }, + "recommends": { + }, + "suggests": { + } + } + } +} +=end :application/json;q=META.json + =cut diff --git a/fhem/FHEM/74_AMADDevice.pm b/fhem/FHEM/74_AMADDevice.pm index baf56a75f..5a69d545b 100644 --- a/fhem/FHEM/74_AMADDevice.pm +++ b/fhem/FHEM/74_AMADDevice.pm @@ -1,5 +1,5 @@ ############################################################################### -# +# # Developed with Kate # # (c) 2015-2019 Copyright: Marko Oldenburg (leongaultier at gmail dot com) @@ -36,7 +36,7 @@ # # if($@){ # Log3($SELF, 2, "$TYPE ($SELF) - error while request: $@"); -# +# # readingsSingleUpdate($hash, "state", "error", 1); # # return; @@ -44,798 +44,970 @@ # # - - - package main; - -my $missingModul = ""; - use strict; use warnings; +use FHEM::Meta; -eval "use Encode qw(encode encode_utf8);1" or $missingModul .= "Encode "; -eval "use JSON;1" or $missingModul .= "JSON "; - - - -my $modulversion = "4.2.7"; -my $flowsetversion = "4.2.5"; - - - - -# Declare functions -sub AMADDevice_Attr(@); -sub AMADDevice_Notify($$); -sub AMADDevice_checkDeviceState($); -sub AMADDevice_decrypt($); -sub AMADDevice_Define($$); -sub AMADDevice_encrypt($); -sub AMADDevice_GetUpdate($); -sub AMADDevice_Initialize($); -sub AMADDevice_WriteReadings($$); -sub AMADDevice_Set($$@); -sub AMADDevice_Undef($$); -sub AMADDevice_Parse($$); -sub AMADDevice_statusRequest($); -sub AMADDevice_CreateVolumeValue($$@); -sub AMADDevice_CreateTtsMsgValue($@); -sub AMADDevice_CreateScreenValue($$); -sub AMADDevice_CreateChangeBtDeviceValue($$); - - - +my $modulversion = '4.4.0'; +my $flowsetversion = '4.4.0'; sub AMADDevice_Initialize($) { my ($hash) = @_; - - $hash->{Match} = '{"amad": \{"amad_id":.+}}'; + $hash->{Match} = '{"amad": \{"amad_id":.+}}'; + + $hash->{SetFn} = 'FHEM::AMADDevice::Set'; + $hash->{DefFn} = 'FHEM::AMADDevice::Define'; + $hash->{UndefFn} = 'FHEM::AMADDevice::Undef'; + $hash->{AttrFn} = 'FHEM::AMADDevice::Attr'; + $hash->{NotifyFn} = 'FHEM::AMADDevice::Notify'; + $hash->{ParseFn} = 'FHEM::AMADDevice::Parse'; + + $hash->{AttrList} = + 'setOpenApp ' + . 'checkActiveTask ' + . 'setFullscreen:0,1 ' + . 'setScreenOrientation:0,1 ' + . 'setScreenBrightness:noArg ' + . 'setBluetoothDevice ' + . 'setScreenlockPIN ' + . 'setScreenOnForTimer ' + . 'setOpenUrlBrowser ' + . 'setNotifySndFilePath ' + . 'setTtsMsgSpeed ' + . 'setTtsMsgLang:de,en ' + . 'setTtsMsgVol ' + . 'setUserFlowState ' + . 'setVolUpDownStep:1,2,4,5 ' + . 'setVolMax ' + . 'setVolFactor:2,3,4,5 ' + . 'setNotifyVolMax ' + . 'setRingSoundVolMax ' + . 'setAPSSID ' + . 'root:0,1 ' + . 'disable:1 ' + . 'IODev ' + . 'remoteServer:Automagic,Autoremote,TNES,other ' + . 'setTakeScreenshotResolution:1280x720,1920x1080,1920x1200 ' + . 'setTakePictureResolution:800x600,1024x768,1280x720,1600x1200,1920x1080 ' + . 'setTakePictureCamera:Back,Front ' + . $readingFnAttributes; + + foreach my $d ( sort keys %{ $modules{AMADDevice}{defptr} } ) { - $hash->{SetFn} = "AMADDevice_Set"; - $hash->{DefFn} = "AMADDevice_Define"; - $hash->{UndefFn} = "AMADDevice_Undef"; - $hash->{AttrFn} = "AMADDevice_Attr"; - $hash->{NotifyFn} = "AMADDevice_Notify"; - $hash->{ParseFn} = "AMADDevice_Parse"; - - $hash->{AttrList} = "setOpenApp ". - "checkActiveTask ". - "setFullscreen:0,1 ". - "setScreenOrientation:0,1 ". - "setScreenBrightness:noArg ". - "setBluetoothDevice ". - "setScreenlockPIN ". - "setScreenOnForTimer ". - "setOpenUrlBrowser ". - "setNotifySndFilePath ". - "setTtsMsgSpeed ". - "setTtsMsgLang:de,en ". - "setTtsMsgVol ". - "setUserFlowState ". - "setVolUpDownStep:1,2,4,5 ". - "setVolMax ". - "setVolFactor:2,3,4,5 ". - "setNotifyVolMax ". - "setRingSoundVolMax ". - "setAPSSID ". - "root:0,1 ". - "disable:1 ". - "IODev ". - "remoteServer:Automagic,Autoremote,TNES,other ". - "setTakeScreenshotResolution:1280x720,1920x1080,1920x1200 ". - "setTakePictureResolution:800x600,1024x768,1280x720,1600x1200,1920x1080 ". - "setTakePictureCamera:Back,Front ". - $readingFnAttributes; - - foreach my $d(sort keys %{$modules{AMADDevice}{defptr}}) { - my $hash = $modules{AMADDevice}{defptr}{$d}; - $hash->{VERSIONMODUL} = $modulversion; - $hash->{VERSIONFLOWSET} = $flowsetversion; + $hash->{VERSIONMODUL} = $modulversion; + $hash->{VERSIONFLOWSET} = $flowsetversion; } + + return FHEM::Meta::InitMod( __FILE__, $hash ); } -sub AMADDevice_Define($$) { +## unserer packagename +package FHEM::AMADDevice; + +use strict; +use warnings; +use POSIX; +use FHEM::Meta; + +use Data::Dumper; #only for Debugging + +use GPUtils qw(GP_Import) + ; # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt + +my $missingModul = ''; + +eval "use Encode qw(encode encode_utf8);1" or $missingModul .= 'Encode '; +eval "use JSON;1" or $missingModul .= 'JSON '; + +## Import der FHEM Funktionen +BEGIN { + GP_Import( + qw(readingsSingleUpdate + readingsBulkUpdate + readingsBulkUpdateIfChanged + readingsBeginUpdate + readingsEndUpdate + CommandDeleteReading + defs + modules + Log3 + CommandAttr + attr + AttrVal + ReadingsVal + IsDisabled + deviceEvents + init_done + gettimeofday + getUniqueId + InternalTimer + RemoveInternalTimer + IOWrite + ReadingsAge + urlEncode + AssignIoPort) + ); +} + +sub Define($$) { my ( $hash, $def ) = @_; - my @a = split( "[ \t]+", $def ); - - return "too few parameters: define AMADDevice " if( @a != 5 ); - return "Cannot define a AMADDevice device. Perl modul $missingModul is missing." if ( $missingModul ); + my @a = split( '[ \t]+', $def ); + return $@ unless ( FHEM::Meta::SetInternals($hash) ); + return +'too few parameters: define AMADDevice ' + if ( @a != 5 ); + return + 'Cannot define a AMADDevice device. Perl modul ' + . $missingModul + . ' is missing.' + if ($missingModul); - my $name = $a[0]; - my $host = $a[2]; - my $amad_id = $a[3]; - my $remoteServer = $a[4]; - - $hash->{HOST} = $host; - $hash->{AMAD_ID} = $amad_id; - $hash->{VERSIONMODUL} = $modulversion; - $hash->{VERSIONFLOWSET} = $flowsetversion; - $hash->{NOTIFYDEV} = "global,$name"; - - $hash->{PORT} = 8090 if($remoteServer eq 'Automagic'); - $hash->{PORT} = 1817 if($remoteServer eq 'Autoremote'); - $hash->{PORT} = 8765 if($remoteServer eq 'TNES'); - $hash->{PORT} = 1111 if($remoteServer eq 'other'); # Dummy Port for other - return 'typo in field. please use Automagic, Autoremote, TNES or other' - unless ( defined($hash->{PORT}) and $hash->{PORT} ); - - $hash->{helper}{infoErrorCounter} = 0; - $hash->{helper}{setCmdErrorCounter} = 0; - $hash->{helper}{deviceStateErrorCounter} = 0; + my $name = $a[0]; + my $host = $a[2]; + my $amad_id = $a[3]; + my $remoteServer = $a[4]; + $hash->{HOST} = $host; + $hash->{AMAD_ID} = $amad_id; + $hash->{VERSIONMODUL} = $modulversion; + $hash->{VERSIONFLOWSET} = $flowsetversion; + $hash->{NOTIFYDEV} = 'global,' . $name; + $hash->{MODEL} = $remoteServer; + $hash->{PORT} = 8090 if ( $remoteServer eq 'Automagic' ); + $hash->{PORT} = 1817 if ( $remoteServer eq 'Autoremote' ); + $hash->{PORT} = 8765 if ( $remoteServer eq 'TNES' ); + $hash->{PORT} = 1111 if ( $remoteServer eq 'other' ); # Dummy Port for other + return +'typo in field. please use Automagic, Autoremote, TNES or other' + unless ( defined( $hash->{PORT} ) and $hash->{PORT} ); - CommandAttr(undef,"$name IODev $modules{AMADCommBridge}{defptr}{BRIDGE}->{NAME}") if(AttrVal($name,'IODev','none') eq 'none'); + $hash->{helper}{infoErrorCounter} = 0; + $hash->{helper}{setCmdErrorCounter} = 0; + $hash->{helper}{deviceStateErrorCounter} = 0; - my $iodev = AttrVal($name,'IODev','none'); - - AssignIoPort($hash,$iodev) if( !$hash->{IODev} ); - - if(defined($hash->{IODev}->{NAME})) { - Log3 $name, 3, "AMADDevice ($name) - I/O device is " . $hash->{IODev}->{NAME}; - } else { - Log3 $name, 1, "AMADDevice ($name) - no I/O device"; + CommandAttr( undef, + $name . ' IODev ' . $modules{AMADCommBridge}{defptr}{BRIDGE}->{NAME} ) + if ( defined( $modules{AMADCommBridge}{defptr}{BRIDGE}->{NAME} ) + and AttrVal( $name, 'IODev', 'none' ) eq 'none' ); + + my $iodev = AttrVal( $name, 'IODev', 'none' ); + + AssignIoPort( $hash, $iodev ) if ( !$hash->{IODev} ); + + if ( defined( $hash->{IODev}->{NAME} ) ) { + Log3( $name, 3, + "AMADDevice ($name) - I/O device is " . $hash->{IODev}->{NAME} ); + } + else { + Log3( $name, 1, "AMADDevice ($name) - no I/O device" ); } - $iodev = $hash->{IODev}->{NAME}; - + my $d = $modules{AMADDevice}{defptr}{$amad_id}; - - return "AMADDevice device $name on AMADCommBridge $iodev already defined." - if( defined($d) and $d->{IODev} == $hash->{IODev} and $d->{NAME} ne $name ); - + return + 'AMADDevice device ' + . $name + . ' on AMADCommBridge ' + . $iodev + . ' already defined.' + if ( defined($d) + and $d->{IODev} == $hash->{IODev} + and $d->{NAME} ne $name ); + + CommandAttr( undef, $name . ' room AMAD' ) + if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); + CommandAttr( undef, $name . ' remoteServer ' . $remoteServer ) + if ( AttrVal( $name, 'remoteServer', 'none' ) eq 'none' ); - CommandAttr(undef,"$name room AMAD") if(AttrVal($name,'room','none') eq 'none'); - CommandAttr(undef,"$name remoteServer $remoteServer") if(AttrVal($name,'remoteServer','none') eq 'none'); - readingsBeginUpdate($hash); - readingsBulkUpdateIfChanged( $hash, "state", "initialized",1); - readingsBulkUpdateIfChanged( $hash, "deviceState", "unknown",1); - readingsEndUpdate($hash,1); - - - Log3 $name, 3, "AMADDevice ($name) - defined with AMAD_ID: $amad_id on port $hash->{PORT}"; + readingsBulkUpdateIfChanged( $hash, 'state', 'initialized', 1 ); + readingsBulkUpdateIfChanged( $hash, 'deviceState', 'unknown', 1 ); + readingsEndUpdate( $hash, 1 ); + Log3( $name, 3, +"AMADDevice ($name) - defined with AMAD_ID: $amad_id on port $hash->{PORT}" + ); + $hash->{NOTIFYDEV} .= ',' . $iodev + if ( defined($iodev) ); $modules{AMADDevice}{defptr}{$amad_id} = $hash; return undef; } -sub AMADDevice_Undef($$) { +sub Undef($$) { - my ( $hash, $arg ) = @_; - my $name = $hash->{NAME}; - my $amad_id = $hash->{AMAD_ID}; - - - RemoveInternalTimer( $hash ); + my ( $hash, $arg ) = @_; + my $name = $hash->{NAME}; + my $amad_id = $hash->{AMAD_ID}; + + RemoveInternalTimer($hash); delete $modules{AMADDevice}{defptr}{$amad_id}; return undef; } -sub AMADDevice_Attr(@) { +sub Attr(@) { my ( $cmd, $name, $attrName, $attrVal ) = @_; my $hash = $defs{$name}; - + my $orig = $attrVal; - if( $attrName eq "remoteServer" ) { - if( $cmd eq "set" ) { - if( $attrVal eq "Automagic" ) { - $hash->{PORT} = 8090; - Log3 $name, 3, "AMADDevice ($name) - set remoteServer to Automagic"; - - } elsif( $attrVal eq "Autoremote" ) { - $hash->{PORT} = 1817; - Log3 $name, 3, "AMADDevice ($name) - set remoteServer to Autoremote"; - - } elsif( $attrVal eq "TNES" ) { - $hash->{PORT} = 8765; - Log3 $name, 3, "AMADDevice ($name) - set remoteServer to TNES"; - - } elsif( $attrVal eq "other" ) { - $hash->{PORT} = 1111; - Log3 $name, 3, "AMADDevice ($name) - set remoteServer to other"; + if ( $attrName eq 'remoteServer' ) { + if ( $cmd eq 'set' ) { + if ( $attrVal eq 'Automagic' ) { + $hash->{PORT} = 8090; + Log3( $name, 3, + "AMADDevice ($name) - set remoteServer to Automagic" ); + } - - $hash->{DEF} = "$hash->{HOST} $hash->{AMAD_ID} $attrVal"; + elsif ( $attrVal eq 'Autoremote' ) { + $hash->{PORT} = 1817; + Log3( $name, 3, + "AMADDevice ($name) - set remoteServer to Autoremote" ); + + } + elsif ( $attrVal eq 'TNES' ) { + $hash->{PORT} = 8765; + Log3( $name, 3, + "AMADDevice ($name) - set remoteServer to TNES" ); + + } + elsif ( $attrVal eq 'other' ) { + $hash->{PORT} = 1111; + Log3( $name, 3, + "AMADDevice ($name) - set remoteServer to other" ); + } + + $hash->{DEF} = + $hash->{HOST} . ' ' . $hash->{AMAD_ID} . ' ' . $attrVal; } } - - elsif( $attrName eq "disable" ) { - if( $cmd eq "set" ) { - if( $attrVal eq "0" ) { - readingsSingleUpdate ( $hash, "state", "active", 1 ); - Log3 $name, 3, "AMADDevice ($name) - enabled"; - } else { + + elsif ( $attrName eq 'disable' ) { + if ( $cmd eq 'set' ) { + if ( $attrVal eq '0' ) { + readingsSingleUpdate( $hash, 'state', 'active', 1 ); + Log3( $name, 3, "AMADDevice ($name) - enabled" ); + } + else { RemoveInternalTimer($hash); - readingsSingleUpdate ( $hash, "state", "disabled", 1 ); - Log3 $name, 3, "AMADDevice ($name) - disabled"; + readingsSingleUpdate( $hash, 'state', 'disabled', 1 ); + Log3( $name, 3, "AMADDevice ($name) - disabled" ); } - - } else { - readingsSingleUpdate ( $hash, "state", "active", 1 ); - Log3 $name, 3, "AMADDevice ($name) - enabled"; + + } + else { + readingsSingleUpdate( $hash, 'state', 'active', 1 ); + Log3( $name, 3, "AMADDevice ($name) - enabled" ); } } - - elsif( $attrName eq "checkActiveTask" ) { - if( $cmd eq "del" ) { - CommandDeleteReading( undef, "$name checkActiveTask" ); + + elsif ( $attrName eq 'checkActiveTask' ) { + if ( $cmd eq 'del' ) { + CommandDeleteReading( undef, $name . ' checkActiveTask' ); } - - Log3 $name, 3, "AMADDevice ($name) - $cmd $attrName $attrVal and run statusRequest"; + + Log3( $name, 3, + "AMADDevice ($name) - $cmd $attrName $attrVal and run statusRequest" + ); } - - elsif( $attrName eq "setScreenlockPIN" ) { - if( $cmd eq "set" and $attrVal ) { - - $attrVal = AMADDevice_encrypt($attrVal); - - } else { - - CommandDeleteReading( undef, "$name screenLock" ); + + elsif ( $attrName eq 'setScreenlockPIN' ) { + if ( $cmd eq 'set' and $attrVal ) { + + $attrVal = encrypt($attrVal); + + } + else { + + CommandDeleteReading( undef, $name . ' screenLock' ); } } - - elsif( $attrName eq "setUserFlowState" ) { - if( $cmd eq "del" ) { - - CommandDeleteReading( undef, "$name userFlowState" ); + + elsif ( $attrName eq 'setUserFlowState' ) { + if ( $cmd eq 'del' ) { + + CommandDeleteReading( undef, $name . ' userFlowState' ); } - - Log3 $name, 3, "AMADDevice ($name) - $cmd $attrName $attrVal and run statusRequest"; + + Log3( $name, 3, + "AMADDevice ($name) - $cmd $attrName $attrVal and run statusRequest" + ); } - - - - if( $cmd eq "set" ) { - if( $attrVal and $orig ne $attrVal ) { - + + if ( $cmd eq 'set' ) { + if ( $attrVal and $orig ne $attrVal ) { + $attr{$name}{$attrName} = $attrVal; - return $attrName ." set to ". $attrVal if( $init_done ); + return $attrName . ' set to ' . $attrVal if ($init_done); } } - + return undef; } -sub AMADDevice_Notify($$) { +sub Notify($$) { - my ($hash,$dev) = @_; + my ( $hash, $dev ) = @_; my $name = $hash->{NAME}; - return if (IsDisabled($name)); - + return if ( IsDisabled($name) ); + my $devname = $dev->{NAME}; my $devtype = $dev->{TYPE}; - my $events = deviceEvents($dev,1); - return if (!$events); + my $events = deviceEvents( $dev, 1 ); + return if ( !$events ); + statusRequest($hash) + if ( + ( + grep /^DELETEATTR.$name.setAPSSID$/, + @{$events} + or grep /^ATTR.$name.setAPSSID.*/, + @{$events} + or grep /^DELETEATTR.$name.checkActiveTask$/, + @{$events} + or grep /^ATTR.$name.checkActiveTask.*/, + @{$events} + or grep /^DELETEATTR.$name.setUserFlowState$/, + @{$events} + or grep /^ATTR.$name.setUserFlowState.*/, + @{$events} + or grep /^ATTR.$hash->{IODev}->{NAME}.fhemServerIP.*/, + @{$events} + ) + and $devname eq 'global' + and $init_done + ); - AMADDevice_statusRequest($hash) if( (grep /^DELETEATTR.$name.setAPSSID$/,@{$events} - or grep /^ATTR.$name.setAPSSID.*/,@{$events} - or grep /^DELETEATTR.$name.checkActiveTask$/,@{$events} - or grep /^ATTR.$name.checkActiveTask.*/,@{$events} - or grep /^DELETEATTR.$name.setUserFlowState$/,@{$events} - or grep /^ATTR.$name.setUserFlowState.*/,@{$events}) - and $init_done and $devname eq 'global' ); + GetUpdate($hash) + if ( + ( + grep /^DEFINED.$name$/, + @{$events} + or grep /^INITIALIZED$/, + @{$events} + or grep /^MODIFIED.$name$/, + @{$events} + ) + and $devname eq 'global' + and $init_done + ); - AMADDevice_GetUpdate($hash) if( (grep /^DEFINED.$name$/,@{$events} - or grep /^INITIALIZED$/,@{$events} - or grep /^MODIFIED.$name$/,@{$events}) - and $devname eq 'global' and $init_done ); - - AMADDevice_checkDeviceState($hash) if( (grep /^DELETEATTR.$name.disable$/,@{$events} - or grep /^ATTR.$name.disable.0$/,@{$events}) - and $devname eq 'global' and $init_done ); + checkDeviceState($hash) + if ( + ( + grep /^DELETEATTR.$name.disable$/, + @{$events} + or grep /^ATTR.$name.disable.0$/, + @{$events} + ) + and $devname eq 'global' + and $init_done + ); return; } -sub AMADDevice_GetUpdate($) { +sub GetUpdate($) { - my ( $hash ) = @_; - my $name = $hash->{NAME}; - my $bname = $hash->{IODev}->{NAME}; - - - RemoveInternalTimer( $hash ); - - if( $init_done and ( ReadingsVal( $name, "deviceState", "unknown" ) eq "unknown" or ReadingsVal( $name, "deviceState", "online" ) eq "online" ) and AttrVal( $name, "disable", 0 ) ne "1" and ReadingsVal( $bname, "fhemServerIP", "not set" ) ne "not set" ) { + my ($hash) = @_; + my $name = $hash->{NAME}; + my $bname = $hash->{IODev}->{NAME}; - AMADDevice_statusRequest($hash); - AMADDevice_checkDeviceState( $hash ); - - } else { + RemoveInternalTimer($hash); - Log3 $name, 4, "AMADDevice ($name) - GetUpdate, FHEM or Device not ready yet"; - Log3 $name, 3, "AMADDevice ($bname) - GetUpdate, Please set $bname fhemServerIP NOW!" if( ReadingsVal( $bname, "fhemServerIP", "none" ) eq "none" ); + if ( + $init_done + and ( ReadingsVal( $name, 'deviceState', 'unknown' ) eq 'unknown' + or ReadingsVal( $name, 'deviceState', 'online' ) eq 'online' ) + and AttrVal( $name, 'disable', 0 ) ne 1 + and AttrVal( $bname, 'fhemServerIP', 'not set' ) ne 'not set' + ) + { - InternalTimer( gettimeofday()+30, "AMADDevice_GetUpdate", $hash, 0 ); + statusRequest($hash); + checkDeviceState($hash); + + } + else { + + Log3( $name, 4, + "AMADDevice ($name) - GetUpdate, FHEM or Device not ready yet" ); + + InternalTimer( gettimeofday() + 30, + 'FHEM::AMADDevice::GetUpdate', $hash, 0 ); } } -sub AMADDevice_statusRequest($) { +sub statusRequest($) { - my $hash = shift; - my $name = $hash->{NAME}; - - my $host = $hash->{HOST}; - my $port = $hash->{PORT}; - my $amad_id = $hash->{AMAD_ID}; - my $uri = $hash->{HOST} . ":" . $hash->{PORT}; - my $header = 'Connection: close'; - my $path; - my $method; - - - my $activetask = AttrVal( $name, "checkActiveTask", "none" ); - my $userFlowState = AttrVal( $name, "setUserFlowState", "none" ); - my $apssid = AttrVal( $name, "setAPSSID", "none" ); - my $fhemip = ReadingsVal($hash->{IODev}->{NAME}, "fhemServerIP", "none"); - my $fhemCtlMode = AttrVal($hash->{IODev}->{NAME},'fhemControlMode','none' ); - my $bport = $hash->{IODev}->{PORT}; - - $header .= "\r\nfhemip: $fhemip\r\nfhemdevice: $name\r\nactivetask: $activetask\r\napssid: $apssid\r\nbport: $bport\r\nuserflowstate: $userFlowState\r\nfhemctlmode: $fhemCtlMode"; - - $method = "GET" if( AttrVal($name,'remoteServer','Automagic') eq 'Automagic' ); - $method = "POST" if (AttrVal($name,'remoteServer','Automagic') ne 'Automagic' ); - - $path ="/fhem-amad/deviceInfo/"; # Pfad muß so im Automagic als http request Trigger drin stehen - - - IOWrite($hash,$amad_id,$uri,$path,$header,$method); - Log3 $name, 5, "AMADDevice ($name) - IOWrite: $uri $method IODevHash=$hash->{IODev}"; -} - -sub AMADDevice_WriteReadings($$) { - - my ( $hash, $decode_json ) = @_; - + my $hash = shift; my $name = $hash->{NAME}; + my $host = $hash->{HOST}; + my $port = $hash->{PORT}; + my $amad_id = $hash->{AMAD_ID}; + my $uri = $hash->{HOST} . ':' . $hash->{PORT}; + my $header = 'Connection: close'; + my $path; + my $method; + + my $activetask = AttrVal( $name, 'checkActiveTask', 'none' ); + my $userFlowState = AttrVal( $name, 'setUserFlowState', 'none' ); + my $apssid = AttrVal( $name, 'setAPSSID', 'none' ); + my $fhemip = AttrVal( $hash->{IODev}->{NAME}, 'fhemServerIP', 'none' ); + my $fhemCtlMode = + AttrVal( $hash->{IODev}->{NAME}, 'fhemControlMode', 'none' ); + my $bport = $hash->{IODev}->{PORT}; + + $header .= +"\r\nfhemip: $fhemip\r\nfhemdevice: $name\r\nactivetask: $activetask\r\napssid: $apssid\r\nbport: $bport\r\nuserflowstate: $userFlowState\r\nfhemctlmode: $fhemCtlMode"; + + $method = 'GET' + if ( AttrVal( $name, 'remoteServer', 'Automagic' ) eq 'Automagic' ); + $method = 'POST' + if ( AttrVal( $name, 'remoteServer', 'Automagic' ) ne 'Automagic' ); + + $path = '/fhem-amad/deviceInfo/' + ; # Pfad muß so im Automagic als http request Trigger drin stehen + + IOWrite( $hash, $amad_id, $uri, $path, $header, $method ); + Log3( $name, 5, + "AMADDevice ($name) - IOWrite: $uri $method IODevHash=$hash->{IODev}" ); +} + +sub WriteReadings($$) { + + my ( $hash, $decode_json ) = @_; + + my $name = $hash->{NAME}; ############################ #### schreiben der Readings - Log3 $name, 5, "AMADDevice ($name) - Processing data: $decode_json"; - readingsSingleUpdate( $hash, "state", "active", 1) if( ReadingsVal( $name, "state", 0 ) ne "initialized" and ReadingsVal( $name, "state", 0 ) ne "active" ); - + Log3( $name, 5, "AMADDevice ($name) - Processing data: $decode_json" ); + readingsSingleUpdate( $hash, 'state', 'active', 1 ) + if ( ReadingsVal( $name, 'state', 0 ) ne 'initialized' + and ReadingsVal( $name, 'state', 0 ) ne 'active' ); + ### Event Readings my $t; my $v; - - + readingsBeginUpdate($hash); - - while( ( $t, $v ) = each %{$decode_json->{payload}} ) { - - $v =~ s/\bnull\b/off/g if( ($t eq "nextAlarmDay" or $t eq "nextAlarmTime") and $v eq "null" ); + + while ( ( $t, $v ) = each %{ $decode_json->{payload} } ) { + + $v =~ s/\bnull\b/off/g + if ( ( $t eq 'nextAlarmDay' or $t eq 'nextAlarmTime' ) + and $v eq 'null' ); $v =~ s/\bnull\b//g; $v = encode_utf8($v); - - readingsBulkUpdateIfChanged($hash, $t, $v, 1) if( defined( $v ) and ($t ne 'deviceState' - or $t ne 'incomingCallerName' - or $t ne 'incomingCallerNumber' - or $t ne 'incomingTelegramMessage' - or $t ne 'incomingSmsMessage' - or $t ne 'incomingWhatsAppMessage' - or $t ne 'nfcLastTagID') - ); - readingsBulkUpdateIfChanged( $hash, $t, ($v / AttrVal($name,'setVolFactor',1)) ) if( $t eq 'volume' and AttrVal($name,'setVolFactor',1) > 1 ); - readingsBulkUpdate( $hash, '.'.$t, $v ) if( $t eq 'deviceState' ); - readingsBulkUpdate( $hash, $t, $v ) if( defined( $v ) and ($t eq 'incomingCallerName' - or $t eq 'incomingCallerNumber' - or $t eq 'incomingTelegramMessage' - or $t eq 'incomingSmsMessage' - or $t eq 'incomingWhatsAppMessage' - or $t eq 'nfcLastTagID') - ); + readingsBulkUpdateIfChanged( $hash, $t, $v, 1 ) + if ( + defined($v) + and ( $t ne 'deviceState' + or $t ne 'incomingCallerName' + or $t ne 'incomingCallerNumber' + or $t ne 'incomingTelegramMessage' + or $t ne 'incomingSmsMessage' + or $t ne 'incomingWhatsAppMessage' + or $t ne 'nfcLastTagID' ) + ); + + readingsBulkUpdateIfChanged( $hash, $t, + ( $v / AttrVal( $name, 'setVolFactor', 1 ) ) ) + if ( $t eq 'volume' and AttrVal( $name, 'setVolFactor', 1 ) > 1 ); + readingsBulkUpdate( $hash, '.' . $t, $v ) if ( $t eq 'deviceState' ); + readingsBulkUpdate( $hash, $t, $v ) + if ( + defined($v) + and ( $t eq 'incomingCallerName' + or $t eq 'incomingCallerNumber' + or $t eq 'incomingTelegramMessage' + or $t eq 'incomingSmsMessage' + or $t eq 'incomingWhatsAppMessage' + or $t eq 'nfcLastTagID' ) + ); } - - readingsBulkUpdateIfChanged( $hash, "deviceState", "offline", 1 ) if( $decode_json->{payload}{airplanemode} and $decode_json->{payload}{airplanemode} eq "on" ); - readingsBulkUpdateIfChanged( $hash, "deviceState", "online", 1 ) if( $decode_json->{payload}{airplanemode} and $decode_json->{payload}{airplanemode} eq "off" ); - readingsBulkUpdateIfChanged( $hash, "lastStatusRequestState", "statusRequest_done", 1 ); - - if( ReadingsVal($name,'volume',1) > 0 ) { - readingsBulkUpdateIfChanged( $hash, "mute", "off", 1 ); - } else { - readingsBulkUpdateIfChanged( $hash, "mute", "on", 1 ); + readingsBulkUpdateIfChanged( $hash, 'deviceState', 'offline', 1 ) + if ( $decode_json->{payload}{airplanemode} + and $decode_json->{payload}{airplanemode} eq 'on' ); + readingsBulkUpdateIfChanged( $hash, 'deviceState', 'online', 1 ) + if ( $decode_json->{payload}{airplanemode} + and $decode_json->{payload}{airplanemode} eq 'off' ); + + readingsBulkUpdateIfChanged( $hash, 'lastStatusRequestState', + 'statusRequest_done', 1 ); + + if ( ReadingsVal( $name, 'volume', 1 ) > 0 ) { + readingsBulkUpdateIfChanged( $hash, 'mute', 'off', 1 ); + } + else { + readingsBulkUpdateIfChanged( $hash, 'mute', 'on', 1 ); } $hash->{helper}{infoErrorCounter} = 0; ### End Response Processing - - readingsBulkUpdateIfChanged( $hash, "state", "active", 1 ) if( ReadingsVal( $name, "state", 0 ) eq "initialized" ); + + readingsBulkUpdateIfChanged( $hash, 'state', 'active', 1 ) + if ( ReadingsVal( $name, 'state', 0 ) eq 'initialized' ); readingsEndUpdate( $hash, 1 ); - - $hash->{helper}{deviceStateErrorCounter} = 0 if( $hash->{helper}{deviceStateErrorCounter} > 0 and ReadingsVal( $name, "deviceState", "offline") eq "online" ); - + + $hash->{helper}{deviceStateErrorCounter} = 0 + if ( $hash->{helper}{deviceStateErrorCounter} > 0 + and ReadingsVal( $name, 'deviceState', 'offline' ) eq 'online' ); + return undef; } -sub AMADDevice_Set($$@) { +sub Set($$@) { - my ($hash, $name, @aa) = @_; - my ($cmd, @args) = @aa; + my ( $hash, $name, @aa ) = @_; + my ( $cmd, @args ) = @aa; - my $amad_id = $hash->{AMAD_ID}; - my $header = 'Connection: close'; - my $uri = $hash->{HOST} . ":" . $hash->{PORT}; - my $path; + my $amad_id = $hash->{AMAD_ID}; + my $header = 'Connection: close'; + my $uri = $hash->{HOST} . ':' . $hash->{PORT}; + my $path = '/fhem-amad/setCommands/'; my $method; - - my @playerList = ('GoogleMusic','SamsungMusic','AmazonMusic','SpotifyMusic','TuneinRadio','AldiMusic','YouTube', - 'YouTubeKids','VlcPlayer','Audible','Deezer','Poweramp','MXPlayerPro'); - my @playerCmd = ('mediaPlay','mediaStop','mediaNext','mediaBack'); - - my $volMax = AttrVal($name,'setVolMax',15); - my $notifyVolMax = AttrVal($name,'setNotifyVolMax',7); - my $ringSoundVolMax = AttrVal($name,'setRingSoundVolMax',7); - - if( lc $cmd eq 'screenmsg' ) { - my $msg = join( " ", @args ); + my @playerList = ( + 'GoogleMusic', 'SamsungMusic', 'AmazonMusic', 'SpotifyMusic', + 'TuneinRadio', 'AldiMusic', 'YouTube', 'YouTubeKids', + 'VlcPlayer', 'Audible', 'Deezer', 'Poweramp', + 'MXPlayerPro' + ); + my @playerCmd = ( 'mediaPlay', 'mediaStop', 'mediaNext', 'mediaBack' ); - $path = "/fhem-amad/setCommands/screenMsg?message=".urlEncode($msg); - $method = "POST"; - } - - elsif( lc $cmd eq 'ttsmsg' ) { - my ($msg,$speed,$lang,$ttsmsgvol) = AMADDevice_CreateTtsMsgValue($hash,@args); - - $path = "/fhem-amad/setCommands/ttsMsg?message=".urlEncode($msg)."&msgspeed=".$speed."&msglang=".$lang."&msgvol=".$ttsmsgvol; - $method = "POST"; - } - - elsif( lc $cmd eq 'userflowstate' ) { - my $datas = join( " ", @args ); - my ($flow,$state) = split( ":", $datas); + my $volMax = AttrVal( $name, 'setVolMax', 15 ); + my $notifyVolMax = AttrVal( $name, 'setNotifyVolMax', 7 ); + my $ringSoundVolMax = AttrVal( $name, 'setRingSoundVolMax', 7 ); - $path = "/fhem-amad/setCommands/flowState?flowstate=".$state."&flowname=".urlEncode($flow); - $method = "POST"; - } - - elsif( lc $cmd eq 'userflowrun' ) { - my $flow = join( " ", @args ); + if ( lc $cmd eq 'screenmsg' ) { + my $msg = join( ' ', @args ); - $path = "/fhem-amad/setCommands/flowRun?flowname=".urlEncode($flow); - $method = "POST"; + $path .= 'screenMsg?message=' . urlEncode($msg); + $method = 'POST'; } - - elsif( lc $cmd eq 'volume' or $cmd eq 'mute' or $cmd =~ 'volume[Down|Up]' ) { - my $vol = AMADDevice_CreateVolumeValue($hash,$cmd,@args); - - $path = "/fhem-amad/setCommands/setVolume?volume=$vol"; - $method = "POST"; - } - - elsif( lc $cmd eq 'volumenotification' ) { - my $volnote = join( " ", @args ); - $path = "/fhem-amad/setCommands/setNotifiVolume?notifivolume=$volnote"; - $method = "POST"; - } - - elsif( lc $cmd eq 'volumeringsound' ) { - my $volring = join( " ", @args ); + elsif ( lc $cmd eq 'ttsmsg' ) { + my ( $msg, $speed, $lang, $ttsmsgvol ) = + CreateTtsMsgValue( $hash, @args ); - $path = "/fhem-amad/setCommands/setRingSoundVolume?ringsoundvolume=$volring"; - $method = "POST"; + $path .= + 'ttsMsg?message=' + . urlEncode($msg) + . '&msgspeed=' + . $speed + . '&msglang=' + . $lang + . '&msgvol=' + . $ttsmsgvol; + $method = 'POST'; } - - elsif( lc $cmd =~ /^media/ ) { - my $mplayer = join( " ", @args ); - $path = "/fhem-amad/setCommands/multimediaControl?button=".$cmd."&mplayer=".$mplayer; - $method = "POST"; + elsif ( lc $cmd eq 'userflowstate' ) { + my $datas = join( ' ', @args ); + my ( $flow, $state ) = split( ':', $datas ); + + $path .= + 'flowState?flowstate=' . $state . '&flowname=' . urlEncode($flow); + $method = 'POST'; } - - elsif( lc $cmd eq 'screenbrightness' ) { - my $bri = join( " ", @args ); - $path = "/fhem-amad/setCommands/setBrightness?brightness=$bri"; - $method = "POST"; + elsif ( lc $cmd eq 'userflowrun' ) { + my $flow = join( ' ', @args ); + + $path .= 'flowRun?flowname=' . urlEncode($flow); + $method = 'POST'; } - - elsif( lc $cmd eq 'screenbrightnessmode' ) { - my $mode = join( " ", @args ); - $path = "/fhem-amad/setCommands/setBrightnessMode?brightnessmode=".($mode eq 'on' ? 1 : 0); - $method = "POST"; + elsif ( lc $cmd eq 'volume' or $cmd eq 'mute' or $cmd =~ 'volume[Down|Up]' ) + { + my $vol = CreateVolumeValue( $hash, $cmd, @args ); + + $path .= 'setVolume?volume=' . $vol; + $method = 'POST'; } - - elsif( lc $cmd eq 'screen' ) { - my $mod = join( " ", @args ); + elsif ( lc $cmd eq 'volumenotification' ) { + my $volnote = join( ' ', @args ); - $path = AMADDevice_CreateScreenValue($hash,$mod); - return "Please set \"setScreenlockPIN\" Attribut first" - unless($path ne 'NO PIN'); - $method = "POST"; + $path .= 'setNotifiVolume?notifivolume=' . $volnote; + $method = 'POST'; } - - elsif( lc $cmd eq 'screenorientation' ) { - - my $mod = join( " ", @args ); - $path = "/fhem-amad/setCommands/setScreenOrientation?orientation=$mod"; - $method = "POST"; - } - - elsif( lc $cmd eq 'activatevoiceinput' ) { - $path = "/fhem-amad/setCommands/setvoicecmd"; - $method = "POST"; - } - - elsif( lc $cmd eq 'screenfullscreen' ) { - my $mod = join( " ", @args ); + elsif ( lc $cmd eq 'volumeringsound' ) { + my $volring = join( ' ', @args ); - $path = "/fhem-amad/setCommands/setScreenFullscreen?fullscreen=$mod"; - $method = "POST"; + $path .= 'setRingSoundVolume?ringsoundvolume=' . $volring; + $method = 'POST'; + } + + elsif ( lc $cmd =~ /^media/ ) { + my $mplayer = join( ' ', @args ); + + $path .= 'multimediaControl?button=' . $cmd . '&mplayer=' . $mplayer; + $method = 'POST'; + } + + elsif ( lc $cmd eq 'screenbrightness' ) { + my $bri = join( ' ', @args ); + + $path .= 'setBrightness?brightness=' . $bri; + $method = 'POST'; + } + + elsif ( lc $cmd eq 'screenbrightnessmode' ) { + my $mode = join( ' ', @args ); + + $path .= + 'setBrightnessMode?brightnessmode=' . ( $mode eq 'on' ? 1 : 0 ); + $method = 'POST'; + } + + elsif ( lc $cmd eq 'screen' ) { + my $mod = join( ' ', @args ); + + $path = CreateScreenValue( $hash, $mod ); + return 'Please set "setScreenlockPIN" Attribut first' + unless ( $path ne 'NO PIN' ); + $method = 'POST'; + } + + elsif ( lc $cmd eq 'screenorientation' ) { + + my $mod = join( ' ', @args ); + + $path .= 'setScreenOrientation?orientation=' . $mod; + $method = 'POST'; + } + + elsif ( lc $cmd eq 'activatevoiceinput' ) { + $path .= 'setvoicecmd'; + $method = 'POST'; + } + + elsif ( lc $cmd eq 'screenfullscreen' ) { + my $mod = join( ' ', @args ); + + $path .= 'setScreenFullscreen?fullscreen=' . $mod; + $method = 'POST'; readingsSingleUpdate( $hash, $cmd, $mod, 1 ); } - - elsif( lc $cmd eq 'openurl' ) { - my $openurl = join( " ", @args ); - my $browser = AttrVal( $name, "setOpenUrlBrowser", "com.android.chrome|com.google.android.apps.chrome.Main" ); + + elsif ( lc $cmd eq 'openurl' ) { + my $openurl = join( ' ', @args ); + my $browser = AttrVal( $name, 'setOpenUrlBrowser', + 'com.android.chrome|com.google.android.apps.chrome.Main' ); my @browserapp = split( /\|/, $browser ); - $path = "/fhem-amad/setCommands/openURL?url=".$openurl."&browserapp=".$browserapp[0]."&browserappclass=".$browserapp[1]; - $method = "POST"; - } - - elsif (lc $cmd eq 'nextalarmtime') { - my $value = join( " ", @args ); - my @alarm = split( ":", $value ); - - $path = "/fhem-amad/setCommands/setAlarm?hour=".$alarm[0]."&minute=".$alarm[1]; - $method = "POST"; - } - - elsif (lc $cmd eq 'timer') { - my $timer = join( " ", @args ); - - $path = "/fhem-amad/setCommands/setTimer?minute=$timer"; - $method = "POST"; + $path .= + 'openURL?url=' + . $openurl + . '&browserapp=' + . $browserapp[0] + . '&browserappclass=' + . $browserapp[1]; + $method = 'POST'; } - elsif( lc $cmd eq 'statusrequest' ) { + elsif ( lc $cmd eq 'nextalarmtime' ) { + my $value = join( ' ', @args ); + my @alarm = split( ':', $value ); - AMADDevice_statusRequest($hash); - return; + $path .= 'setAlarm?hour=' . $alarm[0] . '&minute=' . $alarm[1]; + $method = 'POST'; } - elsif( lc $cmd eq 'openapp' ) { - my $app = join( " ", @args ); + elsif ( lc $cmd eq 'timer' ) { + my $timer = join( ' ', @args ); - $path = "/fhem-amad/setCommands/openApp?app=".$app; - $method = "POST"; + $path .= 'setTimer?minute=' . $timer; + $method = 'POST'; } - - elsif( lc $cmd eq 'nfc' ) { - my $mod = join( " ", @args ); - $path = "/fhem-amad/setCommands/setnfc?nfc=".$mod; - $method = "POST"; + elsif ( lc $cmd eq 'statusrequest' ) { + + statusRequest($hash); + return; } - - elsif( lc $cmd eq 'system' ) { - my $systemcmd = join( " ", @args ); - $path = "/fhem-amad/setCommands/systemcommand?syscmd=$systemcmd"; - $method = "POST"; - readingsSingleUpdate( $hash, "airplanemode", "on", 1 ) if( $systemcmd eq "airplanemodeON" ); - readingsSingleUpdate( $hash, "deviceState", "offline", 1 ) if( $systemcmd eq "airplanemodeON" or $systemcmd eq "shutdown" ); + elsif ( lc $cmd eq 'openapp' ) { + my $app = join( ' ', @args ); + + $path .= 'openApp?app=' . $app; + $method = 'POST'; } - - elsif( lc $cmd eq 'donotdisturb' ) { - my $disturbmod = join( " ", @args ); - $path = "/fhem-amad/setCommands/donotdisturb?disturbmod=$disturbmod"; - $method = "POST"; + elsif ( lc $cmd eq 'nfc' ) { + my $mod = join( ' ', @args ); + + $path .= 'setnfc?nfc=' . $mod; + $method = 'POST'; } - - elsif( lc $cmd eq 'bluetooth' ) { - my $mod = join( " ", @args ); - $path = "/fhem-amad/setCommands/setbluetooth?bluetooth=$mod"; - $method = "POST"; + elsif ( lc $cmd eq 'system' ) { + my $systemcmd = join( ' ', @args ); + + $path .= 'systemcommand?syscmd=' . $systemcmd; + $method = 'POST'; + readingsSingleUpdate( $hash, 'airplanemode', 'on', 1 ) + if ( $systemcmd eq 'airplanemodeON' ); + readingsSingleUpdate( $hash, 'deviceState', 'offline', 1 ) + if ( $systemcmd eq 'airplanemodeON' or $systemcmd eq 'shutdown' ); } - - elsif( lc $cmd eq 'notifysndfile' ) { - my $notify = join( " ", @args ); - my $filepath = AttrVal( $name, "setNotifySndFilePath", "/storage/emulated/0/Notifications/" ); - $path = "/fhem-amad/setCommands/playnotifysnd?notifyfile=".$notify."¬ifypath=".$filepath; - $method = "POST"; + elsif ( lc $cmd eq 'donotdisturb' ) { + my $disturbmod = join( ' ', @args ); + + $path .= 'donotdisturb?disturbmod=' . $disturbmod; + $method = 'POST'; } - - elsif( lc $cmd eq 'changetobtdevice' ) { - my $swToBtDevice = join( " ", @args ); - my ($swToBtMac,$btDeviceOne,$btDeviceTwo) = AMADDevice_CreateChangeBtDeviceValue($hash,$swToBtDevice); - $path = "/fhem-amad/setCommands/setbtdevice?swToBtDeviceMac=".$swToBtMac."&btDeviceOne=".$btDeviceOne."&btDeviceTwo=".$btDeviceTwo; - $method = "POST"; + elsif ( lc $cmd eq 'bluetooth' ) { + my $mod = join( ' ', @args ); + + $path .= 'setbluetooth?bluetooth=' . $mod; + $method = 'POST'; } - - elsif( lc $cmd eq 'clearnotificationbar' ) { - my $appname = join( " ", @args ); - $path = "/fhem-amad/setCommands/clearnotificationbar?app=$appname"; - $method = "POST"; + elsif ( lc $cmd eq 'notifysndfile' ) { + my $notify = join( ' ', @args ); + my $filepath = AttrVal( $name, 'setNotifySndFilePath', + '/storage/emulated/0/Notifications/' ); + + $path .= + 'playnotifysnd?notifyfile=' . $notify . '¬ifypath=' . $filepath; + $method = 'POST'; } - - elsif( lc $cmd eq 'vibrate' ) { - $path = "/fhem-amad/setCommands/setvibrate"; - $method = "POST"; + elsif ( lc $cmd eq 'changetobtdevice' ) { + my $swToBtDevice = join( ' ', @args ); + + my ( $swToBtMac, $btDeviceOne, $btDeviceTwo ) = + CreateChangeBtDeviceValue( $hash, $swToBtDevice ); + $path .= + 'setbtdevice?swToBtDeviceMac=' + . $swToBtMac + . '&btDeviceOne=' + . $btDeviceOne + . '&btDeviceTwo=' + . $btDeviceTwo; + $method = 'POST'; } - - elsif( lc $cmd eq 'showhomescreen' ) { - $path = "/fhem-amad/setCommands/showhomescreen"; - $method = "POST"; + elsif ( lc $cmd eq 'clearnotificationbar' ) { + my $appname = join( ' ', @args ); + + $path .= 'clearnotificationbar?app=' . $appname; + $method = 'POST'; } - - elsif( lc $cmd eq 'takepicture' ) { - return "Please set \"setTakePictureResolution\" Attribut first" - unless(AttrVal($name,'setTakePictureResolution','none') ne 'none'); - - return "Please set \"setTakePictureCamera\" Attribut first" - unless(AttrVal($name,'setTakePictureCamera','none') ne 'none'); - - $path = "/fhem-amad/setCommands/takepicture?pictureresolution=".AttrVal($name,'setTakePictureResolution','none')."&picturecamera=".AttrVal($name,'setTakePictureCamera','none'); - $method = "POST"; + elsif ( lc $cmd eq 'vibrate' ) { + + $path .= 'setvibrate'; + $method = 'POST'; } - - elsif( lc $cmd eq 'takescreenshot' ) { - return "Please set \"setTakeScreenshotResolution\" Attribut first" - unless(AttrVal($name,'setTakeScreenshotResolution','none') ne 'none'); - - $path = "/fhem-amad/setCommands/takescreenshot?screenshotresolution=".AttrVal($name,'setTakeScreenshotResolution','none'); - $method = "POST"; + elsif ( lc $cmd eq 'showhomescreen' ) { + + $path .= 'showhomescreen'; + $method = 'POST'; } - - elsif( lc $cmd eq 'sendintent' ) { - my $intentstring = join( " ", @args ); - my ( $action, $exkey1, $exval1, $exkey2, $exval2 ) = split( "[ \t][ \t]*", $intentstring ); - $exkey1 = "" if( !$exkey1 ); - $exval1 = "" if( !$exval1 ); - $exkey2 = "" if( !$exkey2 ); - $exval2 = "" if( !$exval2 ); - $path = "/fhem-amad/setCommands/sendIntent?action=".$action."&exkey1=".$exkey1."&exval1=".$exval1."&exkey2=".$exkey2."&exval2=".$exval2; - $method = "POST"; + elsif ( lc $cmd eq 'takepicture' ) { + + return 'Please set "setTakePictureResolution" Attribut first' + unless ( + AttrVal( $name, 'setTakePictureResolution', 'none' ) ne 'none' ); + + return 'Please set "setTakePictureCamera" Attribut first' + unless ( AttrVal( $name, 'setTakePictureCamera', 'none' ) ne 'none' ); + + $path .= + 'takepicture?pictureresolution=' + . AttrVal( $name, 'setTakePictureResolution', 'none' ) + . '&picturecamera=' + . AttrVal( $name, 'setTakePictureCamera', 'none' ); + $method = 'POST'; } - - elsif( lc $cmd eq 'installflowsource' ) { - my $flowname = join( " ", @args ); - $path = "/fhem-amad/setCommands/installFlow?flowname=$flowname"; - $method = "POST"; + elsif ( lc $cmd eq 'takescreenshot' ) { + + return 'Please set "setTakeScreenshotResolution" Attribut first' + unless ( + AttrVal( $name, 'setTakeScreenshotResolution', 'none' ) ne 'none' ); + + $path .= 'takescreenshot?screenshotresolution=' + . AttrVal( $name, 'setTakeScreenshotResolution', 'none' ); + $method = 'POST'; } - - elsif( lc $cmd eq 'opencall' ) { - my $string = join( " ", @args ); - my ($callnumber, $time) = split( "[ \t][ \t]*", $string ); - $time = "none" if( !$time ); - $path = "/fhem-amad/setCommands/openCall?callnumber=".$callnumber."&hanguptime=".$time; - $method = "POST"; + elsif ( lc $cmd eq 'sendintent' ) { + my $intentstring = join( ' ', @args ); + my ( $action, $exkey1, $exval1, $exkey2, $exval2 ) = + split( '[ \t][ \t]*', $intentstring ); + $exkey1 = '' if ( !$exkey1 ); + $exval1 = '' if ( !$exval1 ); + $exkey2 = '' if ( !$exkey2 ); + $exval2 = '' if ( !$exval2 ); + + $path .= + 'sendIntent?action=' + . $action + . '&exkey1=' + . $exkey1 + . '&exval1=' + . $exval1 + . '&exkey2=' + . $exkey2 + . '&exval2=' + . $exval2; + $method = 'POST'; } - - elsif( lc $cmd eq 'closecall' ) { - $path = "/fhem-amad/setCommands/closeCall"; - $method = "POST"; + elsif ( lc $cmd eq 'installflowsource' ) { + my $flowname = join( ' ', @args ); + + $path .= 'installFlow?flowname=' . $flowname; + $method = 'POST'; } - - elsif( lc $cmd eq 'startdaydream' ) { - $path = "/fhem-amad/setCommands/startDaydream"; - $method = "POST"; + elsif ( lc $cmd eq 'opencall' ) { + my $string = join( ' ', @args ); + my ( $callnumber, $time ) = split( '[ \t][ \t]*', $string ); + $time = 'none' if ( !$time ); + + $path .= 'openCall?callnumber=' . $callnumber . '&hanguptime=' . $time; + $method = 'POST'; } - - elsif( lc $cmd eq 'currentflowsetupdate' ) { - if( ReadingsVal($name,'flowsetVersionAtDevice','') lt '4.1.99.6' ) { - $path = "/fhem-amad/currentFlowsetUpdate"; - } else { - $path = "/fhem-amad/setCommands/currentFlowsetUpdate"; + elsif ( lc $cmd eq 'closecall' ) { + + $path .= 'closeCall'; + $method = 'POST'; + } + + elsif ( lc $cmd eq 'startdaydream' ) { + + $path .= 'startDaydream'; + $method = 'POST'; + } + + elsif ( lc $cmd eq 'currentflowsetupdate' ) { + + if ( ReadingsVal( $name, 'flowsetVersionAtDevice', '' ) lt '4.1.99.6' ) + { + $path = '/fhem-amad/currentFlowsetUpdate'; } - - $method = "POST"; + else { + $path .= 'currentFlowsetUpdate'; + } + + $method = 'POST'; } - - elsif( lc $cmd eq 'sendsms' ) { - my $string = join( " ", @args ); - my ($smsmessage, $smsnumber) = split( "\\|", $string ); - - $path = "/fhem-amad/setCommands/sendSms?smsmessage=".urlEncode($smsmessage)."&smsnumber=".$smsnumber; - $method = "POST"; - - } else { - - my $apps = AttrVal( $name, "setOpenApp", "none" ); - my $btdev = AttrVal( $name, "setBluetoothDevice", "none" ); - + + elsif ( lc $cmd eq 'sendsms' ) { + my $string = join( ' ', @args ); + my ( $smsmessage, $smsnumber ) = split( '\\|', $string ); + + $path .= + 'sendSms?smsmessage=' + . urlEncode($smsmessage) + . '&smsnumber=' + . $smsnumber; + $method = 'POST'; + + } + else { + + my $apps = AttrVal( $name, 'setOpenApp', 'none' ); + my $btdev = AttrVal( $name, 'setBluetoothDevice', 'none' ); my $list = ''; - foreach(@playerCmd) { - $list .= $_ . ':' . join(',',@playerList) . ' '; + foreach (@playerCmd) { + $list .= $_ . ':' . join( ',', @playerList ) . ' '; } - - $list .= "screenMsg ttsMsg screenBrightnessMode:on,off screenBrightness:slider,0,1,255 screen:on,off,lock,unlock openURL nextAlarmTime:time timer:slider,1,1,60 statusRequest:noArg bluetooth:on,off notifySndFile clearNotificationBar:All,Automagic activateVoiceInput:noArg vibrate:noArg sendIntent openCall closeCall:noArg currentFlowsetUpdate:noArg installFlowSource doNotDisturb:never,always,alarmClockOnly,onlyImportant userFlowState userFlowRun sendSMS startDaydream:noArg volumeUp:noArg volumeDown:noArg mute:on,off showHomeScreen:noArg takePicture:noArg takeScreenshot:noArg"; - $list .= " screenOrientation:auto,landscape,portrait" if( AttrVal( $name, "setScreenOrientation", "0" ) eq "1" ); - $list .= " screenFullscreen:on,off" if( AttrVal( $name, "setFullscreen", "0" ) eq "1" ); - $list .= " openApp:$apps" if( AttrVal( $name, "setOpenApp", "none" ) ne "none" ); - $list .= " system:reboot,shutdown,airplanemodeON" if( AttrVal( $name, "root", "0" ) eq "1" ); - $list .= " changetoBTDevice:$btdev" if( AttrVal( $name, "setBluetoothDevice", "none" ) ne "none" ); - $list .= " nfc:on,off" if( AttrVal( $name, "root", "0" ) eq "1" ); - $list .= " volume:slider,0,1,$volMax"; - $list .= " volumeNotification:slider,0,1,$notifyVolMax"; - $list .= " volumeRingSound:slider,0,1,$ringSoundVolMax"; - + $list .= +'screenMsg ttsMsg screenBrightnessMode:on,off screenBrightness:slider,0,1,255 screen:on,off,lock,unlock openURL nextAlarmTime:time timer:slider,1,1,60 statusRequest:noArg bluetooth:on,off notifySndFile clearNotificationBar:All,Automagic activateVoiceInput:noArg vibrate:noArg sendIntent openCall closeCall:noArg currentFlowsetUpdate:noArg installFlowSource doNotDisturb:never,always,alarmClockOnly,onlyImportant userFlowState userFlowRun sendSMS startDaydream:noArg volumeUp:noArg volumeDown:noArg mute:on,off showHomeScreen:noArg takePicture:noArg takeScreenshot:noArg'; + $list .= ' screenOrientation:auto,landscape,portrait' + if ( AttrVal( $name, 'setScreenOrientation', '0' ) eq '1' ); + $list .= ' screenFullscreen:on,off' + if ( AttrVal( $name, 'setFullscreen', '0' ) eq '1' ); + $list .= ' openApp:' . $apps + if ( AttrVal( $name, 'setOpenApp', 'none' ) ne 'none' ); + $list .= ' system:reboot,shutdown,airplanemodeON' + if ( AttrVal( $name, 'root', '0' ) eq '1' ); + $list .= ' changetoBTDevice:' . $btdev + if ( AttrVal( $name, 'setBluetoothDevice', 'none' ) ne 'none' ); + $list .= ' nfc:on,off' if ( AttrVal( $name, 'root', '0' ) eq '1' ); + $list .= ' volume:slider,0,1,' . $volMax; + $list .= ' volumeNotification:slider,0,1,' . $notifyVolMax; + $list .= ' volumeRingSound:slider,0,1,' . $ringSoundVolMax; return "Unknown argument $cmd, choose one of $list"; } - - - IOWrite($hash,$amad_id,$uri,$path,$header,$method); - Log3 $name, 5, "AMADDevice ($name) - IOWrite: $uri $method IODevHash=$hash->{IODev}"; + + IOWrite( $hash, $amad_id, $uri, $path, $header, $method ); + Log3( $name, 5, + "AMADDevice ($name) - IOWrite: $uri $method IODevHash=$hash->{IODev}" ); return undef; } -sub AMADDevice_Parse($$) { +sub Parse($$) { - my ($io_hash,$json) = @_; - my $name = $io_hash->{NAME}; + my ( $io_hash, $json ) = @_; + my $name = $io_hash->{NAME}; - - my $decode_json = eval{decode_json($json)}; - if($@){ - Log3 $name, 3, "AMADDevice ($name) - JSON error while request: $@"; + my $decode_json = eval { decode_json($json) }; + if ($@) { + Log3( $name, 3, "AMADDevice ($name) - JSON error while request: $@" ); return; } - - Log3 $name, 4, "AMADDevice ($name) - ParseFn was called"; - Log3 $name, 5, "AMADDevice ($name) - ParseFn was called, !!! AMAD_ID: $decode_json->{amad}{amad_id}"; + Log3( $name, 4, "AMADDevice ($name) - ParseFn was called" ); + Log3( $name, 5, +"AMADDevice ($name) - ParseFn was called, !!! AMAD_ID: $decode_json->{amad}{amad_id}" + ); + + my $fhemDevice = $decode_json->{firstrun}{fhemdevice} + if ( defined( $decode_json->{firstrun} ) + and defined( $decode_json->{firstrun}{fhemdevice} ) ); + my $amad_id = $decode_json->{amad}{amad_id}; + + if ( my $hash = $modules{AMADDevice}{defptr}{$amad_id} ) { + my $name = $hash->{NAME}; + + WriteReadings( $hash, $decode_json ); + Log3( $name, 4, + "AMADDevice ($name) - find logical device: $hash->{NAME}" ); - my $fhemDevice = $decode_json->{firstrun}{fhemdevice} if( defined($decode_json->{firstrun}) and defined($decode_json->{firstrun}{fhemdevice}) ); - my $amad_id = $decode_json->{amad}{amad_id}; - - if( my $hash = $modules{AMADDevice}{defptr}{$amad_id} ) { - my $name = $hash->{NAME}; - - AMADDevice_WriteReadings($hash,$decode_json); - Log3 $name, 4, "AMADDevice ($name) - find logical device: $hash->{NAME}"; - return $hash->{NAME}; - - } else { - return "UNDEFINED $fhemDevice AMADDevice $decode_json->{firstrun}{'amaddevice_ip'} $decode_json->{amad}{'amad_id'} $decode_json->{firstrun}{remoteserver}"; + } + else { + + return +"UNDEFINED $fhemDevice AMADDevice $decode_json->{firstrun}{'amaddevice_ip'} $decode_json->{amad}{'amad_id'} $decode_json->{firstrun}{remoteserver}"; } } @@ -843,174 +1015,192 @@ sub AMADDevice_Parse($$) { ################################## #### my little helpers ########### -sub AMADDevice_checkDeviceState($) { +sub checkDeviceState($) { - my ( $hash ) = @_; + my ($hash) = @_; my $name = $hash->{NAME}; - Log3 $name, 4, "AMADDevice ($name) - AMADDevice_checkDeviceState: run Check"; + Log3( $name, 4, "AMADDevice ($name) - checkDeviceState: run Check" ); - - if( ReadingsAge( $name, ".deviceState", 240 ) > 240 ) { - - AMADDevice_statusRequest( $hash ) if( $hash->{helper}{deviceStateErrorCounter} == 0 ); - readingsSingleUpdate( $hash, "deviceState", "offline", 1 ) if( ReadingsAge( $name, ".deviceState", 300) > 300 and $hash->{helper}{deviceStateErrorCounter} > 0 and ReadingsVal($name,'deviceState','online') ne 'offline' ); - $hash->{helper}{deviceStateErrorCounter} = ( $hash->{helper}{deviceStateErrorCounter} + 1 ); + if ( ReadingsAge( $name, '.deviceState', 240 ) > 240 ) { + + statusRequest($hash) + if ( $hash->{helper}{deviceStateErrorCounter} == 0 ); + readingsSingleUpdate( $hash, 'deviceState', 'offline', 1 ) + if ( ReadingsAge( $name, '.deviceState', 300 ) > 300 + and $hash->{helper}{deviceStateErrorCounter} > 0 + and ReadingsVal( $name, 'deviceState', 'online' ) ne 'offline' ); + $hash->{helper}{deviceStateErrorCounter} = + ( $hash->{helper}{deviceStateErrorCounter} + 1 ); } - - InternalTimer( gettimeofday()+240, "AMADDevice_checkDeviceState", $hash, 0 ); - - Log3 $name, 4, "AMADDevice ($name) - AMADDevice_checkDeviceState: set new Timer"; + + InternalTimer( + gettimeofday() + 240, + 'FHEM::AMADDevice::checkDeviceState', + $hash, 0 + ); + + Log3( $name, 4, "AMADDevice ($name) - checkDeviceState: set new Timer" ); } -sub AMADDevice_encrypt($) { +sub encrypt($) { my ($decodedPIN) = @_; my $key = getUniqueId(); my $encodedPIN; - - return $decodedPIN if( $decodedPIN =~ /^crypt:(.*)/ ); - for my $char (split //, $decodedPIN) { + return $decodedPIN if ( $decodedPIN =~ /^crypt:(.*)/ ); + + for my $char ( split //, $decodedPIN ) { my $encode = chop($key); - $encodedPIN .= sprintf("%.2x",ord($char)^ord($encode)); - $key = $encode.$key; + $encodedPIN .= sprintf( "%.2x", ord($char) ^ ord($encode) ); + $key = $encode . $key; } - - return 'crypt:'. $encodedPIN; + + return 'crypt:' . $encodedPIN; } -sub AMADDevice_decrypt($) { +sub decrypt($) { my ($encodedPIN) = @_; my $key = getUniqueId(); my $decodedPIN; - $encodedPIN = $1 if( $encodedPIN =~ /^crypt:(.*)/ ); + $encodedPIN = $1 if ( $encodedPIN =~ /^crypt:(.*)/ ); - for my $char (map { pack('C', hex($_)) } ($encodedPIN =~ /(..)/g)) { + for my $char ( map { pack( 'C', hex($_) ) } ( $encodedPIN =~ /(..)/g ) ) { my $decode = chop($key); - $decodedPIN .= chr(ord($char)^ord($decode)); - $key = $decode.$key; + $decodedPIN .= chr( ord($char) ^ ord($decode) ); + $key = $decode . $key; } return $decodedPIN; } -sub AMADDevice_CreateVolumeValue($$@) { +sub CreateVolumeValue($$@) { - my ($hash,$cmd,@args) = @_; - - my $name = $hash->{NAME}; + my ( $hash, $cmd, @args ) = @_; + + my $name = $hash->{NAME}; my $vol; - - if( $cmd eq 'volume' ) { + if ( $cmd eq 'volume' ) { $vol = join( " ", @args ); - if( $vol =~ /^\+(.*)/ or $vol =~ /^-(.*)/ ) { + if ( $vol =~ /^\+(.*)/ or $vol =~ /^-(.*)/ ) { + + if ( $vol =~ /^\+(.*)/ ) { - if( $vol =~ /^\+(.*)/ ) { - $vol =~ s/^\+//g; $vol = ReadingsVal( $name, "volume", 0 ) + $vol; } - - elsif( $vol =~ /^-(.*)/ ) { - + + elsif ( $vol =~ /^-(.*)/ ) { + $vol =~ s/^-//g; $vol = ReadingsVal( $name, "volume", 15 ) - $vol; } } - - } elsif( $cmd eq 'mute') { - if($args[0] eq 'on') { + + } + elsif ( $cmd eq 'mute' ) { + if ( $args[0] eq 'on' ) { $vol = 0; - readingsSingleUpdate($hash,'.volume',ReadingsVal($name,'volume',0),0); - } else { - $vol = ReadingsVal($name,'.volume',0); + readingsSingleUpdate( $hash, '.volume', + ReadingsVal( $name, 'volume', 0 ), 0 ); } - - } elsif( $cmd =~ 'volume[Down|Up]') { - if( $cmd eq 'volumeUp' ) { - $vol = ReadingsVal( $name, "volume", 0 ) + AttrVal($name,'setVolUpDownStep',3); - } else { - $vol = ReadingsVal( $name, "volume", 0 ) - AttrVal($name,'setVolUpDownStep',3); + else { + $vol = ReadingsVal( $name, '.volume', 0 ); + } + + } + elsif ( $cmd =~ 'volume[Down|Up]' ) { + if ( $cmd eq 'volumeUp' ) { + $vol = + ReadingsVal( $name, "volume", 0 ) + + AttrVal( $name, 'setVolUpDownStep', 3 ); + } + else { + $vol = + ReadingsVal( $name, "volume", 0 ) - + AttrVal( $name, 'setVolUpDownStep', 3 ); } } - + return $vol; } -sub AMADDevice_CreateTtsMsgValue($@) { +sub CreateTtsMsgValue($@) { - my ($hash,@args) = @_; - - my $name = $hash->{NAME}; + my ( $hash, @args ) = @_; + + my $name = $hash->{NAME}; my $msg; my $speed; - my $lang = AttrVal( $name, "setTtsMsgLang","de" ); - my $ttsmsgvol = AttrVal( $name, "setTtsMsgVol","none"); - - if( AttrVal($name,"remoteServer","Automagic") ne 'Automagic') { - $speed = AttrVal( $name, "setTtsMsgSpeed", "5" ); - } else { - $speed = AttrVal( $name, "setTtsMsgSpeed", "1.0" ); + my $lang = AttrVal( $name, 'setTtsMsgLang', 'de' ); + my $ttsmsgvol = AttrVal( $name, 'setTtsMsgVol', 'none' ); + + if ( AttrVal( $name, 'remoteServer', 'Automagic' ) ne 'Automagic' ) { + $speed = AttrVal( $name, 'setTtsMsgSpeed', '5' ); + } + else { + $speed = AttrVal( $name, 'setTtsMsgSpeed', '1.0' ); } + $msg = join( ' ', @args ); - $msg = join( " ", @args ); - - unless($args[0] ne '&en;' and $args[0] ne '&de;') { - $lang = substr(splice(@args,0,1),1,2); - $msg = join( " ", @args ); + unless ( $args[0] ne '&en;' and $args[0] ne '&de;' ) { + $lang = substr( splice( @args, 0, 1 ), 1, 2 ); + $msg = join( ' ', @args ); } - - return ($msg,$speed,$lang,$ttsmsgvol); + + return ( $msg, $speed, $lang, $ttsmsgvol ); } -sub AMADDevice_CreateScreenValue($$) { +sub CreateScreenValue($$) { - my ($hash,$mod) = @_; + my ( $hash, $mod ) = @_; - my $name = $hash->{NAME}; - my $scot = AttrVal( $name, "setScreenOnForTimer", undef ); - $scot = 60 if( !$scot ); + my $name = $hash->{NAME}; + my $scot = AttrVal( $name, 'setScreenOnForTimer', undef ); + $scot = 60 if ( !$scot ); - if ($mod eq "on" or $mod eq "off") { - return ("/fhem-amad/setCommands/setScreenOnOff?screen=".$mod."&screenontime=".$scot); + if ( $mod eq 'on' or $mod eq 'off' ) { + return ('/fhem-amad/setCommands/setScreenOnOff?screen=' + . $mod + . '&screenontime=' + . $scot ); } - elsif ($mod eq "lock" or $mod eq "unlock") { - return "NO PIN" - unless( AttrVal( $name, "setScreenlockPIN", "none" ) ne "none" ); - my $PIN = AttrVal( $name, "setScreenlockPIN", undef ); - $PIN = AMADDevice_decrypt($PIN); + elsif ( $mod eq 'lock' or $mod eq 'unlock' ) { + return 'NO PIN' + unless ( AttrVal( $name, 'setScreenlockPIN', 'none' ) ne 'none' ); + my $PIN = AttrVal( $name, 'setScreenlockPIN', undef ); + $PIN = decrypt($PIN); - return ("/fhem-amad/setCommands/screenlock?lockmod=".$mod."&lockPIN=".$PIN); + return ('/fhem-amad/setCommands/screenlock?lockmod=' + . $mod + . '&lockPIN=' + . $PIN ); } } -sub AMADDevice_CreateChangeBtDeviceValue($$) { +sub CreateChangeBtDeviceValue($$) { - my ($hash,$swToBtDevice) = @_; + my ( $hash, $swToBtDevice ) = @_; - my $name = $hash->{NAME}; - my @swToBtMac = split( /\|/, $swToBtDevice ); - my $btDevices = AttrVal( $name, "setBluetoothDevice", "none" ) if( AttrVal( $name, "setBluetoothDevice", "none" ) ne "none" ); - my @btDevice = split( ',', $btDevices ); - my @btDeviceOne = split( /\|/, $btDevice[0] ); - my @btDeviceTwo = split( /\|/, $btDevice[1] ); - - - return($swToBtMac[1],$btDeviceOne[1],$btDeviceTwo[1]); + my $name = $hash->{NAME}; + my @swToBtMac = split( /\|/, $swToBtDevice ); + my $btDevices = AttrVal( $name, 'setBluetoothDevice', 'none' ) + if ( AttrVal( $name, 'setBluetoothDevice', 'none' ) ne 'none' ); + my @btDevice = split( ',', $btDevices ); + my @btDeviceOne = split( /\|/, $btDevice[0] ); + my @btDeviceTwo = split( /\|/, $btDevice[1] ); + + return ( $swToBtMac[1], $btDeviceOne[1], $btDeviceTwo[1] ); } - - - - 1; =pod @@ -1403,4 +1593,50 @@ sub AMADDevice_CreateChangeBtDeviceValue($$) {
=end html_DE + +=for :application/json;q=META.json 74_AMADDevice.pm +{ + "abstract": "Integrates Android devices into FHEM and displays several settings", + "x_lang": { + "de": { + "abstract": "Integriert Android-Geräte in FHEM und zeigt verschiedene Einstellungen an" + } + }, + "keywords": [ + "fhem-mod-device", + "fhem-core", + "Android", + "Tablet", + "Handy", + "AMAD" + ], + "release_status": "stable", + "license": "GPL_2", + "author": [ + "Marko Oldenburg " + ], + "x_fhem_maintainer": [ + "CoolTux" + ], + "x_fhem_maintainer_github": [ + "LeonGaultier" + ], + "prereqs": { + "runtime": { + "requires": { + "FHEM": 5.00918799, + "perl": 5.016, + "Meta": 0, + "Encode": 0, + "JSON": 0 + }, + "recommends": { + }, + "suggests": { + } + } + } +} +=end :application/json;q=META.json + =cut diff --git a/fhem/FHEM/lib/74_AMADautomagicFlowset_4.2.5.xml b/fhem/FHEM/lib/74_AMADautomagicFlowset_4.4.0.xml similarity index 91% rename from fhem/FHEM/lib/74_AMADautomagicFlowset_4.2.5.xml rename to fhem/FHEM/lib/74_AMADautomagicFlowset_4.4.0.xml index b369469c4..ac667193e 100644 --- a/fhem/FHEM/lib/74_AMADautomagicFlowset_4.2.5.xml +++ b/fhem/FHEM/lib/74_AMADautomagicFlowset_4.4.0.xml @@ -2725,25 +2725,25 @@ Connection: close if (global_bridgeport != {header_bport}) { global_bridgeport = {header_bport} } -if (header_fhemctlmode != null or header_fhemctlmode != {global_fhemctlmode}) { +if (header_fhemctlmode != null and header_fhemctlmode != {global_fhemctlmode}) { global_fhemctlmode = {header_fhemctlmode} } -if (header_fhemip != null or header_fhemip != {global_fhemip}) { +if (header_fhemip != null and header_fhemip != "none" and header_fhemip != {global_fhemip}) { global_fhemip = {header_fhemip} } -if (header_fhemdevice != null or header_fhemdevice != {global_fhemdevice}) { +if (header_fhemdevice != null and header_fhemdevice != {global_fhemdevice}) { global_fhemdevice = {header_fhemdevice} } -if (header_activetask != null or header_activetask != {global_activetask}) { +if (header_activetask != null and header_activetask != {global_activetask}) { global_activetask = {header_activetask} } -if (header_apssid != null or header_apssid != {global_apssid}) { +if (header_apssid != null and header_apssid != {global_apssid}) { global_apssid = {header_apssid} } -if (header_dport != null or header_dport != {global_deviceport}) { +if (header_dport != null and header_dport != {global_deviceport}) { global_deviceport = {header_dport} } -if (header_userflowstate != null or header_userflowstate != {global_userflowstate}) { +if (header_userflowstate != null and header_userflowstate != {global_userflowstate}) { global_userflowstate = {header_userflowstate} } @@ -3418,7 +3418,7 @@ fhemcmd = "setreading"; false Script: Set FHEMDATA JSON -