mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 03:44:52 +00:00
74_AutomowerConnect: Common.pm, automowerconnect.js, handle userattr for API timeouts and logleveldevio, measure response time, prevent some warnings, update map via FW extension, reduce side effects while maually update mower data via polling
git-svn-id: https://svn.fhem.de/fhem/trunk@27684 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
f3eddb5d81
commit
5551c67305
@ -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_AutomowerConnect: Common.pm, automowerconnect.js
|
||||
handle userattr for API timeouts and logleveldevio, measure
|
||||
response time, prevent some warnings, update map via FW extension,
|
||||
reduce side effects while maually update mower data via polling
|
||||
- feature: 72_FRITZBOX: Attribut: disableHostIPv4check
|
||||
- bugfix: 72_FRITZBOX: Parameter Fehlerbehandlung: get fritzLog
|
||||
- change: 10_KNX: moved KNX_scan function to KNXIO-module, see Forum #122582
|
||||
|
@ -378,11 +378,39 @@ __END__
|
||||
</code></li>
|
||||
|
||||
<li><a href="disable">disable</a></li>
|
||||
|
||||
<li><a href="disabledForIntervals">disabledForIntervals</a></li>
|
||||
<br><br>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
|
||||
<a id="AutomowerConnectUserAttr"></a>
|
||||
<b>userattr</b><br>
|
||||
<ul>
|
||||
The following user attributes are taken into account.<br>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-loglevelDevIo'>loglevelDevIo</a><br>
|
||||
<code>attr <name> loglevelDevIo <[012345]></code><br>
|
||||
Set internal deviologlevel, <a target="_blank" href="https://wiki.fhem.de/wiki/DevIo#Wichtige_Internals_zur_Konfiguration"> DevIo: Wichtige_Internals_zur_Konfiguration</a> </li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-timeoutGetMower'>timeoutGetMower</a><br>
|
||||
<code>attr <name> timeoutGetMower <[6 to 60]></code><br>
|
||||
Set timeout for API call, default 5 s. </li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-timeoutApiAuth'>ApiAuth</a><br>
|
||||
<code>attr <name> timeoutApiAuth <[6 to 60]></code><br>
|
||||
Set timeout for API call, default 5 s. </li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-timeoutCMD'>timeoutCMD</a><br>
|
||||
<code>attr <name> timeoutCMD <[6 to 60]></code><br>
|
||||
Set timeout for API call, default 5 s. </li><br>
|
||||
The response time is meassured and logged if a timeout ist set to 60 s.
|
||||
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
|
||||
<a id="AutomowerConnectReadings"></a>
|
||||
<b>Readings</b>
|
||||
<ul>
|
||||
@ -407,7 +435,7 @@ __END__
|
||||
<li>settings_cuttingHeight - actual cutting height from API</li>
|
||||
<li>settings_headlight - actual headlight mode from API</li>
|
||||
<li>statistics_newGeoDataSets - number of new data sets between the last two different time stamps</li>
|
||||
<li>statistics_numberOfCollisions - Number of collisions (last day/all days)</li>
|
||||
<li>statistics_numberOfCollisions - Number of collisions (current day/last day/all days)</li>
|
||||
<li>status_connected - state of connetion between mower and Husqvarna Cloud.</li>
|
||||
<li>status_statusTimestamp - local time of last status update</li>
|
||||
<li>status_statusTimestampDiff - time difference in seconds between the last and second last status update</li>
|
||||
@ -708,11 +736,39 @@ __END__
|
||||
</code></li>
|
||||
|
||||
<li><a href="disable">disable</a></li>
|
||||
|
||||
<li><a href="disabledForIntervals">disabledForIntervals</a></li>
|
||||
<br>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
|
||||
<a id="AutomowerConnectUserAttr"></a>
|
||||
<b>userattr</b><br>
|
||||
<ul>
|
||||
Die folgenden Benutzerattribute werden unterstützt.<br>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-loglevelDevIo'>loglevelDevIo</a><br>
|
||||
<code>attr <name> loglevelDevIo <[012345]></code><br>
|
||||
Setzt das Internal deviologlevel, <a target="_blank" href="https://wiki.fhem.de/wiki/DevIo#Wichtige_Internals_zur_Konfiguration"> DevIo: Wichtige_Internals_zur_Konfiguration</a> </li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-timeoutGetMower'>timeoutGetMower</a><br>
|
||||
<code>attr <name> timeoutGetMower <[6 to 60]></code><br>
|
||||
Setzt den Timeout für das Lesen der Mäherdaten, default 5 s. </li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-timeoutApiAuth'>timeoutApiAuth</a><br>
|
||||
<code>attr <name> timeoutApiAuth <[6 to 60]></code><br>
|
||||
Setzt den Timeout für die Authentifikation, default 5 s. </li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-timeoutCMD'>timeoutCMD</a><br>
|
||||
<code>attr <name> timeoutCMD <[6 to 60]></code><br>
|
||||
Setzt den Timeout für Befehl senden, default 15 s. </li><br>
|
||||
Wird ein Timeout auf 60 s gesetzt, wird die Antwortzeit gemessen und geloggt.
|
||||
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
|
||||
<a id="AutomowerConnectReadings"></a>
|
||||
<b>Readings</b>
|
||||
<ul>
|
||||
@ -737,7 +793,7 @@ __END__
|
||||
<li>settings_cuttingHeight - aktuelle Schnitthöhe aus der API</li>
|
||||
<li>settings_headlight - aktueller Scheinwerfermode aus der API</li>
|
||||
<li>statistics_newGeoDataSets - Anzahl der neuen Datensätze zwischen den letzten zwei unterschiedlichen Zeitstempeln</li>
|
||||
<li>statistics_numberOfCollisions - Anzahl der Kollisionen (letzter Tag/alle Tage)</li>
|
||||
<li>statistics_numberOfCollisions - Anzahl der Kollisionen (laufender Tag/letzter Tag/alle Tage)</li>
|
||||
<li>status_connected - Status der Verbindung zwischen dem Automower und der Husqvarna Cloud.</li>
|
||||
<li>status_statusTimestamp - Lokalzeit des letzten Statusupdates in der API</li>
|
||||
<li>status_statusTimestampDiff - Zeitdifferenz zwischen dem letzten und vorletzten Statusupdate.</li>
|
||||
|
@ -47,6 +47,7 @@ BEGIN {
|
||||
CommandAttr
|
||||
CommandDeleteReading
|
||||
FmtDateTime
|
||||
FW_ME
|
||||
getKeyValue
|
||||
InternalTimer
|
||||
InternalVal
|
||||
@ -174,10 +175,14 @@ my $mapZonesTpl = '{
|
||||
interval_ping => 60,
|
||||
retry_interval_apiauth => 840,
|
||||
retry_interval_getmower => 840,
|
||||
timeout_apiauth => 5,
|
||||
timeout_getmower => 5,
|
||||
timeout_cmd => 15,
|
||||
midnightCycle => 1,
|
||||
client_id => $client_id,
|
||||
grant_type => 'client_credentials',
|
||||
mowerNumber => $mowerNumber,
|
||||
detailFnFirst => 0,
|
||||
scaleToMeterLongitude => 67425,
|
||||
scaleToMeterLatitude => 108886,
|
||||
minLon => 180,
|
||||
@ -187,7 +192,6 @@ my $mapZonesTpl = '{
|
||||
imageHeight => 650,
|
||||
imageWidthHeight => '350 650',
|
||||
mapdesign => $mapAttr,
|
||||
detailFnFirst => 0,
|
||||
mapZonesTpl => $mapZonesTpl,
|
||||
posMinMax => "-180 90\n180 -90",
|
||||
newdatasets => 0,
|
||||
@ -201,7 +205,8 @@ my $mapZonesTpl = '{
|
||||
positions => [],
|
||||
timestamp => 0,
|
||||
errordesc => '-',
|
||||
errordate => ''
|
||||
errordate => '',
|
||||
errorstate => ''
|
||||
},
|
||||
UNKNOWN => {
|
||||
short => 'U',
|
||||
@ -289,7 +294,7 @@ my $mapZonesTpl = '{
|
||||
|
||||
|
||||
AddExtension( $name, \&GetMap, "$type/$name/map" );
|
||||
# AddExtension( $name, \&GetJson, "$type/$name/json" );
|
||||
AddExtension( $name, \&GetJson, "$type/$name/json" );
|
||||
|
||||
if ( $::init_done ) {
|
||||
|
||||
@ -340,6 +345,8 @@ sub Undefine {
|
||||
|
||||
RemoveInternalTimer( $hash );
|
||||
RemoveExtension( "$type/$name/map" );
|
||||
RemoveExtension( "$type/$name/json" );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -364,7 +371,9 @@ sub Rename {
|
||||
my $type = $hash->{TYPE};
|
||||
|
||||
RemoveExtension( "$type/$oldname/map" );
|
||||
RemoveExtension( "$type/$oldname/json" );
|
||||
AddExtension( $newname, \&GetMap, "$type/$newname/map" );
|
||||
AddExtension( $newname, \&GetJson, "$type/$newname/json" );
|
||||
|
||||
if ( $type eq 'AutomowerConnect' ) {
|
||||
|
||||
@ -436,7 +445,7 @@ sub FW_detailFn {
|
||||
|
||||
if ( $hash->{helper} && $hash->{helper}{mower} && $hash->{helper}{mower}{attributes} && $hash->{helper}{mower}{attributes}{positions} && @{$hash->{helper}{mower}{attributes}{positions}} > 0 ) {
|
||||
|
||||
my $img = "./fhem/$type/$name/map";
|
||||
my $img = "$FW_ME/$type/$name/map";
|
||||
my $zoom=AttrVal( $name,"mapImageZoom", 0.7 );
|
||||
my $backgroundcolor = AttrVal($name, 'mapBackgroundColor','');
|
||||
my $bgstyle = $backgroundcolor ? " background-color:$backgroundcolor;" : '';
|
||||
@ -544,45 +553,95 @@ sub FW_detailFn_Update {
|
||||
my $mapy = $latlo-$latru;
|
||||
|
||||
# MOWING PATH
|
||||
my $posxy = '';
|
||||
my @posxy = ();
|
||||
|
||||
if ( @pos > 0 ) {
|
||||
my $k = 0;
|
||||
for ( my $i = 0; $i < @pos; $i++ ){
|
||||
|
||||
$posxy = int( ( $lonlo-$pos[ 0 ]{longitude} ) * $picx / $mapx ).",".int( ( $latlo-$pos[ 0 ]{latitude} ) * $picy / $mapy ).",'".$pos[ 0 ]{act}."'";
|
||||
|
||||
for ( my $i = 1; $i < @pos; $i++ ){
|
||||
|
||||
$posxy .= ",".int( ( $lonlo - $pos[ $i ]{longitude} ) * $picx / $mapx ).",".int( ( $latlo - $pos[ $i ]{latitude} ) * $picy / $mapy ).",'".$pos[ $i ]{act}."'";
|
||||
$posxy[ $k++ ] = int( ( $lonlo - $pos[ $i ]{longitude} ) * $picx / $mapx );
|
||||
$posxy[ $k++ ] = int( ( $latlo - $pos[ $i ]{latitude} ) * $picy / $mapy );
|
||||
$posxy[ $k++ ] = $pos[ $i ]{act};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# MOWING PATH OLD
|
||||
# my $posxy = '';
|
||||
|
||||
# if ( @pos > 0 ) {
|
||||
|
||||
# $posxy = int( ( $lonlo-$pos[ 0 ]{longitude} ) * $picx / $mapx ).",".int( ( $latlo-$pos[ 0 ]{latitude} ) * $picy / $mapy ).",'".$pos[ 0 ]{act}."'";
|
||||
|
||||
# for ( my $i = 1; $i < @pos; $i++ ){
|
||||
|
||||
# $posxy .= ",".int( ( $lonlo - $pos[ $i ]{longitude} ) * $picx / $mapx ).",".int( ( $latlo - $pos[ $i ]{latitude} ) * $picy / $mapy ).",'".$pos[ $i ]{act}."'";
|
||||
|
||||
# }
|
||||
|
||||
# }
|
||||
|
||||
# ERROR MESSAGE
|
||||
my $errdesc = $hash->{helper}{lasterror}{errordesc};
|
||||
my $errdate = $hash->{helper}{lasterror}{errordate};
|
||||
my $errstate = $hash->{helper}{lasterror}{errorstate};
|
||||
|
||||
# ERROR PATH
|
||||
my $poserrxy = int( ( $lonru-$lonlo ) / 2 * $picx / $mapx ).",".int( ( $latlo - $latru ) / 2 * $picy / $mapy );;
|
||||
|
||||
my @poserrxy = ( int( ( $lonru-$lonlo ) / 2 * $picx / $mapx ), int( ( $latlo - $latru ) / 2 * $picy / $mapy ) );
|
||||
|
||||
if ( @poserr > 0 ) {
|
||||
my $k = 0;
|
||||
for ( my $i = 0; $i < @poserr; $i++ ){
|
||||
|
||||
$poserrxy = int( ( $lonlo - $poserr[ 0 ]{longitude} ) * $picx / $mapx ) . "," . int( ( $latlo - $poserr[ 0 ]{latitude} ) * $picy / $mapy );
|
||||
$poserrxy[ $k++ ] = int( ( $lonlo - $poserr[ $i ]{longitude} ) * $picx / $mapx );
|
||||
$poserrxy[ $k++ ] = int( ( $latlo - $poserr[ $i ]{latitude} ) * $picy / $mapy );
|
||||
|
||||
for ( my $i = 1; $i < @poserr; $i++ ){
|
||||
$poserrxy .= ",".int( ( $lonlo - $poserr[ $i ]{longitude} ) * $picx / $mapx) . "," . int( ( $latlo - $poserr[ $i ]{latitude} ) * $picy / $mapy );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# ERROR PATH OLD
|
||||
# my $poserrxy = int( ( $lonru-$lonlo ) / 2 * $picx / $mapx ).",".int( ( $latlo - $latru ) / 2 * $picy / $mapy );;
|
||||
|
||||
# if ( @poserr > 0 ) {
|
||||
|
||||
# $poserrxy = int( ( $lonlo - $poserr[ 0 ]{longitude} ) * $picx / $mapx ) . "," . int( ( $latlo - $poserr[ 0 ]{latitude} ) * $picy / $mapy );
|
||||
|
||||
# for ( my $i = 1; $i < @poserr; $i++ ){
|
||||
# $poserrxy .= ",".int( ( $lonlo - $poserr[ $i ]{longitude} ) * $picx / $mapx) . "," . int( ( $latlo - $poserr[ $i ]{latitude} ) * $picy / $mapy );
|
||||
# }
|
||||
|
||||
# }
|
||||
|
||||
# Log3 $name, 1, "AutomowerConnectUpdateDetail ( '$name', '$type', $detailFnFirst, $picx, $picy, $scalx, [ '$errdesc', '$errdate' ], [ $posxy ], [ $poserrxy ] )";
|
||||
my $detailFnFirst = $hash->{helper}{detailFnFirst};
|
||||
|
||||
# map {
|
||||
# ::FW_directNotify("#FHEMWEB:$_", "AutomowerConnectUpdateDetail ( '$name', '$type', $detailFnFirst, $picx, $picy, $scalx, [ '$errdesc', '$errdate', '$errstate' ], [ $posxy ], [ $poserrxy ] )","");
|
||||
# } devspec2array("TYPE=FHEMWEB");
|
||||
|
||||
# prepare hash for json map update
|
||||
$hash->{helper}{mapupdate}{name} = $name;
|
||||
$hash->{helper}{mapupdate}{type} = $type;
|
||||
$hash->{helper}{mapupdate}{detailfnfirst} = $hash->{helper}{detailFnFirst};
|
||||
$hash->{helper}{mapupdate}{lonlo} = $lonlo;
|
||||
$hash->{helper}{mapupdate}{latlo} = $latlo;
|
||||
$hash->{helper}{mapupdate}{mapx} = $mapx;
|
||||
$hash->{helper}{mapupdate}{mapy} = $mapy;
|
||||
$hash->{helper}{mapupdate}{picx} = $picx;
|
||||
$hash->{helper}{mapupdate}{picy} = $picy;
|
||||
$hash->{helper}{mapupdate}{scalx} = $scalx;
|
||||
$hash->{helper}{mapupdate}{errdesc} = [ "$errdesc", "$errdate", "$errstate" ];
|
||||
$hash->{helper}{mapupdate}{posxy} = \@posxy;
|
||||
$hash->{helper}{mapupdate}{poserrxy} = \@poserrxy;
|
||||
|
||||
map {
|
||||
::FW_directNotify("#FHEMWEB:$_", "AutomowerConnectUpdateDetail ( '$name', '$type', $detailFnFirst, $picx, $picy, $scalx, [ '$errdesc', '$errdate' ], [ $posxy ], [ $poserrxy ] )","");
|
||||
::FW_directNotify("#FHEMWEB:$_", "AutomowerConnectUpdateJson ( '$FW_ME/$type/$name/json' )","");
|
||||
} devspec2array("TYPE=FHEMWEB");
|
||||
|
||||
$hash->{helper}{detailFnFirst} = 0;
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -617,17 +676,19 @@ sub APIAuth {
|
||||
my $client_id = $hash->{helper}->{client_id};
|
||||
my $client_secret = $hash->{helper}->{passObj}->getReadPassword( $name );
|
||||
my $grant_type = $hash->{helper}->{grant_type};
|
||||
my $timeout = AttrVal( $name, 'timeoutApiAuth', $hash->{helper}->{timeout_apiauth} );
|
||||
|
||||
my $header = "Content-Type: application/x-www-form-urlencoded\r\nAccept: application/json";
|
||||
my $data = 'grant_type=' . $grant_type.'&client_id=' . $client_id . '&client_secret=' . $client_secret;
|
||||
::HttpUtils_NonblockingGet( {
|
||||
url => AUTHURL . '/oauth2/token',
|
||||
timeout => 5,
|
||||
timeout => $timeout,
|
||||
hash => $hash,
|
||||
method => 'POST',
|
||||
header => $header,
|
||||
data => $data,
|
||||
callback => \&APIAuthResponse,
|
||||
t_begin => scalar gettimeofday()
|
||||
} );
|
||||
}
|
||||
} else {
|
||||
@ -648,6 +709,7 @@ sub APIAuthResponse {
|
||||
my $statuscode = $param->{code} // '';
|
||||
my $iam = "$type $name APIAuthResponse:";
|
||||
|
||||
Log3 $name, 1, "$iam response time ". sprintf( "%.2f", ( gettimeofday() - $param->{t_begin} ) ) . ' s' if ( $param->{timeout} == 60 );
|
||||
Log3 $name, 1, "\ndebug $iam \n\$statuscode [$statuscode]\n\$err [$err],\n \$data [$data] \n\$param->url $param->{url}" if ( AttrVal($name, 'debug', '') );
|
||||
|
||||
if( !$err && $statuscode == 200 && $data) {
|
||||
@ -726,17 +788,19 @@ sub getMower {
|
||||
my $access_token = ReadingsVal($name,".access_token","");
|
||||
my $provider = ReadingsVal($name,".provider","");
|
||||
my $client_id = $hash->{helper}->{client_id};
|
||||
my $timeout = AttrVal( $name, 'timeoutGetMower', $hash->{helper}->{timeout_getmower} );
|
||||
|
||||
my $header = "Accept: application/vnd.api+json\r\nX-Api-Key: " . $client_id . "\r\nAuthorization: Bearer " . $access_token . "\r\nAuthorization-Provider: " . $provider;
|
||||
Log3 $name, 5, "$iam header [ $header ]";
|
||||
|
||||
::HttpUtils_NonblockingGet({
|
||||
url => APIURL . "/mowers",
|
||||
timeout => 5,
|
||||
timeout => $timeout,
|
||||
hash => $hash,
|
||||
method => "GET",
|
||||
header => $header,
|
||||
callback => \&getMowerResponse,
|
||||
t_begin => scalar gettimeofday()
|
||||
});
|
||||
|
||||
|
||||
@ -750,10 +814,11 @@ sub getMowerResponse {
|
||||
my $hash = $param->{hash};
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $statuscode = $param->{code};
|
||||
my $statuscode = $param->{code} // '';
|
||||
my $iam = "$type $name getMowerResponse:";
|
||||
my $mowerNumber = $hash->{helper}{mowerNumber};
|
||||
|
||||
Log3 $name, 1, "$iam response time ". sprintf( "%.2f", ( gettimeofday() - $param->{t_begin} ) ) . ' s' if ( $param->{timeout} == 60 );
|
||||
Log3 $name, 1, "debug $iam \$statuscode [$statuscode]\n\$err [$err],\n \$data [$data] \n\$param->url $param->{url}" if ( AttrVal($name, 'debug', '') );
|
||||
|
||||
if( !$err && $statuscode == 200 && $data) {
|
||||
@ -800,6 +865,7 @@ sub getMowerResponse {
|
||||
$hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp} = $hash->{helper}{mowers}[$mowerNumber]{attributes}{metadata}{statusTimestamp};
|
||||
$hash->{helper}{mowerold}{attributes}{mower}{activity} = $hash->{helper}{mowers}[$mowerNumber]{attributes}{mower}{activity};
|
||||
$hash->{helper}{mowerold}{attributes}{statistics}{numberOfCollisions} = $hash->{helper}{mowers}[$mowerNumber]{attributes}{statistics}{numberOfCollisions};
|
||||
$hash->{helper}{statistics}{numberOfCollisionsOld} = $hash->{helper}{mowers}[$mowerNumber]{attributes}{statistics}{numberOfCollisions};
|
||||
|
||||
if ( AttrVal( $name, 'mapImageCoordinatesToRegister', '' ) eq '' ) {
|
||||
posMinMax( $hash, $hash->{helper}{mowers}[$mowerNumber]{attributes}{positions} );
|
||||
@ -873,6 +939,7 @@ sub CMD {
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $iam = "$type $name CMD:";
|
||||
my $timeout = AttrVal( $name, 'timeoutCMD', $hash->{helper}->{timeout_cmd} );
|
||||
$hash->{helper}{mower_commandSend} = $cmd[ 0 ] . ' ' . ( $cmd[ 1 ] ? $cmd[ 1 ] : '' );
|
||||
|
||||
if ( IsDisabled( $name ) ) {
|
||||
@ -920,12 +987,13 @@ my $header = "Accept: application/vnd.api+json\r\nX-Api-Key: ".$client_id."\r\nA
|
||||
|
||||
::HttpUtils_NonblockingGet({
|
||||
url => APIURL . "/mowers/". $mower_id . "/".$post,
|
||||
timeout => 15,
|
||||
timeout => $timeout,
|
||||
hash => $hash,
|
||||
method => "POST",
|
||||
header => $header,
|
||||
data => $json,
|
||||
callback => \&CMDResponse,
|
||||
t_begin => scalar gettimeofday()
|
||||
});
|
||||
|
||||
}
|
||||
@ -939,6 +1007,7 @@ sub CMDResponse {
|
||||
my $statuscode = $param->{code};
|
||||
my $iam = "$type $name CMDResponse:";
|
||||
|
||||
Log3 $name, 1, "$iam response time ". sprintf( "%.2f", ( gettimeofday() - $param->{t_begin} ) ) . ' s' if ( $param->{timeout} == 60 );
|
||||
Log3 $name, 1, "\ndebug $iam \n\$statuscode [$statuscode]\n\$err [$err],\n \$data [$data] \n\$param->url $param->{url}" if ( AttrVal($name, 'debug', '') );
|
||||
|
||||
if( !$err && $statuscode == 202 && $data ) {
|
||||
@ -1169,6 +1238,34 @@ sub Attr {
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif( $attrName eq "loglevelDevIo" ) {
|
||||
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
return "$iam $attrName is invalid, select a number of [012345]" unless( $attrVal =~ /^[0-5]{1}$/ );
|
||||
$hash->{devioLoglevel} = $attrVal;
|
||||
Log3 $name, 4, "$iam $cmd $attrName $attrVal";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
delete( $hash->{devioLoglevel} );
|
||||
Log3 $name, 3, "$iam $cmd $attrName and set default.";
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif( $attrName =~ /^(timeoutGetMower|timeoutApiAuth|timeoutCMD)$/ ) {
|
||||
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
return "$iam $attrVal is invalid, allowed time as integer between 5 and 61" unless( $attrVal =~ /^[\d]{1,2}$/ && $attrVal > 5 && $attrVal < 61 );
|
||||
Log3 $name, 4, "$iam $cmd $attrName $attrVal";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
Log3 $name, 3, "$iam $cmd $attrName and set default value.";
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif ( $attrName eq 'numberOfWayPointsToDisplay' ) {
|
||||
|
||||
my $icurr = scalar @{$hash->{helper}{areapos}};
|
||||
@ -1179,7 +1276,7 @@ sub Attr {
|
||||
for ( my $i = $icurr; $i > $attrVal; $i-- ) {
|
||||
pop @{$hash->{helper}{areapos}};
|
||||
}
|
||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||
Log3 $name, 4, "$iam $cmd $attrName $attrVal";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
@ -1360,6 +1457,8 @@ sub AlignArray {
|
||||
|
||||
@ar = reverse @ar if ( $cnt > 1 ); # positions seem to be in reversed order
|
||||
|
||||
# @ar = @ar if ( $cnt > 1 ); # positions seem to be not in reversed order
|
||||
|
||||
$tmp = dclone( \@ar );
|
||||
|
||||
if ( @{ $hash->{helper}{areapos} } ) {
|
||||
@ -1434,6 +1533,7 @@ sub isErrorThanPrepare {
|
||||
my $errc = $hash->{helper}{mower}{attributes}{mower}{errorCode};
|
||||
$hash->{helper}{lasterror}{errordesc} = $::FHEM::Devices::AMConnect::Common::errortable->{$errc};
|
||||
$hash->{helper}{lasterror}{errordate} = FmtDateTimeGMT( $ect / 1000 );
|
||||
$hash->{helper}{lasterror}{errorstate} = $hash->{helper}{mower}{attributes}{mower}{state};
|
||||
$hash->{helper}{lasterror}{errorzone} = $hash->{helper}{currentZone} if ( defined( $hash->{helper}{currentZone} ) );
|
||||
|
||||
my $tmp = dclone( $hash->{helper}{lasterror} );
|
||||
@ -1458,6 +1558,7 @@ sub resetLastErrorIfCorrected {
|
||||
$hash->{helper}{lasterror}{timestamp} = 0;
|
||||
$hash->{helper}{lasterror}{errordesc} = '-';
|
||||
$hash->{helper}{lasterror}{errordate} = '';
|
||||
$hash->{helper}{lasterror}{errorstate} = '';
|
||||
::FHEM::Devices::AMConnect::Common::FW_detailFn_Update ($hash);
|
||||
|
||||
}
|
||||
@ -1653,22 +1754,28 @@ sub GetMap() {
|
||||
}
|
||||
|
||||
#########################
|
||||
# sub GetJson() {
|
||||
# my ($request) = @_;
|
||||
sub GetJson() {
|
||||
my ($request) = @_;
|
||||
|
||||
# if ( $request =~ /^\/(AutomowerConnect)\/(\w+)\/json/ ) {
|
||||
if ( $request =~ /^\/(AutomowerConnect)\/(\w+)\/json/ ) {
|
||||
|
||||
# my $type = $1;
|
||||
# my $name = $2;
|
||||
# my $hash = $::defs{$name};
|
||||
# my $jsonMime = "application/json";
|
||||
# my $jsonData = eval { encode_json ( $hash->{helper}{areapos} ) };
|
||||
# return ( $jsonMime, $jsonData );
|
||||
my $type = $1;
|
||||
my $name = $2;
|
||||
my $hash = $::defs{$name};
|
||||
my $jsonMime = "application/json";
|
||||
my $jsonData = eval { encode_json ( $hash->{helper}{mapupdate} ) };
|
||||
if ($@) {
|
||||
|
||||
# }
|
||||
# return ( "text/plain; charset=utf-8", "No AutomowerConnect device for webhook $request" );
|
||||
Log3 $name, 2, "$type $name encode_json error: $@";
|
||||
return ( "text/plain; charset=utf-8", "No AutomowerConnect device for webhook $request" );
|
||||
|
||||
# }
|
||||
}
|
||||
return ( $jsonMime, $jsonData );
|
||||
|
||||
}
|
||||
return ( "text/plain; charset=utf-8", "No AutomowerConnect device for webhook $request" );
|
||||
|
||||
}
|
||||
|
||||
#########################
|
||||
sub readMap {
|
||||
@ -1782,7 +1889,8 @@ sub fillReadings {
|
||||
readingsBulkUpdateIfChanged($hash, "planner_nextStart", $tstamp ? $timestamp : '-' );
|
||||
|
||||
$pref = 'statistics';
|
||||
readingsBulkUpdateIfChanged( $hash, $pref."_numberOfCollisions", '(' . $hash->{helper}{statistics}{lastDayCollisions} . '/' . $hash->{helper}{mower}{attributes}{$pref}{numberOfCollisions} . ')' );
|
||||
my $noCol = $hash->{helper}{mower}{attributes}{$pref}{numberOfCollisions} - $hash->{helper}{mowerold}{attributes}{$pref}{numberOfCollisions};
|
||||
readingsBulkUpdateIfChanged( $hash, $pref."_numberOfCollisions", '(' . $noCol . '/' . $hash->{helper}{statistics}{lastDayCollisions} . '/' . $hash->{helper}{mower}{attributes}{$pref}{numberOfCollisions} . ')' );
|
||||
readingsBulkUpdateIfChanged( $hash, $pref."_newGeoDataSets", $hash->{helper}{newdatasets} );
|
||||
$pref = 'settings';
|
||||
readingsBulkUpdateIfChanged( $hash, $pref."_headlight", $hash->{helper}{mower}{attributes}{$pref}{headlight}{mode} );
|
||||
@ -1806,7 +1914,9 @@ sub calculateStatistics {
|
||||
$hash->{helper}{statistics}{lastDayTrack} = $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{lastDayArea} = $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{lastDayTime} = $hash->{helper}{statistics}{currentDayTime};
|
||||
$hash->{helper}{statistics}{lastDayCollisions} = $hash->{helper}{mower}{attributes}{statistics}{numberOfCollisions} - $hash->{helper}{mowerold}{attributes}{statistics}{numberOfCollisions};
|
||||
$hash->{helper}{statistics}{lastDayCollisions} = $hash->{helper}{mower}{attributes}{statistics}{numberOfCollisions} - $hash->{helper}{statistics}{numberOfCollisionsOld};
|
||||
$hash->{helper}{statistics}{numberOfCollisionsOld} = $hash->{helper}{mower}{attributes}{statistics}{numberOfCollisions};
|
||||
|
||||
$hash->{helper}{statistics}{currentWeekTrack} += $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{currentWeekArea} += $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentWeekTime} += $hash->{helper}{statistics}{currentDayTime};
|
||||
@ -2056,7 +2166,7 @@ sub listErrorStack {
|
||||
|
||||
for ( my $i = 0; $i < @{ $hash->{helper}{errorstack} }; $i++ ) {
|
||||
|
||||
$cnt++; $ret .= '<tr class="column '.( $cnt % 2 ? 'odd' : 'even' ).'"><td> ' . $hash->{helper}{errorstack}[$i]{errordate} . ' </td><td> ' . $hash->{helper}{errorstack}[$i]{errordesc} . ' </td><td> ' . $hash->{helper}{errorstack}[$i]{errorzone} . ' </td><td> ' . $hash->{helper}{errorstack}[$i]{positions}[0]{longitude} . ' / ' . $hash->{helper}{errorstack}[$i]{positions}[0]{latitude} . ' </td></tr>';
|
||||
$cnt++; $ret .= '<tr class="column '.( $cnt % 2 ? 'odd' : 'even' ).'"><td> ' . $hash->{helper}{errorstack}[$i]{errordate} . ' </td><td> ' . $hash->{helper}{errorstack}[$i]{errorstate} . ' - ' . $hash->{helper}{errorstack}[$i]{errordesc} . ' </td><td> ' . $hash->{helper}{errorstack}[$i]{errorzone} . ' </td><td> ' . $hash->{helper}{errorstack}[$i]{positions}[0]{longitude} . ' / ' . $hash->{helper}{errorstack}[$i]{positions}[0]{latitude} . ' </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
@ -2299,17 +2409,17 @@ sub wsRead {
|
||||
|
||||
AlignArray( $hash );
|
||||
|
||||
my $deltaTime = $hash->{helper}{positionsTime} - $hash->{helper}{statusTime};
|
||||
# my $deltaTime = $hash->{helper}{positionsTime} - $hash->{helper}{statusTime};
|
||||
|
||||
# if encounter positions shortly after status-event count it as error positions
|
||||
if ( $hash->{helper}{mower}{attributes}{mower}{errorCode} && $deltaTime > 0 && $deltaTime < 0.29 && @{ $result->{attributes}{positions} } < 3) {
|
||||
# if ( $hash->{helper}{mower}{attributes}{mower}{errorCode} && $deltaTime > 0 && $deltaTime < 0.29 && @{ $result->{attributes}{positions} } < 3) {
|
||||
|
||||
$hash->{helper}{areapos}[ 0 ]{act} = 'N';
|
||||
$hash->{helper}{areapos}[ 1 ]{act} = 'N';
|
||||
$hash->{helper}{lasterror}{positions} = [dclone( $hash->{helper}{areapos}[ 0 ] ), dclone( $hash->{helper}{areapos}[ 1 ] ) ];
|
||||
$hash->{helper}{errorstack}[0]{positions} = [dclone( $hash->{helper}{areapos}[ 0 ] ), dclone( $hash->{helper}{areapos}[ 1 ] ) ];
|
||||
# $hash->{helper}{areapos}[ 0 ]{act} = 'N';
|
||||
# $hash->{helper}{areapos}[ 1 ]{act} = 'N';
|
||||
# $hash->{helper}{lasterror}{positions} = [dclone( $hash->{helper}{areapos}[ 0 ] ), dclone( $hash->{helper}{areapos}[ 1 ] ) ];
|
||||
# $hash->{helper}{errorstack}[0]{positions} = [dclone( $hash->{helper}{areapos}[ 0 ] ), dclone( $hash->{helper}{areapos}[ 1 ] ) ];
|
||||
|
||||
}
|
||||
# }
|
||||
|
||||
FW_detailFn_Update ($hash);
|
||||
|
||||
|
@ -6,7 +6,7 @@ function AutomowerConnectShowError( ctx, div, dev, picx, picy, errdesc, erray )
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = div.getAttribute( 'data-errorBackgroundColor' );
|
||||
ctx.font = div.getAttribute( 'data-errorFont' );
|
||||
var m = ctx.measureText( errdesc[ 1 ] + ', ' + dev + ': ' + errdesc[ 0 ] ).width > picy - 6;
|
||||
var m = ctx.measureText( errdesc[ 1 ] + ', ' + dev + ': ' + errdesc[ 2 ] + ' - ' + errdesc[ 0 ] ).width > picx - 6;
|
||||
|
||||
if ( m ) {
|
||||
|
||||
@ -24,11 +24,11 @@ function AutomowerConnectShowError( ctx, div, dev, picx, picy, errdesc, erray )
|
||||
if ( m ) {
|
||||
|
||||
ctx.fillText( errdesc[ 1 ] + ', ' + dev + ':', 3, 15 );
|
||||
ctx.fillText( errdesc[ 0 ], 3, 30 );
|
||||
ctx.fillText( errdesc[ 2 ] + ' - ' + errdesc[ 0 ], 3, 30 );
|
||||
|
||||
} else {
|
||||
|
||||
ctx.fillText( errdesc[ 1 ] + ', ' + dev + ': ' + errdesc[ 0 ], 3, 15 );
|
||||
ctx.fillText( errdesc[ 1 ] + ', ' + dev + ': ' + errdesc[ 2 ] + ' - ' + errdesc[ 0 ], 3, 15 );
|
||||
|
||||
}
|
||||
|
||||
@ -271,11 +271,18 @@ function AutomowerConnectTor ( x0, y0, x1, y1 ) {
|
||||
//~ log ('ret: ' + ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function AutomowerConnectUpdateJson ( path ) {
|
||||
$.getJSON( path, function( data, textStatus ) {
|
||||
log( 'AutomowerConnectUpdateJson ( '+path+' ): status '+textStatus );
|
||||
AutomowerConnectUpdateDetail ( data.name, data.type, data.detailfnfirst, data.picx, data.picy, data.scalx, data.errdesc, data.posxy, data.poserrxy );
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//AutomowerConnectUpdateDetail (<devicename>, <type>, <detailfnfirst>, <imagesize x>, <imagesize y>,<scale x>, <error description>, <path array>, <error array>)
|
||||
function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, scalx, errdesc, pos, erray) {
|
||||
//~ $.getJSON('./fhem/AutomowerConnect/am430x/json', function(data) {
|
||||
//~ log(data[0].longitude+' '+data[0].latitude+' '+data[0].act);
|
||||
//~ });
|
||||
const colorat = {
|
||||
"U" : "otherActivityPath",
|
||||
"N" : "errorPath",
|
||||
@ -286,7 +293,6 @@ function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, sca
|
||||
"L" : "leavingPath",
|
||||
"G" : "goingHomePath"
|
||||
};
|
||||
// log('pos.length '+pos.length+' lixy.length '+lixy.length+', scalx '+scalx );
|
||||
// log('loop: Start '+ type+' '+dev );
|
||||
if (FW_urlParams.detail == dev || 1) {
|
||||
const canvas_0 = document.getElementById(type+'_'+dev+'_canvas_0');
|
||||
@ -295,7 +301,7 @@ function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, sca
|
||||
|
||||
if ( canvas && canvas_0 ) {
|
||||
|
||||
// log('loop: canvas && canvas_0 true '+ type+' '+dev );
|
||||
// log('loop: canvas && canvas_0 true '+ type+' '+dev + ' detailfnfirst '+detailfnfirst);
|
||||
|
||||
if ( detailfnfirst ) {
|
||||
|
||||
@ -306,6 +312,7 @@ function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, sca
|
||||
// draw area limits
|
||||
const lixy = div.getAttribute( 'data-areaLimitsPath' ).split(",");
|
||||
if ( lixy.length > 0 ) AutomowerConnectLimits( ctx0, div, lixy, 'area' );
|
||||
// log('pos.length '+pos.length+' lixy.length '+lixy.length+', scalx '+scalx );
|
||||
|
||||
// draw property limits
|
||||
const plixy = div.getAttribute( 'data-propertyLimitsPath' ).split( "," );
|
||||
|
Loading…
x
Reference in New Issue
Block a user