mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 09:55:38 +00:00
74_AutomowerConnect: Common.pm try to reconnect if ws is open but not ready, improve leaving path colorization if position polling is on, some changes in automowerconnect.js, Cref update.
git-svn-id: https://svn.fhem.de/fhem/trunk@27764 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
6e0afc46fc
commit
3fc28e47db
fhem
@ -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.
|
||||
- change: 74_AutomowerConnect: Common.pm try to reconnect if ws is open but
|
||||
not ready, improve leaving path colorization if position polling is
|
||||
on, some changes in automowerconnect.js, Cref update.
|
||||
- new: 98_KNX_scan: implement FHEM-cmd: KNX_scan
|
||||
- change: 00_KNXIO.pm: moved KNX_scan perl function to 10_KNX.pm
|
||||
- change: 10_KNX.pm: moved KNX_scan perl function to 10_KNX.pm
|
||||
|
@ -378,7 +378,7 @@ __END__
|
||||
|
||||
<li><a id='AutomowerConnect-attr-addPollingMinInterval'>addPollingMinInterval</a><br>
|
||||
<code>attr <name> addPollingMinInterval <interval in seconds></code><br>
|
||||
Set minimum intervall for additional polling, default 0 (no polling). Gets periodically statistics data from mower. Make sure to be within API limits (10000 calls per month).</li>
|
||||
Set minimum intervall for additional polling triggered by status-event, default 0 (no polling). Gets periodically statistics data from mower. Make sure to be within API limits (10000 calls per month).</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-addPositionPolling'>addPositionPolling</a><br>
|
||||
<code>attr <name> addPositionPolling <[1|<b>0</b>]></code><br>
|
||||
@ -741,7 +741,7 @@ __END__
|
||||
|
||||
<li><a id='AutomowerConnect-attr-addPollingMinInterval'>addPollingMinInterval</a><br>
|
||||
<code>attr <name> addPollingMinInterval <interval in seconds></code><br>
|
||||
Setzt das Mindestintervall für zusätzliches Polling der API, default 0 (kein Polling). Liest periodisch statistische Daten vom Mäher. Es muss sichergestellt werden, das die API Begrenzung (10000 Anfragen pro Monat) eingehalten wird.</li>
|
||||
Setzt das Mindestintervall für zusätzliches Polling der API nach einem status-event, default 0 (kein Polling). Liest periodisch zusätzlich statistische Daten vom Mäher. Es muss sichergestellt werden, das die API Begrenzung (10000 Anfragen pro Monat) eingehalten wird.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-addPositionPolling'>addPositionPolling</a><br>
|
||||
<code>attr <name> addPositionPolling <[1|<b>0</b>]></code><br>
|
||||
|
@ -156,7 +156,9 @@ mowingPathLineColor="#ff0000"
|
||||
mowingPathLineDash="6,2"
|
||||
mowingPathLineWidth="1"
|
||||
mowingPathDotWidth="2"
|
||||
mowingPathUseDots=""';
|
||||
mowingPathUseDots=""
|
||||
mowingPathShowCollisions=""
|
||||
';
|
||||
|
||||
my $mapZonesTpl = '{
|
||||
"01_oben" : {
|
||||
@ -174,11 +176,13 @@ my $mapZonesTpl = '{
|
||||
passObj => FHEM::Core::Authentication::Passwords->new($type),
|
||||
interval => 840,
|
||||
interval_ws => 7110,
|
||||
interval_ping => 60,
|
||||
interval_ping => 570,
|
||||
use_position_polling => 0,
|
||||
additional_polling => 0,
|
||||
reverse_positions_order => 1,
|
||||
retry_interval_apiauth => 840,
|
||||
retry_interval_getmower => 840,
|
||||
retry_interval_wsreopen => 2,
|
||||
timeout_apiauth => 5,
|
||||
timeout_getmower => 5,
|
||||
timeout_cmd => 10,
|
||||
@ -742,7 +746,6 @@ sub APIAuthResponse {
|
||||
|
||||
}
|
||||
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# GET MOWERS
|
||||
@ -818,7 +821,7 @@ sub getMowerResponseWs {
|
||||
my $iam = "$type $name getMowerResponseWs:";
|
||||
|
||||
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', '') );
|
||||
Log3 $name, 4, "$iam response polling after status-event \$statuscode >$statuscode<, \$err >$err<, \$param->url $param->{url} \n \$data >$data<";
|
||||
|
||||
if( !$err && $statuscode == 200 && $data) {
|
||||
|
||||
@ -848,13 +851,14 @@ sub getMowerResponseWs {
|
||||
for ( $cnt = 0; $cnt < $poslen; $cnt++ ) {
|
||||
|
||||
if ( $hash->{helper}{searchpos}[ 0 ]{longitude} == $result->{data}{attributes}{positions}[ $cnt ]{longitude}
|
||||
&& $hash->{helper}{searchpos}[ 0 ]{latitude} == $result->{data}{attributes}{positions}[ $cnt ]{latitude} ) {
|
||||
&& $hash->{helper}{searchpos}[ 0 ]{latitude} == $result->{data}{attributes}{positions}[ $cnt ]{latitude} || $cnt == $poslen -1) { # if nothing found take all
|
||||
|
||||
if ( $cnt > 0 ) {
|
||||
|
||||
my @ar;
|
||||
push @ar, @{ $result->{data}{attributes}{positions} }[ 0 .. $cnt-1 ];
|
||||
$hash->{helper}{mower}{attributes}{positions} = dclone( \@ar );
|
||||
|
||||
AlignArray( $hash );
|
||||
FW_detailFn_Update ($hash);
|
||||
|
||||
@ -915,7 +919,7 @@ sub 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', '') );
|
||||
Log3 $name, 4, "$iam response \$statuscode >$statuscode<, \$err >$err<, \$param->url $param->{url} \n\$data >$data<";
|
||||
|
||||
if( !$err && $statuscode == 200 && $data) {
|
||||
|
||||
@ -1007,7 +1011,7 @@ sub getMowerResponse {
|
||||
} else {
|
||||
|
||||
readingsSingleUpdate( $hash, 'device_state', "error statuscode $statuscode", 1 );
|
||||
Log3 $name, 1, "$iam \$statuscode [$statuscode]\n\$err [$err],\n \$data [$data] \n\$param->url $param->{url}";
|
||||
Log3 $name, 1, "$iam \$statuscode >$statuscode<, \$err >$err<, \$param->url $param->{url} \n\$data >$data<";
|
||||
|
||||
}
|
||||
|
||||
@ -1563,6 +1567,8 @@ sub AlignArray {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $use_position_polling = $hash->{helper}{use_position_polling};
|
||||
my $reverse_positions_order = $hash->{helper}{reverse_positions_order};
|
||||
my $additional_polling = $hash->{helper}{additional_polling};
|
||||
my $act = $hash->{helper}{mower}{attributes}{mower}{activity};
|
||||
my $actold = $hash->{helper}{mowerold}{attributes}{mower}{activity};
|
||||
my $cnt = @{ $hash->{helper}{mower}{attributes}{positions} };
|
||||
@ -1573,8 +1579,9 @@ sub AlignArray {
|
||||
my @ar = @{ $hash->{helper}{mower}{attributes}{positions} };
|
||||
my $deltaTime = $hash->{helper}{positionsTime} - $hash->{helper}{statusTime};
|
||||
|
||||
# if encounter positions shortly after status event old activity is assigned to positions
|
||||
if ( $cnt > 1 && $deltaTime > 0 && $deltaTime < 0.29 && !$use_position_polling) {
|
||||
# if encounter positions shortly after status event old activity is assigned to positions
|
||||
if ( $cnt > 1 && $deltaTime > 0 && $deltaTime < 0.29 && !$use_position_polling ||
|
||||
$use_position_polling && ( $actold =~ /LEAVING/ && $act eq 'MOWING' || $act =~ /GOING_HOME/ && $actold eq 'MOWING' ) ) {
|
||||
|
||||
map { $_->{act} = $hash->{helper}{$actold}{short} } @ar;
|
||||
|
||||
@ -1586,8 +1593,11 @@ sub AlignArray {
|
||||
|
||||
if ( !$use_position_polling ) {
|
||||
|
||||
@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
|
||||
if ( $reverse_positions_order ) {
|
||||
|
||||
@ar = reverse @ar if ( $cnt > 1 ); # positions seem to be in reversed order
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1618,6 +1628,12 @@ sub AlignArray {
|
||||
|
||||
}
|
||||
|
||||
if ( $hash->{helper}{newcollisions} && $additional_polling && $act =~ /^(MOWING)$/ ) {
|
||||
|
||||
TagWayPointsAsCollision ( $hash, $cnt );
|
||||
|
||||
}
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && $act =~ /^(MOWING)$/ ) {
|
||||
|
||||
$tmp = dclone( \@ar );
|
||||
@ -1758,6 +1774,8 @@ sub ZoneHandling {
|
||||
|
||||
map { $hash->{helper}{mapZones}{$_}{currentDayCntPct} = ( $sumDayCnt ? sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{zoneCnt} / $sumDayCnt * 100 ) : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{currentDayAreaPct} = ( $sumDayArea ? sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{zoneLength} / $sumDayArea * 100 ) : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{currentDayTrack} = $hash->{helper}{mapZones}{$_}{zoneLength};
|
||||
$hash->{helper}{mapZones}{$_}{currentDayTime} = $hash->{helper}{mapZones}{$_}{zoneCnt} * 30;
|
||||
} @zonekeys;
|
||||
|
||||
$hash->{helper}{mapZones}{$hash->{helper}{currentZone}}{currentDayCollisions} += $hash->{helper}{newcollisions};
|
||||
@ -1818,6 +1836,19 @@ sub calcPathLength {
|
||||
return $lsum;
|
||||
}
|
||||
|
||||
#########################
|
||||
sub TagWayPointsAsCollision {
|
||||
my ( $hash, $i ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
for ( my $k = 1; $k < ($i-1); $k++) {
|
||||
|
||||
$hash->{helper}{areapos}[$k]{act} = 'K';
|
||||
|
||||
}
|
||||
$hash->{helper}{areapos}[0]{act} = 'KE';
|
||||
$hash->{helper}{areapos}[$i-1]{act} = 'KS' if ($i>1);
|
||||
}
|
||||
|
||||
#########################
|
||||
sub AreaStatistics {
|
||||
my ( $hash, $i ) = @_;
|
||||
@ -2056,9 +2087,11 @@ sub calculateStatistics {
|
||||
$hash->{helper}{statistics}{currentWeekTrack} += $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{currentWeekArea} += $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentWeekTime} += $hash->{helper}{statistics}{currentDayTime};
|
||||
$hash->{helper}{statistics}{currentWeekCollisions} += $hash->{helper}{statistics}{lastDayCollisions};
|
||||
$hash->{helper}{statistics}{currentDayTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentDayArea} = 0;
|
||||
$hash->{helper}{statistics}{currentDayTime} = 0;
|
||||
$hash->{helper}{statistics}{currentDayCollisions} = 0;
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
@ -2069,9 +2102,15 @@ sub calculateStatistics {
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCnt} += $hash->{helper}{mapZones}{$_}{zoneCnt};
|
||||
$sumCurrentWeekCnt += $hash->{helper}{mapZones}{$_}{currentWeekCnt};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekArea} += $hash->{helper}{mapZones}{$_}{zoneLength};
|
||||
$sumCurrentWeekArea += $hash->{helper}{mapZones}{$_}{currentWeekArea};
|
||||
$sumCurrentWeekArea += ( $hash->{helper}{mapZones}{$_}{currentWeekArea} ? $hash->{helper}{mapZones}{$_}{currentWeekArea} : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{lastDayTrack} = $hash->{helper}{mapZones}{$_}{currentDayTrack};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekTrack} += ( $hash->{helper}{mapZones}{$_}{currentDayTrack} ? $hash->{helper}{mapZones}{$_}{currentDayTrack} : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{lastDayTime} = ( $hash->{helper}{mapZones}{$_}{currentDayTime} ? $hash->{helper}{mapZones}{$_}{currentDayTime} : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekTime} += ( $hash->{helper}{mapZones}{$_}{currentDayTime} ? $hash->{helper}{mapZones}{$_}{currentDayTime} : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{zoneCnt} = 0;
|
||||
$hash->{helper}{mapZones}{$_}{zoneLength} = 0;
|
||||
$hash->{helper}{mapZones}{$_}{currentDayTrack} = 0;
|
||||
$hash->{helper}{mapZones}{$_}{currentDayTime} = 0;
|
||||
} @zonekeys;
|
||||
|
||||
map {
|
||||
@ -2081,6 +2120,11 @@ sub calculateStatistics {
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekAreaPct} = ( $sumCurrentWeekArea ? sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{currentWeekArea} / $sumCurrentWeekArea * 100 ) : '' );
|
||||
$hash->{helper}{mapZones}{$_}{currentDayCntPct} = '';
|
||||
$hash->{helper}{mapZones}{$_}{currentDayAreaPct} = '';
|
||||
if ( $hash->{helper}{additional_polling} ) {
|
||||
$hash->{helper}{mapZones}{$_}{lastDayCollisions} = ( $hash->{helper}{mapZones}{$_}{currentDayCollisions} ? $hash->{helper}{mapZones}{$_}{currentDayCollisions} : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCollisions} += ( $hash->{helper}{mapZones}{$_}{currentDayCollisions} ? $hash->{helper}{mapZones}{$_}{currentDayCollisions} : 0 );
|
||||
$hash->{helper}{mapZones}{$_}{currentDayCollisions} = 0;
|
||||
}
|
||||
} @zonekeys;
|
||||
|
||||
}
|
||||
@ -2090,9 +2134,11 @@ sub calculateStatistics {
|
||||
$hash->{helper}{statistics}{lastWeekTrack} = $hash->{helper}{statistics}{currentWeekTrack};
|
||||
$hash->{helper}{statistics}{lastWeekArea} = $hash->{helper}{statistics}{currentWeekArea};
|
||||
$hash->{helper}{statistics}{lastWeekTime} = $hash->{helper}{statistics}{currentWeekTime};
|
||||
$hash->{helper}{statistics}{lastWeekCollisions} = $hash->{helper}{statistics}{currentWeekCollisions};
|
||||
$hash->{helper}{statistics}{currentWeekTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentWeekArea} = 0;
|
||||
$hash->{helper}{statistics}{currentWeekTime} = 0;
|
||||
$hash->{helper}{statistics}{currentWeekCollisions} = 0;
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
@ -2100,8 +2146,16 @@ sub calculateStatistics {
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekCntPct} = $hash->{helper}{mapZones}{$_}{currentWeekCntPct};
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekAreaPct} = $hash->{helper}{mapZones}{$_}{currentWeekAreaPct};
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekTrack} = $hash->{helper}{mapZones}{$_}{currentWeekTrack};
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekTime} = $hash->{helper}{mapZones}{$_}{currentWeekTime};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCntPct} = '';
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekAreaPct} = '';
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekTrack} = 0;
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekTime} = 0;
|
||||
if ( $hash->{helper}{additional_polling} ) {
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekCollisions} = $hash->{helper}{mapZones}{$_}{currentWeekCollisions};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCollisions} = 0;
|
||||
}
|
||||
} @zonekeys;
|
||||
|
||||
}
|
||||
@ -2125,6 +2179,16 @@ sub listStatisticsData {
|
||||
my ( $hash ) = @_;
|
||||
if ( $::init_done && $hash->{helper}{statistics} ) {
|
||||
|
||||
my %unit =(
|
||||
Track => 'm',
|
||||
Area => 'qm',
|
||||
Time => 's',
|
||||
Collisions => ' ',
|
||||
CntPct => '%',
|
||||
AreaPct => '%'
|
||||
);
|
||||
my @props = qw(Track Area Time Collisions);
|
||||
my @items = qw(currentDay lastDay currentWeek lastWeek);
|
||||
my $additional_polling = $hash->{helper}{additional_polling};
|
||||
my $name = $hash->{NAME};
|
||||
my $cnt = 0;
|
||||
@ -2140,95 +2204,48 @@ sub listStatisticsData {
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{mower}{attributes}{statistics}{<b>totalRunningTime</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{mower}{attributes}{statistics}{totalRunningTime} / 3600 ) . '<sup>1</sup> </td><td> h </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{mower}{attributes}{statistics}{<b>totalSearchingTime</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{mower}{attributes}{statistics}{totalSearchingTime} / 3600 ) . ' </td><td> h </td></tr>';
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentDayTrack</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentDayTrack} ) . ' </td><td> m </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentDayArea</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentDayArea} ) . ' </td><td> qm </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentDayTime</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentDayTime} ) . ' </td><td> s </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentDayCollisions</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentDayCollisions} ) . ' </td><td> </td></tr>' if ( $additional_polling );
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> <b>calculated speed</b>  </td><td> ' . sprintf( "%.2f", $hash->{helper}{statistics}{currentDayTrack} / $hash->{helper}{statistics}{currentDayTime} ) . ' </td><td> m/s </td></tr>' if ( $hash->{helper}{statistics}{currentDayTime} );
|
||||
my $prop = '';
|
||||
for my $item ( @items ) {
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastDayTrack</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastDayTrack} ) . ' </td><td> m </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastDayArea</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastDayArea} ) . ' </td><td> qm </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastDayTime</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastDayTime} ) . ' </td><td> s </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastDayCollisions</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastDayCollisions} ) . ' </td><td> </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> <b>last day calculated speed</b>  </td><td> ' . sprintf( "%.2f", $hash->{helper}{statistics}{lastDayTrack} / $hash->{helper}{statistics}{lastDayTime} ) . ' </td><td> m/s </td></tr>' if ( $hash->{helper}{statistics}{lastDayTime} );
|
||||
for $prop ( @props ) {
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>'. $item . $prop . '</b>}  </td><td> ' . sprintf( "%.0f", ( $hash->{helper}{statistics}{$item.$prop} ? $hash->{helper}{statistics}{$item.$prop} : 0 ) ) . ' </td><td> ' . $unit{$prop} . ' </td></tr>' if ( $item.$prop ne 'currentDayCollision' or $additional_polling );
|
||||
|
||||
}
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> <b>'. $item . ' calculated speed</b>  </td><td> ' . sprintf( "%.2f", $hash->{helper}{statistics}{$item.'Track'} / $hash->{helper}{statistics}{$item.'Time'} ) . ' </td><td> m/s </td></tr>' if ( $hash->{helper}{statistics}{$item.'Time'} );
|
||||
|
||||
}
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentWeekTrack</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentWeekTrack} ) . ' </td><td> m </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentWeekArea</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentWeekArea} ) . ' </td><td> qm </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>currentWeekTime</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{currentWeekTime} ) . ' </td><td> s </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastWeekTrack</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastWeekTrack} ) . ' </td><td> m </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastWeekArea</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastWeekArea} ) . ' </td><td> qm </td></tr>';
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> $hash->{helper}{statistics}{<b>lastWeekTime</b>}  </td><td> ' . sprintf( "%.0f", $hash->{helper}{statistics}{lastWeekTime} ) . ' </td><td> s </td></tr>';
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
my @props = qw(Track CntPct AreaPct);
|
||||
unshift @props, 'Collisions' if ( $additional_polling );
|
||||
|
||||
if ( $additional_polling ) {
|
||||
for my $prop ( @props ) {
|
||||
|
||||
for ( @zonekeys ) {
|
||||
for my $item ( @items ) {
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>currentDayCollisions</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{currentDayCollisions} ? $hash->{helper}{mapZones}{$_}{currentDayCollisions} : '' ) . ' </td><td> </td></tr>';
|
||||
for ( @zonekeys ) {
|
||||
|
||||
if ($prop eq 'Track') {
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ).'"><td> <b> '. $item . ' calculated speed for '. $_ . '</b>  </td><td> ' . sprintf( "%.2f", $hash->{helper}{mapZones}{$_}{$item.'Track'} / $hash->{helper}{mapZones}{$_}{$item.'Time'} ) . ' </td><td> m/s </td></tr>' if ( $hash->{helper}{mapZones}{$_}{$item.'Time'} );
|
||||
|
||||
} else {
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>'. $item . $prop . '</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{$item.$prop} ? $hash->{helper}{mapZones}{$_}{$item.$prop} : '' ) . ' </td><td> ' . $unit{$prop} . ' </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>currentDayCntPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{currentDayCntPct} ? $hash->{helper}{mapZones}{$_}{currentDayCntPct} : '' ) . ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>lastDayCntPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{lastDayCntPct} ? $hash->{helper}{mapZones}{$_}{lastDayCntPct} : '' ) . ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>currentWeekCntPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{currentWeekCntPct} ? $hash->{helper}{mapZones}{$_}{currentWeekCntPct} : '' ) . ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>lastWeekCntPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{lastWeekCntPct} ? $hash->{helper}{mapZones}{$_}{lastWeekCntPct} : '' ). ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>currentDayAreaPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{currentDayAreaPct} ? $hash->{helper}{mapZones}{$_}{currentDayAreaPct} : '' ) . ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>lastDayAreaPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{lastDayAreaPct} ? $hash->{helper}{mapZones}{$_}{lastDayAreaPct} : '' ) . ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>currentWeekAreaPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{currentWeekAreaPct} ? $hash->{helper}{mapZones}{$_}{currentWeekAreaPct} : '' ) . ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
|
||||
$ret .= '<tr class="column '.( $cnt++ % 2 ? 'odd' : 'even' ) . '"><td> $hash->{helper}{mapZones}{' . $_ . '}{<b>lastWeekAreaPct</b>}  </td><td> ' . ( $hash->{helper}{mapZones}{$_}{lastWeekAreaPct} ? $hash->{helper}{mapZones}{$_}{lastWeekAreaPct} : '' ). ' </td><td> % </td></tr>';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$ret .= '</tbody></table>';
|
||||
@ -2495,11 +2512,21 @@ sub wsReopen {
|
||||
RemoveInternalTimer( $hash, \&wsReopen );
|
||||
RemoveInternalTimer( $hash, \&wsKeepAlive );
|
||||
DevIo_CloseDev( $hash ) if ( DevIo_IsOpen( $hash ) );
|
||||
$hash->{DeviceName} = WSDEVICENAME;
|
||||
DevIo_OpenDev( $hash, 0, \&wsInit, \&wsCb );
|
||||
# $hash->{DeviceName} = WSDEVICENAME;
|
||||
# DevIo_OpenDev( $hash, 0, \&wsInit, \&wsCb );
|
||||
InternalTimer( gettimeofday() + $hash->{helper}{retry_interval_wsreopen}, \&wsAsyncDevIo_OpenDev, $hash, 0 );
|
||||
|
||||
}
|
||||
|
||||
#########################
|
||||
sub wsAsyncDevIo_OpenDev {
|
||||
my ( $hash ) = @_;
|
||||
RemoveInternalTimer( $hash, \&wsAsyncDevIo_OpenDev );
|
||||
$hash->{DeviceName} = WSDEVICENAME;
|
||||
$hash->{helper}{retry_interval_wsreopen} = 2;
|
||||
DevIo_OpenDev( $hash, 0, \&wsInit, \&wsCb );
|
||||
}
|
||||
|
||||
#########################
|
||||
sub wsRead {
|
||||
my ($hash) = @_;
|
||||
@ -2510,6 +2537,7 @@ sub wsRead {
|
||||
my $use_position_polling = $hash->{helper}{use_position_polling};
|
||||
my $buf = DevIo_SimpleRead( $hash );
|
||||
return "" if ( !defined( $buf ) );
|
||||
Log3 $name, 4, "$iam received websocket data: >$buf<";
|
||||
|
||||
if ( $buf ) {
|
||||
|
||||
@ -2525,6 +2553,14 @@ sub wsRead {
|
||||
|
||||
$hash->{helper}{wsResult}{other} = dclone( $result );
|
||||
|
||||
if ( $result =~ /^{"ready":false/ ) {
|
||||
|
||||
readingsSingleUpdate( $hash, 'mower_wsEvent', 'not ready', 1);
|
||||
$hash->{helper}{retry_interval_wsreopen} = 420;
|
||||
wsReopen($hash);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( defined( $result->{type} ) && $result->{id} eq $hash->{helper}{mower_id} ) {
|
||||
@ -2551,13 +2587,12 @@ sub wsRead {
|
||||
isErrorThanPrepare( $hash );
|
||||
resetLastErrorIfCorrected( $hash );
|
||||
|
||||
} elsif ( ( $additional_polling < $hash->{helper}{storesum} || $additional_polling && $act eq 'LEAVING' ) && !$hash->{helper}{midnightCycle} ) {
|
||||
} elsif ( ( $additional_polling < $hash->{helper}{storesum} || $additional_polling && $act =~ /^(LEAVING|GOING_HOME)/ ) && !$hash->{helper}{midnightCycle} ) {
|
||||
|
||||
$hash->{helper}{storesum} = 0;
|
||||
# RemoveInternalTimer( $hash, \&getMowerWs );
|
||||
# InternalTimer(gettimeofday() + 2, \&getMowerWs, $hash, 0 );
|
||||
getMowerWs( $hash );
|
||||
Log3 $name, 4, "$iam received websocket data, and polling is on: >$buf<";
|
||||
$hash->{First_Read} = 0;
|
||||
return;
|
||||
|
||||
@ -2577,7 +2612,6 @@ sub wsRead {
|
||||
|
||||
} elsif ( $use_position_polling && $additional_polling ) {
|
||||
|
||||
Log3 $name, 4, "$iam received websocket data, but position polling is on: >$buf<";
|
||||
$hash->{First_Read} = 0;
|
||||
return;
|
||||
|
||||
@ -2607,7 +2641,6 @@ sub wsRead {
|
||||
|
||||
}
|
||||
|
||||
Log3 $name, 4, "$iam received websocket data: >$buf<";
|
||||
$hash->{First_Read} = 0;
|
||||
return;
|
||||
|
||||
@ -2616,6 +2649,7 @@ sub wsRead {
|
||||
#########################
|
||||
sub wsReady {
|
||||
my ($hash ) = @_;
|
||||
RemoveInternalTimer( $hash, \&wsAsyncDevIo_OpenDev);
|
||||
RemoveInternalTimer( $hash, \&wsReopen);
|
||||
RemoveInternalTimer( $hash, \&wsKeepAlive);
|
||||
return DevIo_OpenDev( $hash, 1, \&wsInit, \&wsCb );
|
||||
|
@ -115,6 +115,44 @@ function AutomowerConnectScale( ctx, picx, picy, scalx ) {
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function AutomowerConnectTag( ctx, pos, colorat ) {
|
||||
|
||||
for ( i = 0; i < pos.length ; i+=3 ){
|
||||
|
||||
if ( pos[ i + 2 ] == 'K' ){
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash( [] );
|
||||
ctx.lineWidth=1.5;
|
||||
ctx.strokeStyle = 'white';
|
||||
ctx.fillStyle= 'black';
|
||||
ctx.arc( parseInt( pos[ i ] ), parseInt( pos[ i + 1 ] ), 2, 0, 2 * Math.PI, false );
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
if ( pos[ i + 2 ] == 'KE' ){
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash( [] );
|
||||
ctx.lineWidth=3;
|
||||
ctx.strokeStyle = 'white';
|
||||
ctx.fillStyle= 'black';
|
||||
ctx.arc( parseInt( pos[ i ] ), parseInt( pos[ i + 1 ] ), 4, 0, 2 * Math.PI, false );
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
if ( pos[ i + 2 ] == 'KS' ){
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash( [] );
|
||||
ctx.lineWidth=3;
|
||||
ctx.strokeStyle = 'red';
|
||||
ctx.fillStyle= 'black';
|
||||
ctx.arc( parseInt( pos[ i ] ), parseInt( pos[ i + 1 ] ), 4, 0, 2 * Math.PI, false );
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
function AutomowerConnectIcon( ctx, csx, csy, csrel, type ) {
|
||||
if (parseInt(csx) > 0 && parseInt(csy) > 0) {
|
||||
// draw icon
|
||||
@ -302,6 +340,9 @@ function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, sca
|
||||
"P" : "chargingStationPath",
|
||||
"C" : "chargingStationPath",
|
||||
"M" : "mowingPath",
|
||||
"K" : "mowingPath",
|
||||
"KE" : "mowingPath",
|
||||
"KS" : "mowingPath",
|
||||
"L" : "leavingPath",
|
||||
"G" : "goingHomePath"
|
||||
};
|
||||
@ -355,6 +396,10 @@ function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, sca
|
||||
|
||||
}
|
||||
|
||||
// draw collision tag
|
||||
if ( div.getAttribute( 'data-mowingPathShowCollisions' ) )
|
||||
AutomowerConnectTag( ctx, pos, colorat );
|
||||
|
||||
// draw start
|
||||
if ( div.getAttribute( 'data-mowingPathDisplayStart' ) ) {
|
||||
ctx.beginPath();
|
||||
|
Loading…
x
Reference in New Issue
Block a user