2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-09 20:57:11 +00:00

70_BRAVIA.pm: own package, new command stack, new reading application

git-svn-id: https://svn.fhem.de/fhem/trunk@18986 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
vuffiraa 2019-03-21 20:32:55 +00:00
parent 356769d935
commit caf640a03f
3 changed files with 567 additions and 524 deletions

View File

@ -1,5 +1,8 @@
# 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.
- changed: 70_BRAVIA: optimized command queue,
introduced own package,
new reading application
- feature: 93_Log2Syslog: parseProfile = Automatic for automatic protocol
detection (default) if a collector is defined
- feature: 93_DbRep: attribute "sqlCmdVars" to set SQL variables or PRAGMA

View File

@ -165,7 +165,7 @@ sub GetStatus($;$) {
my $name = $hash->{NAME};
my $interval = $hash->{INTERVAL};
my @successor = ();
Log3($name, 5, "BOTVAC $name: called function GetStatus()");
# use actionInterval if state is busy or paused
@ -260,7 +260,7 @@ sub Set($@) {
$usage .= " findMe:noArg" if ( GetServiceVersion($hash, "findMe") eq "basic-1" );
$usage .= " startManual:noArg" if ( GetServiceVersion($hash, "manualCleaning") ne "" );
$usage .= " statusRequest:noArg schedule:on,off syncRobots:noArg";
# house cleaning
$usage .= " nextCleaningMode:eco,turbo" if ($houseCleaningSrv =~ /basic-\d/);
$usage .= " nextCleaningNavigationMode:normal,extra#care" if ($houseCleaningSrv eq "minimal-2");
@ -442,7 +442,7 @@ sub Set($@) {
Log3($name, 2, "BOTVAC Can't set robot, run 'syncRobots' before");
}
}
# reloadMaps
elsif ( $a[1] eq "reloadMaps" ) {
Log3($name, 2, "BOTVAC set $name $arg");
@ -490,7 +490,7 @@ sub Set($@) {
readingsSingleUpdate($hash, $a[1], $a[2], 0);
}
# wsCommand || wsCommand
elsif ( $a[1] =~ /wsCombo|wsCommand/) {
Log3($name, 2, "BOTVAC set $name $arg");
@ -500,7 +500,7 @@ sub Set($@) {
my $cmd = ($a[1] eq "wsCombo" ? "combo" : "command");
wsEncode($hash, "{ \"$cmd\": \"$a[2]\" }");
}
# password
elsif ( $a[1] eq "password") {
Log3($name, 2, "BOTVAC set $name " . $a[1]);
@ -619,7 +619,7 @@ sub SendCommand($$;$$@) {
my $URL = "https://";
my $response;
my $return;
my %sslArgs;
if ($service ne "sessions" && $service ne "dashboard") {
@ -687,7 +687,7 @@ sub SendCommand($$;$$@) {
$data .= "\"category\":2";
$data .= ",\"mode\":";
$data .= (GetCleaningParameter($hash, "cleaningMode", "eco") eq "eco" ? "1" : "2");
$data .= ",\"modifier\":1";
$data .= ",\"modifier\":1";
} elsif ($version eq "minimal-2") {
$data .= "\"category\":2";
$data .= ",\"navigationMode\":";
@ -711,7 +711,7 @@ sub SendCommand($$;$$@) {
my $zone = GetCleaningParameter($hash, "cleaningZone", "");
$data .= ",\"boundaryId\":\"".$zone."\"" if ($zone ne "");
}
}
}
$data .= "}";
}
elsif ($cmd eq "startSpot") {
@ -724,7 +724,7 @@ sub SendCommand($$;$$@) {
$data .= (GetCleaningParameter($hash, "cleaningMode", "eco") eq "eco" ? "1" : "2");
}
if ($version eq "basic-1" or $version eq "minimal-2") {
$data .= ",\"modifier\":";
$data .= ",\"modifier\":";
$data .= (GetCleaningParameter($hash, "cleaningModifier", "normal") eq "normal" ? "1" : "2");
}
if ($version eq "micro-2" or $version eq "minimal-2") {
@ -732,14 +732,14 @@ sub SendCommand($$;$$@) {
$data .= (GetCleaningParameter($hash, "cleaningNavigationMode", "normal") eq "normal" ? "1" : "2");
}
if ($version eq "basic-1" or $version eq "basic-3") {
$data .= ",\"spotWidth\":";
$data .= ",\"spotWidth\":";
$data .= GetCleaningParameter($hash, "cleaningSpotWidth", "200");
$data .= ",\"spotHeight\":";
$data .= ",\"spotHeight\":";
$data .= GetCleaningParameter($hash, "cleaningSpotHeight", "200");
}
}
$data .= "}";
}
elsif ($cmd eq "setMapBoundaries" or $cmd eq "getMapBoundaries") {
elsif ($cmd eq "setMapBoundaries" or $cmd eq "getMapBoundaries") {
if (defined($option) and ref($option) eq "HASH") {
$data .= ",\"params\":{";
foreach( keys %$option ) {
@ -749,7 +749,7 @@ sub SendCommand($$;$$@) {
$data .= "}";
}
}
$data .= "}";
my $now = time();
@ -804,7 +804,7 @@ sub ReceiveCommand($$$) {
my @successor = @{$param->{successor}};
my $rc = ( $param->{buf} ) ? $param->{buf} : $param;
my $loadMap;
my $return;
my $reqId = 0;
@ -824,7 +824,7 @@ sub ReceiveCommand($$$) {
# keep last state
#readingsBulkUpdateIfChanged( $hash, "state", "Error" );
# stop pulling for current interval
Log3($name, 4, "BOTVAC $name: drop successors");
LogSuccessors($hash, @successor);
@ -833,7 +833,7 @@ sub ReceiveCommand($$$) {
# data received
elsif ($data) {
if ( !defined($cmd) ) {
Log3($name, 4, "BOTVAC $name: RCV $service");
} else {
@ -945,13 +945,13 @@ sub ReceiveCommand($$$) {
}
}
}
#remove outdated calendar information
foreach ( keys %currentEvents ) {
delete( $hash->{READINGS}{$_} );
}
}
}
}
elsif ( $cmd eq "getMapBoundaries" ) {
if ( ref($return->{data}) eq "HASH" ) {
$reqId = $return->{reqId};
@ -997,7 +997,7 @@ sub ReceiveCommand($$$) {
readingsBulkUpdateIfChanged($hash, "floorplan_".$reqId."_zones", $zonesList);
}
}
}
}
elsif ( $cmd eq "getGeneralInfo" ) {
if ( ref($return->{data}) eq "HASH" ) {
my $generalInfo = $return->{data};
@ -1017,11 +1017,11 @@ sub ReceiveCommand($$$) {
# sendToBase, setMapBoundaries, getRobotManualCleaningInfo
if ( ref($return) eq "HASH" ) {
push(@successor , ["robots", "maps"])
if ($cmd eq "setMapBoundaries" or
if ($cmd eq "setMapBoundaries" or
(defined($return->{state}) and
($return->{state} == 1 or $return->{state} == 4) and # Idle or Error
$return->{state} != ReadingsNum($name, "stateId", $return->{state})));
#readingsBulkUpdateIfChanged($hash, "version", $return->{version});
#readingsBulkUpdateIfChanged($hash, "data", $return->{data});
readingsBulkUpdateIfChanged($hash, "result", $return->{result}) if (defined($return->{result}));
@ -1090,14 +1090,14 @@ sub ReceiveCommand($$$) {
}
}
}
# Sessions
elsif ( $service eq "sessions" ) {
if ( ref($return) eq "HASH" and defined($return->{access_token})) {
readingsBulkUpdateIfChanged($hash, ".accessToken", $return->{access_token});
}
}
# dashboard
elsif ( $service eq "dashboard" ) {
if ( ref($return) eq "HASH" ) {
@ -1121,7 +1121,7 @@ sub ReceiveCommand($$$) {
$hash->{helper}{ROBOTS} = \@robotList;
SetRobot($hash, ReadingsNum($name, "robot", 0));
push(@successor , ["robots", "maps"]);
}
}
@ -1167,7 +1167,7 @@ sub ReceiveCommand($$$) {
}
}
}
# loadmap
elsif ( $service eq "loadmap" ) {
readingsBulkUpdate($hash, ".map_cache", $data)
@ -1181,12 +1181,12 @@ sub ReceiveCommand($$$) {
}
readingsEndUpdate( $hash, 1 );
if ($loadMap) {
my $url = ReadingsVal($name, ".map_url", "");
push(@successor , ["loadmap", $url]) if ($url ne "");
}
if (@successor) {
my @nextCmd = @{shift(@successor)};
my $cmdLength = @nextCmd;
@ -1279,13 +1279,13 @@ sub StorePassword($$) {
$key = Digest::MD5::md5_hex(unpack "H*", $key);
$key .= Digest::MD5::md5_hex($key);
}
for my $char (split //, $password) {
my $encode=chop($key);
$enc_pwd.=sprintf("%.2x",ord($char)^ord($encode));
$key=$encode.$key;
}
my $err = setKeyValue($index, $enc_pwd);
return "error while saving the password - $err" if(defined($err));
@ -1298,16 +1298,16 @@ sub ReadPassword($) {
my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd";
my $key = getUniqueId().$index;
my ($password, $err);
Log3($name, 4, "BOTVAC $name: Read password from file");
($err, $password) = getKeyValue($index);
if ( defined($err) ) {
Log3($name, 3, "BOTVAC $name: unable to read password from file: $err");
return undef;
return undef;
}
if ( defined($password) ) {
if ( eval "use Digest::MD5;1" ) {
$key = Digest::MD5::md5_hex(unpack "H*", $key);
@ -1333,22 +1333,22 @@ sub CheckRegistration($$$$$) {
if (ReadingsVal($name, ".secretKey", "") eq "") {
my @nextCmd = ($service, $cmd, $option);
unshift(@successor, [$service, $cmd, $option]);
my @succ_item;
my $msg = " successor:";
for (my $i = 0; $i < @successor; $i++) {
@succ_item = @{$successor[$i]};
$msg .= " $i: ";
$msg .= join(",", map { defined($_) ? $_ : '' } @succ_item);
}
Log3($name, 4, "BOTVAC created".$msg);
my @succ_item;
my $msg = " successor:";
for (my $i = 0; $i < @successor; $i++) {
@succ_item = @{$successor[$i]};
$msg .= " $i: ";
$msg .= join(",", map { defined($_) ? $_ : '' } @succ_item);
}
Log3($name, 4, "BOTVAC created".$msg);
SendCommand($hash, "sessions", undef, undef, @successor) if (ReadingsVal($name, ".accessToken", "") eq "");
SendCommand($hash, "dashboard", undef, undef, @successor) if (ReadingsVal($name, ".accessToken", "") ne "");
return 1;
}
return;
}
@ -1557,15 +1557,14 @@ sub LogSuccessors($@) {
my ($hash,@successor) = @_;
my $name = $hash->{NAME};
my $msg = "BOTVAC $name: RCV successors";
my $msg = "BOTVAC $name: successors";
my @succ_item;
for (my $i = 0; $i < @successor; $i++) {
@succ_item = @{$successor[$i]};
$msg .= " $i: ";
$msg .= join(",", map { defined($_) ? $_ : '' } @succ_item);
}
Log3($name, 4, $msg);
Log3($name, 4, $msg) if (@successor > 0);
}
sub ShowMap($;$$) {
@ -1575,23 +1574,23 @@ sub ShowMap($;$$) {
$img .= ' width="'.$width.'"' if (defined($width));
$img .= ' width="'.$height.'"' if (defined($height));
$img .= ' alt="Map currently not available">';
return $img;
}
sub GetMap() {
my ($request) = @_;
if ($request =~ /^\/BOTVAC\/(\w+)\/map/) {
my $name = $1;
my $width = $3;
my $height = $5;
return ("image/png", ReadingsVal($name, ".map_cache", ""));
}
return ("text/plain; charset=utf-8", "No BOTVAC device for webhook $request");
}
#######################################
@ -1604,7 +1603,7 @@ sub wsOpen($$$) {
Log3($name, 4, "BOTVAC(ws) $name: Establishing socket connection");
$hash->{DeviceName} = join(':', $ip_address, $port);
::DevIo_CloseDev($hash) if(::DevIo_IsOpen($hash));
::DevIo_CloseDev($hash) if(::DevIo_IsOpen($hash));
if (::DevIo_OpenDev($hash, 0, "BOTVAC::wsHandshake")) {
Log3($name, 2, "BOTVAC(ws) $name: ERROR: Can't open websocket to $hash->{DeviceName}");
@ -1640,7 +1639,7 @@ sub wsHandshake($) {
my $date = FmtDateTimeRFC1123($now);
my $message = lc($serial) . "\n" . $date . "\n";
my $hmac = hmac_sha256_hex($message, ReadingsVal($name, ".secretKey", ""));
my $wsHandshakeCmd = "GET $path HTTP/1.1\r\n";
$wsHandshakeCmd .= "Host: $host:$port\r\n";
$wsHandshakeCmd .= "Sec-WebSocket-Key: $wsKey\r\n";
@ -1650,13 +1649,13 @@ sub wsHandshake($) {
$wsHandshakeCmd .= "Date: $date\r\n";
$wsHandshakeCmd .= "Authorization: NEATOAPP $hmac\r\n";
$wsHandshakeCmd .= "Connection: Upgrade\r\n";
$wsHandshakeCmd .= "\r\n";
$wsHandshakeCmd .= "\r\n";
Log3($name, 4, "BOTVAC(ws) $name: Starting Websocket Handshake");
wsWrite($hash,$wsHandshakeCmd);
$hash->{HELPER}{wsKey} = $wsKey;
return undef;
}
@ -1696,7 +1695,7 @@ sub wsCheckHandshake($$) {
sub wsWrite($@) {
my ($hash,$string) = @_;
my $name = $hash->{NAME};
Log3($name, 4, "BOTVAC(ws) $name: WriteFn called:\n$string");
::DevIo_SimpleWrite($hash, $string, 0);
@ -1728,7 +1727,7 @@ sub wsCallback(@) {
my ($param, $err, $data) = @_;
my $hash = $param->{hash};
my $name = $hash->{NAME};
if($err){
Log3($name, 3, "received callback with error:\n$err");
} elsif($data){
@ -1793,10 +1792,10 @@ sub wsEncode($$;$$) {
$wsString .= pack 'N', $len >> 32;
$wsString .= pack 'N', ($len & 0xffffffff);
}
if ($masked) {
if ($masked) {
my $mask = pack 'N', int(rand(2**32));
$wsString .= $mask;
$wsString .= wsMasking($payload, $mask);
$wsString .= wsMasking($payload, $mask);
} else {
$wsString .= $payload;
}
@ -1815,9 +1814,9 @@ sub wsPong($) {
sub wsDecode($$) {
my ($hash,$wsString) = @_;
my $name = $hash->{NAME};
Log3($name, 5, "BOTVAC(ws) $name: String:\n" . $wsString);
while (length $wsString) {
my $FIN = (ord(substr($wsString,0,1)) & 0b10000000) >> 7;
my $OPCODE = (ord(substr($wsString,0,1)) & 0b00001111);
@ -2050,7 +2049,7 @@ sub wsMasking($$) {
<ul>
<li><code>house</code> - cleaning without a persisted map</li>
<li><code>map</code> - cleaning with a persisted map</li>
<li><code>zone</code> - cleaning in a specific zone, set zone with nextCleaningZone</li>
<li><code>zone</code> - cleaning in a specific zone, set zone with nextCleaningZone</li>
</ul>
</li>
<br>

File diff suppressed because it is too large Load Diff