Diverse JSON Strings hinzugefügt, Codeanpassungen und Bugfixes

This commit is contained in:
Marko Oldenburg 2017-05-28 20:45:59 +02:00
parent 874cdb7bf1
commit 3e2de00594
2 changed files with 228 additions and 93 deletions

View File

@ -41,7 +41,8 @@
###### Möglicher Aufbau eines JSON Strings für die AMADCommBridge
#
# first initial String
# {"amad": {"amad_id": "37836534","fhemcmd": "setreading"},"payload": {"fhemdevice": "TabletWohnzimmer","fhemserverip": "192.168.1.25","amaddevice_ip": "192.168.1.123"}}
# {"amad": {"amad_id": "1495827100156","fhemcmd": "setreading"},"payload": {},"firstrun": {"fhemdevice": "TabletWohnzimmer","fhemserverip": "fhem02.tuxnet.local","amaddevice_ip": "10.6.9.35"}}
# {"amad": {"amad_id": "1495827100156","fhemcmd": "setreading"},"payload": {},"firstrun": {"fhemdevice": "TabletWohnzimmer","fhemserverip": "fhem02.tuxnet.local","amaddevice_ip": "10.6.9.35"}}
#
# default String
# {"amad": {"amad_id": "37836534","fhemcmd": "setreading"},"payload": {"reading0": "value0","reading1": "value1","readingX": "valueX"}}
@ -67,8 +68,8 @@ use TcpServerUtils;
eval "use JSON;1" or $missingModul .= "JSON ";
my $modulversion = "3alpha27";
my $flowsetversion = "2.6.12";
my $modulversion = "3.9.48";
my $flowsetversion = "3.9.48";
@ -78,7 +79,6 @@ sub AMADCommBridge_Attr(@);
sub AMADCommBridge_Open($);
sub AMADCommBridge_Read($);
sub AMADCommBridge_Define($$);
sub AMADCommBridge_WriteRequest($$$);
sub AMADCommBridge_Initialize($);
sub AMADCommBridge_Set($@);
sub AMADCommBridge_Write($@);
@ -86,6 +86,8 @@ sub AMADCommBridge_Undef($$);
sub AMADCommBridge_ResponseProcessing($$);
sub AMADCommBridge_Close($);
sub AMADCommBridge_ErrorHandling($$$);
sub AMADCommBridge_ProcessRead($$);
sub AMADCommBridge_ParseMsg($$);
@ -99,7 +101,7 @@ sub AMADCommBridge_Initialize($) {
$hash->{ReadFn} = "AMADCommBridge_Read";
$hash->{WriteFn} = "AMADCommBridge_Write";
$hash->{Clients} = ":AMADDevice:";
$hash->{MatchList} = { "1:AMADDevice" => '.*' };
$hash->{MatchList} = { "1:AMADDevice" => '{"amad": {"amad_id":.+}}' };
# Consumer
@ -246,9 +248,7 @@ sub AMADCommBridge_Set($@) {
sub AMADCommBridge_Write($@) {
my ($hash,$amad_id,$uri,$method) = @_;
my $header = "Connection: close\r\n";
$header .= shift;
my ($hash,$amad_id,$uri,$header,$method) = @_;
my $name = $hash->{NAME};
@ -589,6 +589,7 @@ sub AMADCommBridge_Close($) {
sub AMADCommBridge_Read($) {
my $hash = shift;
my $name = $hash->{NAME};
if( $hash->{SERVERSOCKET} ) { # Accept and create a child
@ -598,62 +599,39 @@ sub AMADCommBridge_Read($) {
# Read 1024 byte of data
my $buf;
my $ret = sysread($hash->{CD}, $buf, 1024);
my $ret = sysread($hash->{CD}, $buf, 2048);
# When there is an error in connection return
if( !defined($ret ) || $ret <= 0 ) {
CommandDelete( undef, $hash->{NAME} );
CommandDelete( undef, $name );
Log3 $name, 5, "AMADCommBridge ($name) - Error in connection";
return;
}
AMADCommBridge_ResponseProcessing($hash,$buf);
AMADCommBridge_ProcessRead($hash,$buf);
}
sub AMADCommBridge_ResponseProcessing($$) {
my ($hash,$buf) = @_;
sub AMADCommBridge_ProcessRead($$) {
my ($hash, $buf) = @_;
my $name = $hash->{NAME};
my $bhash = $modules{AMADCommBridge}{defptr}{BRIDGE};
my $bname = $bhash->{NAME};
my @data = split( '\R\R', $buf );
my $data = $data[0];
my $json = $data[1];
my $buffer = '';
#### Verarbeitung der Daten welche über die AMADCommBridge kommen ####
Log3 $bname, 5, "AMADCommBridge ($name) - Receive RAW Message in Debugging Mode: $buf";
Log3 $name, 4, "AMADCommBridge ($name) - process read";
my $response;
my $c;
my $json = $data[1];
my $decode_json;
$decode_json = eval{decode_json($json)};
if($@){
Log3 $bname, 3, "AMADCommBridge ($name) - error while request: $@";
readingsSingleUpdate($bhash, "state", "error", 1);
return;
}
my $amad_id = $decode_json->{amad}{amad_id};
my $fhemcmd = $decode_json->{amad}{fhemcmd};
my $fhemDevice;
if( defined($decode_json->{payload}{fhemdevice}) and ($decode_json->{payload}{fhemdevice}) ) {
$fhemDevice = $decode_json->{payload}{fhemdevice} if( defined($decode_json->{payload}{fhemdevice}) );
} else {
$fhemDevice = $modules{AMADDevice}{defptr}{$amad_id}->{NAME};
}
if ( $data[0] =~ /currentFlowsetUpdate.xml/ ) {
if ( $data =~ /currentFlowsetUpdate.xml/ ) {
my $fhempath = $attr{global}{modpath};
$response = qx(cat $fhempath/FHEM/lib/74_AMADautomagicFlowset_$flowsetversion.xml);
@ -667,7 +645,7 @@ sub AMADCommBridge_ResponseProcessing($$) {
return;
}
elsif ( $data[0] =~ /installFlow_([^.]*.xml)/ ) {
elsif ( $data =~ /installFlow_([^.]*.xml)/ ) {
if( defined($1) ){
$response = qx(cat /tmp/$1);
@ -683,8 +661,98 @@ sub AMADCommBridge_ResponseProcessing($$) {
}
if(defined($hash->{PARTIAL}) and $hash->{PARTIAL}) {
elsif( !defined($amad_id) ) {
Log3 $name, 5, "AMADCommBridge ($name) - PARTIAL: " . $hash->{PARTIAL};
$buffer = $hash->{PARTIAL};
} else {
Log3 $name, 4, "AMADCommBridge ($name) - No PARTIAL buffer";
}
Log3 $name, 5, "AMADCommBridge ($name) - Incoming data: " . $json;
$buffer = $buffer . $json;
Log3 $name, 5, "AMADCommBridge ($name) - Current processing buffer (PARTIAL + incoming data): " . $buffer;
my ($correct_json,$tail) = AMADCommBridge_ParseMsg($hash, $buffer);
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;
}
$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};
}
sub AMADCommBridge_ResponseProcessing($$) {
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";
my $response;
my $c;
#my $json = $data[1];
my $decode_json;
$decode_json = eval{decode_json($json)};
if($@){
Log3 $bname, 3, "AMADCommBridge ($name) - ERROR while request: $@";
readingsSingleUpdate($bhash, "JSON info", "JSON ERROR", 1);
$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;
return;
}
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->{payload}{fhemdevice} if( defined($decode_json->{firstrun}{fhemdevice}) );
} else {
$fhemDevice = $modules{AMADDevice}{defptr}{$amad_id}->{NAME};
}
if( !defined($amad_id) ) {
readingsSingleUpdate( $bhash, "transmitterERROR", $hash->{NAME}." has no device name sends", 1 ) if( AttrVal( $bname, "expertMode", 0 ) eq "1" );
Log3 $bname, 4, "AMADCommBridge ($name) - ERROR - no device name given. please check your global variable in automagic";
@ -700,7 +768,6 @@ sub AMADCommBridge_ResponseProcessing($$) {
}
if( defined($fhemcmd) and ($fhemcmd) ) {
if ( $fhemcmd eq 'setreading' ) {
return Log3 $bname, 3, "AMADCommBridge ($name) - AMADCommBridge: processing receive no reading values from Device: $fhemDevice"
@ -710,7 +777,7 @@ sub AMADCommBridge_ResponseProcessing($$) {
Dispatch($bhash,$json,undef);
Log3 $bname, 4, "AMADCommBridge ($bname) - call Dispatcher";
readingsSingleUpdate($bhash,'fhemServerIP',$decode_json->{payload}{'fhemserverip'},1) if( defined($decode_json->{payload}{'fhemserverip'}));
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};
@ -723,12 +790,12 @@ sub AMADCommBridge_ResponseProcessing($$) {
return;
}
elsif ( $fhemcmd =~ /set\b/ ) {
my $fhemCmd = $data[1];
elsif ( $fhemcmd eq 'set' ) {
my $fhemCmd = $decode_json->{payload}{setcmd};
fhem ("set $fhemCmd") if( ReadingsVal( $bname, "expertMode", 0 ) eq "1" );
readingsSingleUpdate( $bhash, "receiveFhemCommand", "set ".$fhemCmd, 0 );
Log3 $bname, 4, "AMADCommBridge ($name) - AMADCommBridge_CommBridge: set reading receive fhem command";
Log3 $bname, 3, "AMADCommBridge ($name) - AMADCommBridge_CommBridge: set reading receive fhem command";
$response = "header lines: \r\n AMADCommBridge receive Data complete\r\n FHEM execute set command now\r\n";
$c = $hash->{CD};
@ -741,8 +808,8 @@ sub AMADCommBridge_ResponseProcessing($$) {
return;
}
elsif ( $fhemcmd =~ /voiceinputvalue\b/ ) {
my $fhemCmd = lc $data[1];
elsif ( $fhemcmd eq 'voiceinputvalue' ) {
my $fhemCmd = $decode_json->{payload}{voiceinputdata};
readingsBeginUpdate( $bhash);
readingsBulkUpdate( $bhash, "receiveVoiceCommand", $fhemCmd );
@ -761,8 +828,8 @@ sub AMADCommBridge_ResponseProcessing($$) {
return;
}
elsif ( $fhemcmd =~ /readingsval\b/ ) {
my $fhemCmd = $data[1];
elsif ( $fhemcmd eq 'readingsval' ) {
my $fhemCmd = $decode_json->{payload}{readingsvalcmd};
my @datavalue = split( ' ', $fhemCmd );
$response = ReadingsVal( $datavalue[0], $datavalue[1], $datavalue[2] );
@ -773,7 +840,6 @@ sub AMADCommBridge_ResponseProcessing($$) {
"Content-Length: ".length($response)."\r\n\r\n",
$response;
Log3 $bname, 4, "AMADCommBridge ($name) - AMADCommBridge_CommBridge: response ReadingsVal Value to Automagic Device";
return;
}
@ -813,10 +879,58 @@ sub AMADCommBridge_ResponseProcessing($$) {
$response;
}
##################
### my little helper
##################
sub AMADCommBridge_ParseMsg($$) {
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) {
$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 '{') {
$open++;
} elsif($c eq '}') {
$close++;
}
$msg .= $c;
}
}
if($open != $close) {
$tail = $msg;
$msg = '';
}
}
Log3 $name, 5, "AMADCommBridge ($name) - return msg: $msg and tail: $tail";
return ($msg,$tail);
}
##### bleibt zu Anschauungszwecken erhalten
#sub AMADCommBridge_Header2Hash($) {
#

View File

@ -54,8 +54,8 @@ use Encode qw(encode);
eval "use JSON;1" or $missingModul .= "JSON ";
my $modulversion = "3alpha27";
my $flowsetversion = "2.6.12";
my $modulversion = "3.9.49";
my $flowsetversion = "3.9.48";
@ -69,10 +69,10 @@ sub AMADDevice_encrypt($);
sub AMADDevice_GetUpdate($);
sub AMADDevice_Initialize($);
sub AMADDevice_WriteReadings($$);
sub AMADDevice_SelectSetCmd($$@);
sub AMADDevice_Set($$@);
sub AMADDevice_Undef($$);
sub AMADDevice_Parse($$);
sub AMADDevice_statusRequest($);
@ -81,7 +81,7 @@ sub AMADDevice_Initialize($) {
my ($hash) = @_;
$hash->{Match} = '.*';
$hash->{Match} = '{"amad": {"amad_id":.+}}';
$hash->{SetFn} = "AMADDevice_Set";
$hash->{DefFn} = "AMADDevice_Define";
@ -185,11 +185,11 @@ sub AMADDevice_Define($$) {
if( $init_done ) {
#AMADDevice_GetUpdate($hash);
AMADDevice_GetUpdate($hash);
} else {
#InternalTimer( gettimeofday()+30, "AMADDevice_GetUpdate", $hash, 0 ) if( ($hash->{HOST}) );
InternalTimer( gettimeofday()+30, "AMADDevice_GetUpdate", $hash, 0 ) if( ($hash->{HOST}) );
}
$modules{AMADDevice}{defptr}{$amad_id} = $hash;
@ -318,14 +318,13 @@ sub AMADDevice_GetUpdate($) {
my ( $hash ) = @_;
my $name = $hash->{NAME};
my $bhash = $modules{AMADDevice}{defptr}{BRIDGE};
my $bname = $bhash->{NAME};
my $bname = $hash->{IODev}->{NAME};
RemoveInternalTimer( $hash );
if( $init_done && ( ReadingsVal( $name, "deviceState", "unknown" ) eq "unknown" or ReadingsVal( $name, "deviceState", "online" ) eq "online" ) && AttrVal( $name, "disable", 0 ) ne "1" && ReadingsVal( $bname, "fhemServerIP", "not set" ) ne "not set" ) {
AMADDevice_statusRequest( $hash );
AMADDevice_statusRequest($hash);
AMADDevice_checkDeviceState( $hash );
} else {
@ -337,6 +336,36 @@ sub AMADDevice_GetUpdate($) {
}
}
sub AMADDevice_statusRequest($) {
my $hash = shift;
my $name = $hash->{NAME};
my $host = $hash->{HOST};
my $port = $hash->{PORT};
my $amad_id = $hash->{AMAD_ID};
my $uri;
my $header = 'Connection: close';
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 $bport = $hash->{IODev}->{PORT};
my $amad_id = $hash->{AMAD_ID};
$uri = $host . ":" . $port . "/fhem-amad/deviceInfo/"; # Pfad muß so im Automagic als http request Trigger drin stehen
$header .= "\r\nfhemip: $fhemip\r\nfhemdevice: $name\r\nactivetask: $activetask\r\napssid: $apssid\r\nbport: $bport\r\nuserflowstate: $userFlowState\r\namadid: $amad_id";
$method = "GET";
IOWrite($hash,$amad_id,$uri,$header,$method);
Log3 $name, 5, "AMADDevice ($name) - IOWrite: $uri $method IODevHash=$hash->{IODev}";
}
sub AMADDevice_WriteReadings($$) {
my ( $hash, $decode_json ) = @_;
@ -359,7 +388,7 @@ sub AMADDevice_WriteReadings($$) {
while( ( $t, $v ) = each %{$decode_json->{payload}} ) {
readingsBulkUpdate( $hash, $t, $v ) if( defined( $v ) );
$v =~ s/\bnull\b/off/g if( ($t eq "nextAlarmDay" || $t eq "nextAlarmTime") && $v eq "null" );
$v =~ s/\bnull\b/off/g if( ($t eq "nextAlarmDay" or $t eq "nextAlarmTime") and $v eq "null" );
$v =~ s/\bnull\b//g;
}
@ -388,7 +417,7 @@ sub AMADDevice_Set($$@) {
my $port = $hash->{PORT};
my $amad_id = $hash->{AMAD_ID};
my $uri;
my $header;
my $header = 'Connection: close';
my $method;
@ -557,16 +586,8 @@ sub AMADDevice_Set($$@) {
elsif( lc $cmd eq 'statusrequest' ) {
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 $bport = $hash->{IODev}->{PORT};
$uri = $host . ":" . $port . "/fhem-amad/deviceInfo/"; # Pfad muß so im Automagic als http request Trigger drin stehen
$header = "fhemip: $fhemip\r\nfhemdevice: $name\r\nactivetask: $activetask\r\napssid: $apssid\r\nbport: $bport\r\nuserflowstate: $userFlowState";
$method = "GET";
AMADDevice_statusRequest($hash);
return;
}
elsif( lc $cmd eq 'openapp' ) {
@ -716,8 +737,8 @@ sub AMADDevice_Set($$@) {
return "Unknown argument $cmd, choose one of $list";
}
$header = undef unless( defined($header) and ($header) );
IOWrite($hash,$amad_id,$uri,$method,$header);
IOWrite($hash,$amad_id,$uri,$header,$method);
Log3 $name, 5, "AMADDevice ($name) - IOWrite: $uri $method IODevHash=$hash->{IODev}";
return undef;
@ -736,12 +757,12 @@ sub AMADDevice_Parse($$) {
return;
}
Log3 $name, 3, "AMADDevice ($name) - ParseFn was called";
Log3 $name, 3, "AMADDevice ($name) - ParseFn was called, !!! JSON: $json";
Log3 $name, 3, "AMADDevice ($name) - ParseFn was called, !!! AMAD_ID: $decode_json->{amad}{amad_id}";
Log3 $name, 4, "AMADDevice ($name) - ParseFn was called";
Log3 $name, 4, "AMADDevice ($name) - ParseFn was called, !!! JSON: $json";
Log3 $name, 4, "AMADDevice ($name) - ParseFn was called, !!! AMAD_ID: $decode_json->{amad}{amad_id}";
my $fhemDevice = $decode_json->{payload}{fhemdevice} if( defined($decode_json->{payload}{fhemdevice}) );
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} ) {
@ -754,7 +775,7 @@ sub AMADDevice_Parse($$) {
} else {
return "UNDEFINED $fhemDevice AMADDevice $decode_json->{payload}{'amaddevice_ip'} $decode_json->{amad}{'amad_id'} IODev=$name";
return "UNDEFINED $fhemDevice AMADDevice $decode_json->{firstrun}{'amaddevice_ip'} $decode_json->{amad}{'amad_id'} IODev=$name";
}
}