diff --git a/73_AMADCommBridge.pm b/73_AMADCommBridge.pm index fba1061..d5d8be0 100755 --- a/73_AMADCommBridge.pm +++ b/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,935 +58,1154 @@ ## ## - - 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.4.0"; -my $flowsetversion = "4.4.0"; - - - - -# 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 ' + . $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 + attr + AttrVal + ReadingsVal + init_done + urlEncode + 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 ); + delete $modules{AMADCommBridge}{defptr}{BRIDGE} + if ( defined( $modules{AMADCommBridge}{defptr}{BRIDGE} ) + and $hash->{BRIDGE} ); + TcpServer_Close($hash); 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); - - } else { - my $list = "open:noArg close:noArg"; +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 $name = $hash->{NAME}; - my $port = $hash->{PORT}; - + my $hash = shift; + 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}; - 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."; + 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." ); + } + 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" ); + 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"; $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 = (); @@ -997,19 +1216,11 @@ sub AMADCommBridge_ParseMsg($$) { # # $value =~ s/^ //; # $hash{$key} = $value; -# } -# +# } +# # return \%hash; #} - - - - - - - - 1; =pod @@ -1162,4 +1373,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