mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 03:44:52 +00:00
AutomowerConnectFamily: add definiton of zones, possibillity to highlight a path section, some fixes
git-svn-id: https://svn.fhem.de/fhem/trunk@27484 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
e5a7d32f08
commit
fa8620d535
@ -1,5 +1,7 @@
|
||||
# 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.
|
||||
- feature: AutomowerConnectFamily: add definiton of zones, possibillity to
|
||||
highlight path section, some fixes
|
||||
- bugfix: 72_FRITZBOX: Dumper Fehler
|
||||
- bugfix: 72_FRITZBOX: weitere Stabilisierung
|
||||
- feature: 72_FRITZBOX: set <name> reboot
|
||||
|
@ -111,6 +111,8 @@ sub Initialize() {
|
||||
"mapImageZoom " .
|
||||
"mapBackgroundColor " .
|
||||
"mapDesignAttributes:textField-long " .
|
||||
"mapZones:textField-long " .
|
||||
"mowerActivityToHighLight:textField-long " .
|
||||
"showMap:1,0 " .
|
||||
"chargingStationCoordinates " .
|
||||
"chargingStationImagePosition:left,top,right,bottom,center " .
|
||||
@ -364,6 +366,12 @@ sub getMowerResponse {
|
||||
readingsBulkUpdateIfChanged($hash, $pref.'_state', $hash->{helper}{mower}{attributes}{$pref}{state} );
|
||||
readingsBulkUpdateIfChanged($hash, $pref.'_commandStatus', 'cleared' );
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && $hash->{helper}{currentZone} && $hash->{helper}{mapZones}{$hash->{helper}{currentZone}}{curZoneCnt} ) {
|
||||
my $curZon = $hash->{helper}{currentZone};
|
||||
my $curZonCnt = $hash->{helper}{mapZones}{$curZon}{curZoneCnt};
|
||||
readingsBulkUpdateIfChanged($hash, $pref.'_currentZone', $curZon . '(' . $curZonCnt . '/' . $hash->{helper}{newdatasets} . ')' );
|
||||
}
|
||||
|
||||
my $tstamp = $hash->{helper}{mower}{attributes}{$pref}{errorCodeTimestamp};
|
||||
my $timestamp = ::FHEM::Devices::AMConnect::Common::FmtDateTimeGMT($tstamp/1000);
|
||||
readingsBulkUpdateIfChanged($hash, $pref."_errorCodeTimestamp", $tstamp ? $timestamp : '-' );
|
||||
@ -402,37 +410,73 @@ sub getMowerResponse {
|
||||
readingsBulkUpdateIfChanged($hash, $pref."_TimestampOld", FmtDateTime( $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp}/1000 ));
|
||||
readingsEndUpdate($hash, 1);
|
||||
|
||||
my @time = localtime();
|
||||
my $secs = ( $time[2] * 3600 ) + ( $time[1] * 60 ) + $time[0];
|
||||
my $interval = $hash->{helper}->{interval};
|
||||
# do at midnight
|
||||
if ( $secs <= $interval ) {
|
||||
my @time = localtime();
|
||||
my $secs = ( $time[2] * 3600 ) + ( $time[1] * 60 ) + $time[0];
|
||||
my $interval = $hash->{helper}->{interval};
|
||||
# do at midnight
|
||||
if ( $secs <= $interval ) {
|
||||
|
||||
$hash->{helper}{statistics}{lastDayTrack} = $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{lastDayArea} = $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentWeekTrack} += $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{currentWeekArea} += $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentDayTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentDayArea} = 0;
|
||||
# do on mondays
|
||||
if ( $time[6] == 1 ) {
|
||||
$hash->{helper}{statistics}{lastDayTrack} = $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{lastDayArea} = $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentWeekTrack} += $hash->{helper}{statistics}{currentDayTrack};
|
||||
$hash->{helper}{statistics}{currentWeekArea} += $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentDayTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentDayArea} = 0;
|
||||
|
||||
$hash->{helper}{statistics}{lastWeekTrack} = $hash->{helper}{statistics}{currentWeekTrack};
|
||||
$hash->{helper}{statistics}{lastWeekArea} = $hash->{helper}{statistics}{currentWeekArea};
|
||||
$hash->{helper}{statistics}{currentWeekTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentWeekArea} = 0;
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
my $sumLastDayCnt=0;
|
||||
my $sumCurrentWeekCnt=0;
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastDayCnt} = $hash->{helper}{mapZones}{$_}{zoneCnt};
|
||||
$sumLastDayCnt += $hash->{helper}{mapZones}{$_}{lastDayCnt};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCnt} += $hash->{helper}{mapZones}{$_}{lastDayCnt};
|
||||
$sumCurrentWeekCnt += $hash->{helper}{mapZones}{$_}{currentWeekCnt};
|
||||
$hash->{helper}{mapZones}{$_}{zoneCnt} = 0;
|
||||
} @zonekeys;
|
||||
|
||||
}
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastDayCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{lastDayCnt} / $sumLastDayCnt * 100 );
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{currentWeekCnt} / $sumCurrentWeekCnt * 100 );
|
||||
} @zonekeys;
|
||||
|
||||
#clear position arrays
|
||||
if ( AttrVal( $name, 'weekdaysToResetWayPoints', 1 ) =~ $time[6] ) {
|
||||
|
||||
$hash->{helper}{areapos} = [];
|
||||
$hash->{helper}{otherpos} = [];
|
||||
}
|
||||
# do on days
|
||||
if ( $time[6] == 1 ) {
|
||||
|
||||
$hash->{helper}{statistics}{lastWeekTrack} = $hash->{helper}{statistics}{currentWeekTrack};
|
||||
$hash->{helper}{statistics}{lastWeekArea} = $hash->{helper}{statistics}{currentWeekArea};
|
||||
$hash->{helper}{statistics}{currentWeekTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentWeekArea} = 0;
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
my $sumLastWeekCnt=0;
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekCnt} = $hash->{helper}{mapZones}{$_}{currentWeekCnt};
|
||||
$sumLastWeekCnt += $hash->{helper}{mapZones}{$_}{lastWeekCnt};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCnt} = 0;
|
||||
} @zonekeys;
|
||||
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{lastWeekCnt} / $sumLastWeekCnt * 100 );
|
||||
} @zonekeys;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#clear position arrays
|
||||
if ( AttrVal( $name, 'weekdaysToResetWayPoints', 1 ) =~ $time[6] ) {
|
||||
|
||||
$hash->{helper}{areapos} = [];
|
||||
$hash->{helper}{otherpos} = [];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
readingsSingleUpdate($hash, 'state', 'connected', 1 );
|
||||
|
||||
RemoveInternalTimer( $hash, \&APIAuth );
|
||||
@ -486,6 +530,12 @@ sub Set {
|
||||
CommandAttr( $hash, "$name mapDesignAttributes $design" );
|
||||
return undef;
|
||||
|
||||
} elsif ( $setName eq 'mapZonesTemplateToAttribute' ) {
|
||||
|
||||
my $tpl = $hash->{helper}{mapZonesTpl};
|
||||
CommandAttr( $hash, "$name mapZones $tpl" );
|
||||
return undef;
|
||||
|
||||
} elsif ( ReadingsVal( $name, 'state', 'defined' ) !~ /defined|initialized|authentification|authenticated|update/ && $setName eq 'mowerScheduleToAttribute' ) {
|
||||
|
||||
my $calendarjson = eval { JSON::XS->new->pretty(1)->encode ($hash->{helper}{mower}{attributes}{calendar}{tasks}) };
|
||||
@ -542,7 +592,7 @@ sub Set {
|
||||
}
|
||||
my $ret = " getNewAccessToken:noArg ParkUntilFurtherNotice:noArg ParkUntilNextSchedule:noArg Pause:noArg Start:selectnumbers,60,60,600,0,lin Park:selectnumbers,60,60,600,0,lin ResumeSchedule:noArg getUpdate:noArg client_secret ";
|
||||
$ret .= "chargingStationPositionToAttribute:noArg headlight:ALWAYS_OFF,ALWAYS_ON,EVENING_ONLY,EVENING_AND_NIGHT cuttingHeight:1,2,3,4,5,6,7,8,9 mowerScheduleToAttribute:noArg ";
|
||||
$ret .= "sendScheduleFromAttributeToMower:noArg defaultDesignAttributesToAttribute:noArg ";
|
||||
$ret .= "sendScheduleFromAttributeToMower:noArg defaultDesignAttributesToAttribute:noArg mapZonesTemplateToAttribute:noArg ";
|
||||
return "Unknown argument $setName, choose one of".$ret;
|
||||
|
||||
}
|
||||
@ -599,8 +649,8 @@ sub Attr {
|
||||
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
return "$iam $attrName is invalid enter a combination of weekday numbers <0123456>" unless( $attrVal =~ /0|1|2|3|4|5|6/ );
|
||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||
return "$iam $attrName is invalid, enter a combination of weekday numbers, space or - [0123456 -]" unless( $attrVal =~ /0|1|2|3|4|5|6| |-/ );
|
||||
Log3 $name, 4, "$iam $cmd $attrName $attrVal";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
@ -735,7 +785,58 @@ sub Attr {
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName encode error: $@ \n $json";
|
||||
}
|
||||
Log3 $name, 4, "$iam $cmd $attrName array";
|
||||
Log3 $name, 4, "$iam $cmd $attrName mower schedule array";
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif( $attrName eq "mapZones" ) {
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
my $longitude = 10;
|
||||
my $latitude = 52;
|
||||
my $perl = eval { decode_json ($attrVal) };
|
||||
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName decode error: $@ \n $attrVal";
|
||||
}
|
||||
|
||||
for ( keys %{$perl} ) {
|
||||
|
||||
my $cond = eval "($perl->{$_}{condition})";
|
||||
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName syntax error in condition: $@ \n $perl->{$_}{condition}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Log3 $name, 4, "$iam $cmd $attrName";
|
||||
$hash->{helper}{mapZones} = $perl;
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
delete $hash->{helper}{mapZones};
|
||||
delete $hash->{helper}{currentZone};
|
||||
CommandDeleteReading( $hash, "$name mower_currentZone" );
|
||||
Log3 $name, 3, "$iam $cmd $attrName";
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif( $attrName eq "mowerActivityToHighLight" ) {
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
my $act = 'LEAVING';
|
||||
my $actold = 'LEAVING';
|
||||
my $perl = eval "($attrVal)";
|
||||
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName syntax error in condition: $@ \n $attrVal";
|
||||
}
|
||||
Log3 $name, 4, "$iam $cmd $attrName";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
Log3 $name, 3, "$iam $cmd $attrName";
|
||||
|
||||
}
|
||||
}
|
||||
@ -939,7 +1040,6 @@ __END__
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li><a id='AutomowerConnect-attr-mapImageCoordinatesToRegister'>mapImageCoordinatesToRegister</a><br>
|
||||
<code>attr <name> mapImageCoordinatesToRegister <upper left longitude><space><upper left latitude><line feed><lower right longitude><space><lower right latitude></code><br>
|
||||
Upper left and lower right coordinates to register (or to fit to earth) the image. Format: linewise longitude and latitude values separated by 1 space.<br>
|
||||
@ -986,8 +1086,8 @@ __END__
|
||||
While in activity PARKED_IN_CS/CHARGING every 42 min a geo data set is generated.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-weekdaysToResetWayPoints'>weekdaysToResetWayPoints</a><br>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456></code><br>
|
||||
A combination of weekday numbers when the way point stack will be reset, default 1.</li>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]></code><br>
|
||||
A combination of weekday numbers when the way point stack will be reset. No reset for space or minus. The way points are shifted through the dedicated stack. Default 1.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-scaleToMeterXY'>scaleToMeterXY</a><br>
|
||||
<code>attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude></code><br>
|
||||
@ -995,6 +1095,54 @@ __END__
|
||||
Longitude: <code>(LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)</code><br>
|
||||
Latitude: <code>(LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)</code></li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-mapZones'>mapZones</a><br>
|
||||
<code>attr <name> mapZones <valid perl condition to separate Zones></code><br>
|
||||
Provide the zones with conditions as JSON-String:<br>
|
||||
The waypoints are accessable by the variables $longitude und $latitude.<br>
|
||||
Zones have have to be separated by conditions in alphabetical order of their names.<br>
|
||||
The last zone is determined by the remaining waypoints.<br>
|
||||
Syntactical example:<br>
|
||||
<code>
|
||||
'{<br>
|
||||
    "<name_1>" : {<br>
|
||||
      "condition" : "<condition to separate name_1 from other zones>"<br>
|
||||
  },<br>
|
||||
    "<name_2>" : {<br>
|
||||
      "condition" : "<condition to separate name_2 from other zones, except name_1>"<br>
|
||||
  },<br>
|
||||
    "<name_3>" : {<br>
|
||||
      "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"<br>
|
||||
  },<br>
|
||||
    "<name_n-1>" : {<br>
|
||||
      "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"<br>
|
||||
  },<br>
|
||||
    "<name n>" : {<br>
|
||||
      "condition" : "Use 'undef' because the last zone remains."<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code><br>
|
||||
Example with two Zones and virtual lines defined by latitude 52.6484600648553, 52.64839739580418 (horizontal) and longitude 9.54799477359984 (vertikal). all way points above 52.6484600648553 or all way points above 52.64839739580418 and all way points to the right of 9.54799477359984 belong to zone 01_oben. All other way points belong to zone 02_unten.<br>
|
||||
<code>
|
||||
'{<br>
|
||||
    "01_oben" : {<br>
|
||||
      "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"<br>
|
||||
  },<br>
|
||||
    "02_unten" : {<br>
|
||||
      "condition" : "undef"<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code></li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-mowerActivityToHighLight'>mowerActivityToHighLight</a><br>
|
||||
<code>attr <name> mowerActivityToHighLight <perl condition to determine a path section></code><br>
|
||||
A perl condition to highlight a path section by mower activities.<br>
|
||||
The current interval activity is accessible by $act. The last intervall activity is accessible by $actold.<br>
|
||||
LineColor, LineDash and LineWidth are adjustable by the attribut <i>mapDesignAttributes</i> under otherActivityPath...<br>
|
||||
Example: Highlight path when leaving charging station.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/</code><br>
|
||||
Example: Highlight path when returning to charging station.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/</code><br></li>
|
||||
|
||||
<li><a href="disable">disable</a></li>
|
||||
<li><a href="disabledForIntervals">disabledForIntervals</a></li>
|
||||
|
||||
@ -1013,6 +1161,7 @@ __END__
|
||||
<li>batteryPercent - battery state of charge in percent</li>
|
||||
<li>mower_activity - current activity "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"</li>
|
||||
<li>mower_commandStatus - Status of the last sent command cleared each status update</li>
|
||||
<li>mower_currentZone - Zone name with activity MOWING in the last interval and number of way points in parenthesis.</li>
|
||||
<li>mower_errorCode - last error code</li>
|
||||
<li>mower_errorCodeTimestamp - last error code time stamp</li>
|
||||
<li>mower_errorDescription - error description</li>
|
||||
@ -1234,7 +1383,7 @@ __END__
|
||||
Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (<code>/\s|\R$/</code>).<br>
|
||||
Die Angabe der UTM Koordinaten muss als Dezimalzahl in Meter erfolgen.<br>
|
||||
Das Attribut muss nach dem Attribut mapImageCoordinatesToRegister gesetzt werden.<br>
|
||||
Dieses Attribut berechnet die Skalierungsfaktoren. Das Attribut scaleToMeterXY wird entsprechend gesetzt</li>
|
||||
Dieses Attribut berechnet die Skalierungsfaktoren. Das Attribut scaleToMeterXY wird entsprechend gesetzt.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-showMap'>showMap</a><br>
|
||||
<code>attr <name> showMap <><b>1</b>,0</code><br>
|
||||
@ -1242,7 +1391,7 @@ __END__
|
||||
|
||||
<li><a id='AutomowerConnect-attr-chargingStationCoordinates'>chargingStationCoordinates</a><br>
|
||||
<code>attr <name> chargingStationCoordinates <longitude><separator><latitude></code><br>
|
||||
Longitude und Latitude der Ladestation als WGS84 (GPS) Koordinaten als Deimalzahl. <separator> ist 1 Leerzeichen</li>
|
||||
Longitude und Latitude der Ladestation als WGS84 (GPS) Koordinaten als Deimalzahl. <separator> ist 1 Leerzeichen.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-chargingStationImagePosition'>chargingStationImagePosition</a><br>
|
||||
<code>attr <name> chargingStationImagePosition <<b>right</b>, bottom, left, top, center></code><br>
|
||||
@ -1258,7 +1407,7 @@ __END__
|
||||
|
||||
<li><a id='AutomowerConnect-attr-mowingAreaLimits'>mowingAreaLimits</a><br>
|
||||
<code>attr <name> mowingAreaLimits <positions list></code><br>
|
||||
Liste von Positionen, die den Mähbereich beschreiben. Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (<code>/\s|\R$/</code>).<br>Die Liste der Positionen kann aus einer mit Google Earth erzeugten KML-Datei entnommen werden, aber ohne Höhenangaben</li>
|
||||
Liste von Positionen, die den Mähbereich beschreiben. Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (<code>/\s|\R$/</code>).<br>Die Liste der Positionen kann aus einer mit Google Earth erzeugten KML-Datei entnommen werden, aber ohne Höhenangaben.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-propertyLimits'>propertyLimits</a><br>
|
||||
<code>attr <name> propertyLimits <positions list></code><br>
|
||||
@ -1266,12 +1415,12 @@ __END__
|
||||
|
||||
<li><a id='AutomowerConnect-attr-numberOfWayPointsToDisplay'>numberOfWayPointsToDisplay</a><br>
|
||||
<code>attr <name> numberOfWayPointsToDisplay <number of way points></code><br>
|
||||
Legt die Anzahl der gespeicherten und und anzuzeigenden Wegpunkte fest, default 5000
|
||||
Legt die Anzahl der gespeicherten und und anzuzeigenden Wegpunkte fest, default 5000.
|
||||
Während der Aktivität MOWING wird ca. alle 30 s und während PARKED_IN_CS/CHARGING wird alle 42 min ein Geodatensatz erzeugt.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-weekdaysToResetWayPoints'>weekdaysToResetWayPoints</a><br>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456></code><br>
|
||||
Eine Kombination von Wochentagnummern an denen der Wegpunktspeicher gelöscht wird, default 1.</li>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]></code><br>
|
||||
Eine Kombination von Wochentagnummern an denen der Wegpunktspeicher gelöscht wird. Keine Löschung bei Leer- oder Minuszeichen, die Wegpunkte werden durch den zugeteilten Wegpunktspeicher geschoben. Standard 1.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-scaleToMeterXY'>scaleToMeterXY</a><br>
|
||||
<code>attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude></code><br>
|
||||
@ -1279,6 +1428,55 @@ __END__
|
||||
Longitude: <code>(LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)</code><br>
|
||||
Latitude: <code>(LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)</code></li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-mapZones'>mapZones</a><br>
|
||||
<code>attr <name> mapZones <JSON string with zone names in alpabetical order and valid perl condition to seperate the zones></code><br>
|
||||
Die Wegpunkte stehen über die Perlvariablen $longitude und $latitude zur Verfügung.<br>
|
||||
Die Zonennamen und Bedingungen müssen als JSON-String angegeben werden.<br>
|
||||
Die Zonennamen müssen in alphabetischer Reihenfolge durch Bedingungen abgegrenzt werden.<br>
|
||||
Die letzte Zone ergibt sich aus den übrig gebliebenen Wegpunkten.<br>
|
||||
Syntaxbeispiel:<br>
|
||||
<code>
|
||||
'{<br>
|
||||
    "<name_1>" : {<br>
|
||||
      "condition" : "<condition to separate name_1 from other zones>"<br>
|
||||
  },<br>
|
||||
    "<name_2>" : {<br>
|
||||
      "condition" : "<condition to separate name_2 from other zones, except name_1>"<br>
|
||||
  },<br>
|
||||
    "<name_3>" : {<br>
|
||||
      "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"<br>
|
||||
  },<br>
|
||||
    "<name_n-1>" : {<br>
|
||||
      "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"<br>
|
||||
  },<br>
|
||||
    "<name n>" : {<br>
|
||||
      "condition" : "Use 'undef' because the last zone remains."<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code><br>
|
||||
Beispiel mit zwei Zonen und gedachten Linien bestimmt durch die Punkte Latitude 52.6484600648553, 52.64839739580418 (horizontal) und 9.54799477359984 (vertikal). Alle Wegpunkte deren Latitude über einer horizontalen Linie mit der Latitude 52.6484600648553 liegen oder alle Wegpunkte deren Latitude über einer horizontalen Linie mit der Latitude 52.64839739580418 liegen und deren Longitude rechts von einer vertikale Linie mit der Longitude 9.54799477359984 liegen, gehören zur Zone 01_oben. Alle anderen Wegpunkte gehören zur Zone 02_unten.
|
||||
<code>
|
||||
'{<br>
|
||||
    "01_oben" : {<br>
|
||||
      "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"<br>
|
||||
  },<br>
|
||||
    "02_unten" : {<br>
|
||||
      "condition" : "undef"<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code></li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-mowerActivityToHighLight'>mowerActivityToHighLight</a><br>
|
||||
<code>attr <name> mowerActivityToHighLight <perl condition to determine a path section></code><br>
|
||||
Eine Perl Bedingung, die Aktivitäten verknüpft, um einen Pfadabschnitt festzulegen, der hervorgehoben wird.<br>
|
||||
Die Aktivität im aktuellen Interval steht über die Perlvariable $act und die Aktivität im letzten Intervall über $actold zur Verfügung.<br>
|
||||
Die Farbe, Strichstärke und Muster können über das Attribut <i>mapDesignAttributes</i> unter otherActivityPath... eingestellt werden.<br>
|
||||
Beispiel: Pfad beim Verlassen der Ladestation hervorheben.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/</code><br>
|
||||
Beispiel: Pfad beim Zurückkehren zur Ladestation hervorheben.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/</code><br>
|
||||
</li>
|
||||
|
||||
<li><a href="disable">disable</a></li>
|
||||
<li><a href="disabledForIntervals">disabledForIntervals</a></li>
|
||||
|
||||
@ -1298,6 +1496,7 @@ __END__
|
||||
<li>batteryPercent - Batterieladung in Prozent</li>
|
||||
<li>mower_activity - aktuelle Aktivität "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"</li>
|
||||
<li>mower_commandStatus - Status des letzten uebermittelten Kommandos wird duch Statusupdate zurückgesetzt.</li>
|
||||
<li>mower_currentZone - Name der Zone im aktuell abgefragten Intervall, in der der Mäher gemäht hat und Anzahl der Wegpunkte in der Zone in Klammern.</li>
|
||||
<li>mower_errorCode - last error code</li>
|
||||
<li>mower_errorCodeTimestamp - last error code time stamp</li>
|
||||
<li>mower_errorDescription - error description</li>
|
||||
|
@ -105,6 +105,8 @@ sub Initialize() {
|
||||
"mapImageZoom " .
|
||||
"mapBackgroundColor " .
|
||||
"mapDesignAttributes:textField-long " .
|
||||
"mapZones:textField-long " .
|
||||
"mowerActivityToHighLight:textField-long " .
|
||||
"showMap:1,0 " .
|
||||
"chargingStationCoordinates " .
|
||||
"chargingStationImagePosition:left,top,right,bottom,center " .
|
||||
@ -195,6 +197,12 @@ sub Notify {
|
||||
readingsBulkUpdateIfChanged($hash, $pref.'_state', $hash->{helper}{mower}{attributes}{$pref}{state} );
|
||||
readingsBulkUpdateIfChanged($hash, $pref.'_commandStatus', 'cleared' );
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && $hash->{helper}{currentZone} && $hash->{helper}{mapZones}{$hash->{helper}{currentZone}}{curZoneCnt} ) {
|
||||
my $curZon = $hash->{helper}{currentZone};
|
||||
my $curZonCnt = $hash->{helper}{mapZones}{$curZon}{curZoneCnt};
|
||||
readingsBulkUpdateIfChanged($hash, $pref.'_currentZone', $curZon . '(' . $curZonCnt . '/' . $hash->{helper}{newdatasets} . ')' );
|
||||
}
|
||||
|
||||
my $tstamp = $hash->{helper}{mower}{attributes}{$pref}{errorCodeTimestamp};
|
||||
my $timestamp = ::FHEM::Devices::AMConnect::Common::FmtDateTimeGMT($tstamp/1000);
|
||||
readingsBulkUpdateIfChanged($hash, $pref."_errorCodeTimestamp", $tstamp ? $timestamp : '-' );
|
||||
@ -247,7 +255,27 @@ sub Notify {
|
||||
$hash->{helper}{statistics}{currentWeekArea} += $hash->{helper}{statistics}{currentDayArea};
|
||||
$hash->{helper}{statistics}{currentDayTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentDayArea} = 0;
|
||||
# do on mondays
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
my $sumLastDayCnt=0;
|
||||
my $sumCurrentWeekCnt=0;
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastDayCnt} = $hash->{helper}{mapZones}{$_}{zoneCnt};
|
||||
$sumLastDayCnt += $hash->{helper}{mapZones}{$_}{lastDayCnt};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCnt} += $hash->{helper}{mapZones}{$_}{lastDayCnt};
|
||||
$sumCurrentWeekCnt += $hash->{helper}{mapZones}{$_}{currentWeekCnt};
|
||||
$hash->{helper}{mapZones}{$_}{zoneCnt} = 0;
|
||||
} @zonekeys;
|
||||
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastDayCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{lastDayCnt} / $sumLastDayCnt * 100 );
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{currentWeekCnt} / $sumCurrentWeekCnt * 100 );
|
||||
} @zonekeys;
|
||||
|
||||
}
|
||||
# do on days
|
||||
if ( $time[6] == 1 ) {
|
||||
|
||||
$hash->{helper}{statistics}{lastWeekTrack} = $hash->{helper}{statistics}{currentWeekTrack};
|
||||
@ -255,6 +283,22 @@ sub Notify {
|
||||
$hash->{helper}{statistics}{currentWeekTrack} = 0;
|
||||
$hash->{helper}{statistics}{currentWeekArea} = 0;
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
my $sumLastWeekCnt=0;
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekCnt} = $hash->{helper}{mapZones}{$_}{currentWeekCnt};
|
||||
$sumLastWeekCnt += $hash->{helper}{mapZones}{$_}{lastWeekCnt};
|
||||
$hash->{helper}{mapZones}{$_}{currentWeekCnt} = 0;
|
||||
} @zonekeys;
|
||||
|
||||
map {
|
||||
$hash->{helper}{mapZones}{$_}{lastWeekCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{lastWeekCnt} / $sumLastWeekCnt * 100 );
|
||||
} @zonekeys;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#clear position arrays
|
||||
@ -310,6 +354,13 @@ sub Set {
|
||||
CommandAttr( $hash, "$name mapDesignAttributes $design" );
|
||||
return undef;
|
||||
|
||||
################
|
||||
} elsif ( $setName eq 'mapZonesTemplateToAttribute' ) {
|
||||
|
||||
my $tpl = $hash->{helper}{mapZonesTpl};
|
||||
CommandAttr( $hash, "$name mapZones $tpl" );
|
||||
return undef;
|
||||
|
||||
################
|
||||
} elsif ( ReadingsVal( $name, 'state', 'defined' ) !~ /defined|initialized/ && $setName =~ /^(Start|Park|cuttingHeight)$/ ) {
|
||||
if ( $setVal =~ /^(\d+)$/) {
|
||||
@ -337,7 +388,7 @@ sub Set {
|
||||
}
|
||||
my $ret = " ParkUntilFurtherNotice:noArg ParkUntilNextSchedule:noArg Pause:noArg Start:selectnumbers,60,60,600,0,lin Park:selectnumbers,60,60,600,0,lin ResumeSchedule:noArg ";
|
||||
$ret .= "chargingStationPositionToAttribute:noArg headlight:ALWAYS_OFF,ALWAYS_ON,EVENING_ONLY,EVENING_AND_NIGHT cuttingHeight:1,2,3,4,5,6,7,8,9 mowerScheduleToAttribute:noArg ";
|
||||
$ret .= "sendScheduleFromAttributeToMower:noArg defaultDesignAttributesToAttribute:noArg ";
|
||||
$ret .= "sendScheduleFromAttributeToMower:noArg defaultDesignAttributesToAttribute:noArg mapZonesTemplateToAttribute:noArg ";
|
||||
return "Unknown argument $setName, choose one of".$ret;
|
||||
|
||||
}
|
||||
@ -380,7 +431,7 @@ sub Attr {
|
||||
}
|
||||
|
||||
::FHEM::Devices::AMConnect::Common::readMap($hash);
|
||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||
Log3 $name, 4, "$iam $cmd $attrName $attrVal";
|
||||
} else {
|
||||
return "$iam $attrName wrong image type, use webp, png, jpeg or jpg";
|
||||
Log3 $name, 3, "$iam wrong image type, use webp, png, jpeg or jpg";
|
||||
@ -400,8 +451,8 @@ sub Attr {
|
||||
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
return "$iam $attrName is invalid enter a combination of weekday numbers <0123456>" unless( $attrVal =~ /0|1|2|3|4|5|6/ );
|
||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||
return "$iam $attrName is invalid, enter a combination of weekday numbers, space or - [0123456 -]" unless( $attrVal =~ /0|1|2|3|4|5|6| |-/ );
|
||||
Log3 $name, 4, "$iam $cmd $attrName $attrVal";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
@ -419,7 +470,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" ) {
|
||||
|
||||
@ -523,6 +574,57 @@ sub Attr {
|
||||
}
|
||||
Log3 $name, 4, "$iam $cmd $attrName array";
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif( $attrName eq "mapZones" ) {
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
my $longitude = 10;
|
||||
my $latitude = 52;
|
||||
my $perl = eval { decode_json ($attrVal) };
|
||||
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName decode error: $@ \n $attrVal";
|
||||
}
|
||||
|
||||
for ( keys %{$perl} ) {
|
||||
|
||||
my $cond = eval "($perl->{$_}{condition})";
|
||||
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName syntax error in condition: $@ \n $perl->{$_}{condition}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Log3 $name, 4, "$iam $cmd $attrName";
|
||||
$hash->{helper}{mapZones} = $perl;
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
delete $hash->{helper}{mapZones};
|
||||
delete $hash->{helper}{currentZone};
|
||||
CommandDeleteReading( $hash, "$name mower_currentZone" );
|
||||
Log3 $name, 3, "$iam $cmd $attrName";
|
||||
|
||||
}
|
||||
##########
|
||||
} elsif( $attrName eq "mowerActivityToHighLight" ) {
|
||||
if( $cmd eq "set" ) {
|
||||
|
||||
my $act = 'LEAVING';
|
||||
my $actold = 'LEAVING';
|
||||
my $perl = eval "($attrVal)";
|
||||
|
||||
if ($@) {
|
||||
return "$iam $cmd $attrName syntax error in condition: $@ \n $attrVal";
|
||||
}
|
||||
Log3 $name, 4, "$iam $cmd $attrName";
|
||||
|
||||
} elsif( $cmd eq "del" ) {
|
||||
|
||||
Log3 $name, 3, "$iam $cmd $attrName";
|
||||
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
@ -738,13 +840,9 @@ __END__
|
||||
While in activity MOWING every 30 s a geo data set is generated.
|
||||
While in activity PARKED_IN_CS/CHARGING every 42 min a geo data set is generated.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-weekdaysToResetWayPoints'>weekdaysToResetWayPoints</a><br>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456></code><br>
|
||||
A combination of weekday numbers when the way point stack will be reset, default 1.</li>
|
||||
|
||||
<li><a id='AutomowerConnect-attr-weekdaysToResetWayPoints'>weekdaysToResetWayPoints</a><br>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456></code><br>
|
||||
Eine Kombination von Wochentagnummern an denen der Wegpunktspeicher gelöscht wird, default 1.</li>
|
||||
<li><a id='AutomowerConnectDevice-attr-weekdaysToResetWayPoints'>weekdaysToResetWayPoints</a><br>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]></code><br>
|
||||
A combination of weekday numbers when the way point stack will be reset. No reset for space or minus. The way points are shifted through the dedicated stack.Default 1.</li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-scaleToMeterXY'>scaleToMeterXY</a><br>
|
||||
<code>attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude></code><br>
|
||||
@ -752,6 +850,54 @@ __END__
|
||||
Longitude: <code>(LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)</code><br>
|
||||
Latitude: <code>(LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)</code></li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-mapZones'>mapZones</a><br>
|
||||
<code>attr <name> mapZones <valid perl condition to separate Zones></code><br>
|
||||
Provide the zones with conditions as JSON-String:<br>
|
||||
The waypoints are accessable by the variables $longitude und $latitude.<br>
|
||||
Zones have have to be separated by conditions in alphabetical order of their names.<br>
|
||||
The last zone is determined by the remaining waypoints.<br>
|
||||
Syntactical example:<br>
|
||||
<code>
|
||||
'{<br>
|
||||
    "<name_1>" : {<br>
|
||||
      "condition" : "<condition to separate name_1 from other zones>"<br>
|
||||
  },<br>
|
||||
    "<name_2>" : {<br>
|
||||
      "condition" : "<condition to separate name_2 from other zones, except name_1>"<br>
|
||||
  },<br>
|
||||
    "<name_3>" : {<br>
|
||||
      "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"<br>
|
||||
  },<br>
|
||||
    "<name_n-1>" : {<br>
|
||||
      "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"<br>
|
||||
  },<br>
|
||||
    "<name n>" : {<br>
|
||||
      "condition" : "Use undef because the last zone remains."<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code><br>
|
||||
Example with two Zones and virtual lines defined by latitude 52.6484600648553, 52.64839739580418 (horizontal) and longitude 9.54799477359984 (vertikal). all way points above 52.6484600648553 or all way points above 52.64839739580418 and all way points to the right of 9.54799477359984 belong to zone 01_oben. All other way points belong to zone 02_unten.<br>
|
||||
<code>
|
||||
'{<br>
|
||||
    "01_oben" : {<br>
|
||||
      "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"<br>
|
||||
  },<br>
|
||||
    "02_unten" : {<br>
|
||||
      "condition" : "undef"<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code></li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-mowerActivityToHighLight'>mowerActivityToHighLight</a><br>
|
||||
<code>attr <name> mowerActivityToHighLight <perl condition to determine a path section></code><br>
|
||||
A perl condition to highlight a path section by mower activities.<br>
|
||||
The current interval activity is accessible by $act. The last intervall activity is accessible by $actold.<br>
|
||||
LineColor, LineDash and LineWidth are adjustable by the attribut <i>mapDesignAttributes</i> under otherActivityPath...<br>
|
||||
Example: Highlight path when leaving charging station.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/</code><br>
|
||||
Example: Highlight path when returning to charging station.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/</code><br></li>
|
||||
|
||||
<li><a href="disable">disable</a></li>
|
||||
<li><a href="disabledForIntervals">disabledForIntervals</a></li>
|
||||
|
||||
@ -768,6 +914,7 @@ __END__
|
||||
<li>batteryPercent - battery state of charge in percent</li>
|
||||
<li>mower_activity - current activity "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"</li>
|
||||
<li>mower_commandStatus - Status of the last sent command cleared each status update</li>
|
||||
<li>mower_currentZone - Zone name with activity MOWING in the last interval and number of way points in parenthesis.</li>
|
||||
<li>mower_errorCode - last error code</li>
|
||||
<li>mower_errorCodeTimestamp - last error code time stamp</li>
|
||||
<li>mower_errorDescription - error description</li>
|
||||
@ -916,7 +1063,7 @@ __END__
|
||||
</ul>
|
||||
<br>
|
||||
<a id="AutomowerConnectDeviceAttributes"></a>
|
||||
<b>Attributes</b>
|
||||
<b>Attribute</b>
|
||||
<ul>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-mapImagePath'>mapImagePath</a><br>
|
||||
@ -961,7 +1108,7 @@ __END__
|
||||
Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (<code>/\s|\R$/</code>).<br>
|
||||
Die Angabe der UTM Koordinaten muss als Dezimalzahl in Meter erfolgen.<br>
|
||||
Das Attribut muss nach dem Attribut mapImageCoordinatesToRegister gesetzt werden.<br>
|
||||
Dieses Attribut berechnet die Skalierungsfaktoren. Das Attribut scaleToMeterXY wird entsprechend gesetzt</li>
|
||||
Dieses Attribut berechnet die Skalierungsfaktoren. Das Attribut scaleToMeterXY wird entsprechend gesetzt.</li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-showMap'>showMap</a><br>
|
||||
<code>attr <name> showMap <><b>1</b>,0</code><br>
|
||||
@ -996,12 +1143,65 @@ __END__
|
||||
Legt die Anzahl der gespeicherten und anzuzeigenden Wegpunkte fest, default 5000.
|
||||
Während der Aktivität MOWING wird ca. alle 30 s und während PARKED_IN_CS/CHARGING wird alle 42 min ein Geodatensatz erzeugt.</li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-weekdaysToResetWayPoints'>weekdaysToResetWayPoints</a><br>
|
||||
<code>attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]></code><br>
|
||||
Eine Kombination von Wochentagnummern an denen der Wegpunktspeicher gelöscht wird. Keine Löschung bei Leer- oder Minuszeichen, die Wegpunkte werden durch den zugeteilten Wegpunktspeicher geschoben. Standard 1.</li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-scaleToMeterXY'>scaleToMeterXY</a><br>
|
||||
<code>attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude></code><br>
|
||||
Der Skalierfaktor hängt vom Standort ab und muss daher für kurze Strecken berechnet werden. <seperator> ist 1 Leerzeichen.<br>
|
||||
Longitude: <code>(LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)</code><br>
|
||||
Latitude: <code>(LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)</code></li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-mapZones'>mapZones</a><br>
|
||||
<code>attr <name> mapZones <JSON string with zone names in alpabetical order and valid perl condition to seperate the zones></code><br>
|
||||
Die Wegpunkte stehen über die Perlvariablen $longitude und $latitude zur Verfügung.<br>
|
||||
Die Zonennamen und Bedingungen müssen als JSON-String angegeben werden.<br>
|
||||
Die Zonennamen müssen in alphabetischer Reihenfolge durch Bedingungen abgegrenzt werden.<br>
|
||||
Die letzte Zone ergibt sich aus den übrig gebliebenen Wegpunkten.<br>
|
||||
Syntaxbeispiel:<br>
|
||||
<code>
|
||||
'{<br>
|
||||
    "<name_1>" : {<br>
|
||||
      "condition" : "<condition to separate name_1 from other zones>"<br>
|
||||
  },<br>
|
||||
    "<name_2>" : {<br>
|
||||
      "condition" : "<condition to separate name_2 from other zones, except name_1>"<br>
|
||||
  },<br>
|
||||
    "<name_3>" : {<br>
|
||||
      "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"<br>
|
||||
  },<br>
|
||||
    "<name_n-1>" : {<br>
|
||||
      "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"<br>
|
||||
  },<br>
|
||||
    "<name n>" : {<br>
|
||||
      "condition" : "Use undef because the last zone remains."<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code><br>
|
||||
Beispiel mit zwei Zonen und gedachten Linien bestimmt durch die Punkte Latitude 52.6484600648553, 52.64839739580418 (horizontal) und 9.54799477359984 (vertikal). Alle Wegpunkte deren Latitude über einer horizontalen Linie mit der Latitude 52.6484600648553 liegen oder alle Wegpunkte deren Latitude über einer horizontalen Linie mit der Latitude 52.64839739580418 liegen und deren Longitude rechts von einer vertikale Linie mit der Longitude 9.54799477359984 liegen, gehören zur Zone 01_oben Alle anderen Wegpunkte gehören zur Zone 02_unten.
|
||||
<code>
|
||||
'{<br>
|
||||
    "01_oben" : {<br>
|
||||
      "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"<br>
|
||||
  },<br>
|
||||
    "02_unten" : {<br>
|
||||
      "condition" : "undef"<br>
|
||||
  }<br>
|
||||
}'<br>
|
||||
</code></li>
|
||||
|
||||
<li><a id='AutomowerConnectDevice-attr-mowerActivityToHighLight'>mowerActivityToHighLight</a><br>
|
||||
<code>attr <name> mowerActivityToHighLight <perl condition to determine a path section></code><br>
|
||||
Eine Perl Bedingung, die Aktivitäten verknüpft, um einen Pfadabschnitt festzulegen, der hervorgehoben wird.<br>
|
||||
Die Aktivität im aktuellen Interval steht über die Perlvariable $act und die Aktivität im letzten Intervall über $actold zur Verfügung.<br>
|
||||
Die Farbe, Strichstärke und Muster können über das Attribut <i>mapDesignAttributes</i> unter otherActivityPath... eingestellt werden.<br>
|
||||
Beispiel: Pfad beim Verlassen der Ladestation hervorheben.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/</code><br>
|
||||
Beispiel: Pfad beim Zurückkehren zur Ladestation hervorheben.<br>
|
||||
<code>attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/</code><br>
|
||||
</li>
|
||||
|
||||
<li><a href="disable">disable</a></li>
|
||||
<li><a href="disabledForIntervals">disabledForIntervals</a></li>
|
||||
|
||||
@ -1019,6 +1219,7 @@ __END__
|
||||
<li>batteryPercent - Batterieladung in Prozent</li>
|
||||
<li>mower_activity - aktuelle Aktivität "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"</li>
|
||||
<li>mower_commandStatus - Status des letzten uebermittelten Kommandos wird duch Statusupdate zurückgesetzt.</li>
|
||||
<li>mower_currentZone - Name der Zone im aktuell abgefragten Intervall, in der der Mäher gemäht hat und Anzahl der Wegpunkte in der Zone in Klammern.</li>
|
||||
<li>mower_errorCode - last error code</li>
|
||||
<li>mower_errorCodeTimestamp - last error code time stamp</li>
|
||||
<li>mower_errorDescription - error description</li>
|
||||
|
@ -137,14 +137,33 @@ errorPathLineDash=""
|
||||
errorPathLineWidth="2"
|
||||
chargingStationPathLineColor="#999999"
|
||||
chargingStationPathLineDash="6,2"
|
||||
chargingStationPathLineWidth="1"
|
||||
chargingStationPathLineWidth="3"
|
||||
otherActivityPathLineColor="#33cc33"
|
||||
otherActivityPathLineDash="6,2"
|
||||
otherActivityPathLineWidth="1"
|
||||
otherActivityPathLineWidth="2"
|
||||
mowingPathDisplayStart=""
|
||||
mowingPathLineColor="#ff0000"
|
||||
mowingPathLineDash="6,2"
|
||||
mowingPathLineWidth="1"';
|
||||
|
||||
my $mapZonesTpl = '{
|
||||
"A_Zone_1" : {
|
||||
"condition" : "<condition to separate Zone_1 from other zones>"
|
||||
},
|
||||
"B_Zone_2" : {
|
||||
"condition" : "<condition to separate Zone_2 from other zones, except myZone_1>"
|
||||
},
|
||||
"C_Zone_3" : {
|
||||
"condition" : "<condition to separate Zone_3 from other zones, except myZone_1 and myZone_2>"
|
||||
},
|
||||
"D_Zone_x" : {
|
||||
"condition" : "<condition to separate Zone_x from other zones ,except the zones already seperated>"
|
||||
},
|
||||
"E_LastZone" : {
|
||||
"condition" : "Use undef because the last zone remains."
|
||||
}
|
||||
}';
|
||||
|
||||
|
||||
%$hash = (%$hash,
|
||||
helper => {
|
||||
@ -163,6 +182,7 @@ mowingPathLineWidth="1"';
|
||||
imageHeight => 650,
|
||||
imageWidthHeight => '350 650',
|
||||
mapdesign => $mapAttr,
|
||||
mapZonesTpl => $mapZonesTpl,
|
||||
posMinMax => "-180 90\n180 -90",
|
||||
newdatasets => 0,
|
||||
MAP_PATH => '',
|
||||
@ -185,7 +205,7 @@ mowingPathLineWidth="1"';
|
||||
},
|
||||
UNKNOWN => {
|
||||
arrayName => 'otherpos',
|
||||
maxLength => 50,
|
||||
maxLength => 100,
|
||||
cnt => 0,
|
||||
callFn => ''
|
||||
},
|
||||
@ -661,73 +681,92 @@ sub CMDResponse {
|
||||
sub AlignArray {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $activity = $hash->{helper}{mower}{attributes}{mower}{activity};
|
||||
my $arrayName = $hash->{helper}{$activity}{arrayName};
|
||||
my $act = $hash->{helper}{mower}{attributes}{mower}{activity};
|
||||
my $actold = $hash->{helper}{mowerold}{attributes}{mower}{activity};
|
||||
my $searchlen = 2;
|
||||
my $i = 0;
|
||||
my $cnt = 0;
|
||||
my $tmp = [];
|
||||
|
||||
if ( isGoodActivity( $hash ) ) {
|
||||
my $poslen = @{ $hash->{helper}{mower}{attributes}{positions} };
|
||||
my @searchposlon = ( $hash->{helper}{searchpos}[0]{longitude}, $hash->{helper}{searchpos}[1]{longitude} );
|
||||
my @searchposlat = ( $hash->{helper}{searchpos}[0]{latitude}, $hash->{helper}{searchpos}[1]{latitude} );
|
||||
|
||||
my $poslen = @{ $hash->{helper}{mower}{attributes}{positions} };
|
||||
my @searchposlon = ( $hash->{helper}{searchpos}[0]{longitude}, $hash->{helper}{searchpos}[1]{longitude} );
|
||||
my @searchposlat = ( $hash->{helper}{searchpos}[0]{latitude}, $hash->{helper}{searchpos}[1]{latitude} );
|
||||
my $maxLength = $hash->{helper}{$activity}{maxLength};
|
||||
for ( $i = 0; $i < $poslen-2; $i++ ) { # -2 due to 2 alignment data sets at the end
|
||||
if ( $searchposlon[ 0 ] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{longitude}
|
||||
&& $searchposlat[ 0 ] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{latitude}
|
||||
&& $searchposlon[ 1 ] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{longitude}
|
||||
&& $searchposlat[ 1 ] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{latitude} ) {
|
||||
for ( $cnt = 0; $cnt < $poslen-1; $cnt++ ) { # <-1 due to 2 alignment data sets at the end
|
||||
|
||||
if ( $i > 0 ) {
|
||||
my @ar = @{ $hash->{helper}{mower}{attributes}{positions} }[ 0 .. $i-1 ];
|
||||
$tmp = dclone( \@ar );
|
||||
|
||||
if ( $i && @{ $hash->{helper}{$arrayName} } ) {
|
||||
if ( $searchposlon[ 0 ] == $hash->{helper}{mower}{attributes}{positions}[ $cnt ]{longitude}
|
||||
&& $searchposlat[ 0 ] == $hash->{helper}{mower}{attributes}{positions}[ $cnt ]{latitude}
|
||||
&& $searchposlon[ 1 ] == $hash->{helper}{mower}{attributes}{positions}[ $cnt+1 ]{longitude}
|
||||
&& $searchposlat[ 1 ] == $hash->{helper}{mower}{attributes}{positions}[ $cnt+1 ]{latitude} ) {
|
||||
|
||||
unshift ( @{ $hash->{helper}{$arrayName} }, @$tmp );
|
||||
if ( $cnt > 0 ) {
|
||||
|
||||
} elsif ( $i ) {
|
||||
my @ar = @{ $hash->{helper}{mower}{attributes}{positions} }[ 0 .. $cnt-1 ];
|
||||
$tmp = dclone( \@ar );
|
||||
|
||||
$hash->{helper}{$arrayName} = $tmp;
|
||||
if ( @{ $hash->{helper}{areapos} } ) {
|
||||
|
||||
}
|
||||
|
||||
while ( @{ $hash->{helper}{$arrayName} } > $maxLength ) {
|
||||
|
||||
pop ( @{ $hash->{helper}{$arrayName}} ); # reduce to max allowed length
|
||||
|
||||
}
|
||||
|
||||
posMinMax( $hash, $tmp );
|
||||
#callFn if present
|
||||
if ( $hash->{helper}{$activity}{callFn} ) {
|
||||
|
||||
$hash->{helper}{$activity}{cnt} = $i;
|
||||
no strict "refs";
|
||||
&{ $hash->{helper}{$activity}{callFn} }( $hash );
|
||||
use strict "refs";
|
||||
|
||||
}
|
||||
unshift ( @{ $hash->{helper}{areapos} }, @$tmp );
|
||||
|
||||
} else {
|
||||
|
||||
$hash->{helper}{$activity}{cnt} = 0;
|
||||
$hash->{helper}{areapos} = $tmp;
|
||||
|
||||
}
|
||||
|
||||
last;
|
||||
while ( @{ $hash->{helper}{areapos} } > $hash->{helper}{MOWING}{maxLength} ) {
|
||||
|
||||
pop ( @{ $hash->{helper}{areapos}} ); # reduce to max allowed length
|
||||
|
||||
}
|
||||
|
||||
posMinMax( $hash, $tmp );
|
||||
|
||||
if ( $act =~ /^(MOWING)$/ && $actold =~ /^(MOWING|LEAVING|PARKED_IN_CS|CHARGING)$/ ) {
|
||||
|
||||
AreaStatistics ( $hash, $tmp, $cnt );
|
||||
|
||||
}
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && $act =~ /^(MOWING)$/ && $actold =~ /^(MOWING|LEAVING|PARKED_IN_CS|CHARGING)$/ ) {
|
||||
|
||||
$tmp = dclone( \@ar );
|
||||
ZoneHandling ( $hash, $tmp, $cnt );
|
||||
|
||||
}
|
||||
|
||||
if ( $act =~ /^(CHARGING|PARKED_IN_CS)$/ && $actold =~ /^(PARKED_IN_CS|CHARGING)$/ ) {
|
||||
|
||||
$tmp = dclone( \@ar );
|
||||
ChargingStationPosition ( $hash, $tmp, $cnt );
|
||||
|
||||
}
|
||||
|
||||
my $val = AttrVal($name, 'mowerActivityToHighLight', 0);
|
||||
|
||||
if ( $val && eval( "$val" ) ) {
|
||||
|
||||
$tmp = dclone( \@ar );
|
||||
HighlightPath ( $hash, $tmp, $cnt );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$cnt = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
last;
|
||||
|
||||
isErrorThanPrepare( $hash, $tmp );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
isErrorThanPrepare( $hash, $tmp );
|
||||
|
||||
resetLastErrorIfCorrected($hash);
|
||||
$hash->{helper}{newdatasets} = $i;
|
||||
|
||||
$hash->{helper}{newdatasets} = $cnt;
|
||||
$hash->{helper}{searchpos} = [ dclone( $hash->{helper}{mower}{attributes}{positions}[0] ), dclone( $hash->{helper}{mower}{attributes}{positions}[1] ) ];
|
||||
return undef;
|
||||
|
||||
@ -787,27 +826,84 @@ sub resetLastErrorIfCorrected {
|
||||
|
||||
}
|
||||
#########################
|
||||
sub isGoodActivity {
|
||||
sub ZoneHandling {
|
||||
my ( $hash, $poshash, $cnt ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $zone = '';
|
||||
my $nextzone = '';
|
||||
my @pos = @$poshash;
|
||||
my $longitude = 0;
|
||||
my $latitude = 0;
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
my $i = 0;
|
||||
my $k = 0;
|
||||
|
||||
my ( $hash ) = @_;
|
||||
my $act = $hash->{helper}{mower}{attributes}{mower}{activity};
|
||||
my $actold = $hash->{helper}{mowerold}{attributes}{mower}{activity};
|
||||
|
||||
my $ret = $hash->{helper}{$act}{arrayName} && (
|
||||
$act eq $actold
|
||||
|| $act =~ /^(MOWING)$/ && $actold =~ /^(LEAVING|PARKED_IN_CS|CHARGING)$/
|
||||
# || $act =~ /^(GOING_HOME)$/ && $actold =~ /^(MOWING)$/
|
||||
|| $act =~ /^(CHARGING|PARKED_IN_CS)$/ && $actold =~ /^(PARKED_IN_CS|CHARGING)$/
|
||||
|| $act =~ /^(NOT_APPLICABLE)$/ && $actold =~ /^(UNKNOWN|NOT_APPLICABLE|MOWING|GOING_HOME|CHARGING|LEAVING|PARKED_IN_CS|STOPPED_IN_GARDEN)$/);
|
||||
return $ret;
|
||||
map{ $hash->{helper}{mapZones}{$_}{curZoneCnt} = 0 } @zonekeys;
|
||||
|
||||
for ( $i = 0; $i < $cnt; $i++){
|
||||
|
||||
$longitude = $pos[$i]{longitude};
|
||||
$latitude = $pos[$i]{latitude};
|
||||
|
||||
for ( $k = 0; $k < @zonekeys-1; $k++){
|
||||
|
||||
if ( eval ("$hash->{helper}{mapZones}{$zonekeys[$k]}{condition}") ) {
|
||||
|
||||
if ( $hash->{helper}{mapZones}{$zonekeys[$k]}{curZoneCnt} == $i) { # find current zone and count consecutive way points
|
||||
|
||||
$hash->{helper}{mapZones}{$zonekeys[$k]}{curZoneCnt}++;
|
||||
$hash->{helper}{currentZone} = $zonekeys[$k];
|
||||
|
||||
}
|
||||
|
||||
$hash->{helper}{mapZones}{$zonekeys[$k]}{zoneCnt}++;
|
||||
|
||||
last;
|
||||
|
||||
} elsif ( $k == @zonekeys-2 ) { # last zone
|
||||
|
||||
if ( $hash->{helper}{mapZones}{$zonekeys[$k+1]}{curZoneCnt} == $i) { # find current zone and count consecutive way points
|
||||
|
||||
$hash->{helper}{mapZones}{$zonekeys[$k+1]}{curZoneCnt}++;
|
||||
$hash->{helper}{currentZone} = $zonekeys[$k+1];
|
||||
|
||||
}
|
||||
|
||||
$hash->{helper}{mapZones}{$zonekeys[$k+1]}{zoneCnt}++;
|
||||
|
||||
}
|
||||
|
||||
my $sumDayCnt=0;
|
||||
map { $sumDayCnt += $hash->{helper}{mapZones}{$_}{zoneCnt} } @zonekeys;
|
||||
map { $hash->{helper}{mapZones}{$_}{currentDayCntPct} = sprintf( "%.0f", $hash->{helper}{mapZones}{$_}{zoneCnt} / $sumDayCnt * 100 ) } @zonekeys;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#########################
|
||||
sub ChargingStationPosition {
|
||||
my ($hash) = @_;
|
||||
my ( $hash, $poshash, $cnt ) = @_;
|
||||
if ( $cnt && @{ $hash->{helper}{cspos} } ) {
|
||||
|
||||
unshift ( @{ $hash->{helper}{cspos} }, @$poshash );
|
||||
|
||||
} elsif ( $cnt ) {
|
||||
|
||||
$hash->{helper}{cspos} = $poshash;
|
||||
|
||||
}
|
||||
|
||||
while ( @{ $hash->{helper}{cspos} } > $hash->{helper}{PARKED_IN_CS}{maxLength} ) {
|
||||
|
||||
pop ( @{ $hash->{helper}{cspos}} ); # reduce to max allowed length
|
||||
|
||||
}
|
||||
my $n = @{$hash->{helper}{cspos}};
|
||||
if ( $n > 0 ) {
|
||||
|
||||
my $xm = 0;
|
||||
map { $xm += $_->{longitude} } @{$hash->{helper}{cspos}};
|
||||
$xm = $xm/$n;
|
||||
@ -816,16 +912,38 @@ sub ChargingStationPosition {
|
||||
$ym = $ym/$n;
|
||||
$hash->{helper}{chargingStation}{longitude} = sprintf("%.8f",$xm);
|
||||
$hash->{helper}{chargingStation}{latitude} = sprintf("%.8f",$ym);
|
||||
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#########################
|
||||
sub HighlightPath {
|
||||
my ( $hash, $poshash, $cnt ) = @_;
|
||||
if ( $cnt && @{ $hash->{helper}{otherpos} } ) {
|
||||
|
||||
unshift ( @{ $hash->{helper}{otherpos} }, @$poshash );
|
||||
|
||||
} elsif ( $cnt ) {
|
||||
|
||||
$hash->{helper}{otherpos} = $poshash;
|
||||
|
||||
}
|
||||
|
||||
while ( @{ $hash->{helper}{otherpos} } > $hash->{helper}{UNKNOWN}{maxLength} ) {
|
||||
|
||||
pop ( @{ $hash->{helper}{otherpos}} ); # reduce to max allowed length
|
||||
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
#########################
|
||||
sub AreaStatistics {
|
||||
my ($hash) = @_;
|
||||
my ( $hash, $poshash, $i ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $activity = 'MOWING';
|
||||
my $i = $hash->{helper}{$activity}{cnt};
|
||||
my $k = 0;
|
||||
my @xyarr = @{$hash->{helper}{areapos}};# areapos
|
||||
my $n = scalar @xyarr;
|
||||
@ -975,6 +1093,40 @@ sub listStatisticsData {
|
||||
$cnt++;$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>';
|
||||
$cnt++;$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>';
|
||||
|
||||
if ( AttrVal($name, 'mapZones', 0) && defined( $hash->{helper}{mapZones} ) ) {
|
||||
|
||||
my @zonekeys = sort (keys %{$hash->{helper}{mapZones}});
|
||||
|
||||
for ( @zonekeys ) {
|
||||
|
||||
$cnt++;
|
||||
$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 ) {
|
||||
|
||||
$cnt++;
|
||||
$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 ) {
|
||||
|
||||
$cnt++;
|
||||
$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 ) {
|
||||
|
||||
$cnt++;
|
||||
$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>';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$ret .= '</tbody></table>';
|
||||
$ret .= '<p><sup>1</sup> totalRunningTime = totalCuttingTime + totalSearchingTime';
|
||||
$ret .= '</html>';
|
||||
@ -1088,7 +1240,7 @@ sub listInternalData {
|
||||
$ret .= '<tr class="col_header"><td> Used For Action </td><td> Stack Name </td><td> Current Size </td><td> Max Size </td></tr>';
|
||||
$ret .= '<tr class="column odd"><td>PARKED_IN_CS, CHARGING </td><td> cspos </td><td> ' . $csnr . ' </td><td> ' . $csnrmax . ' </td></tr>';
|
||||
$ret .= '<tr class="column even"><td>MOWING </td><td> areapos </td><td> ' . $arnr . ' </td><td> ' . $arnrmax . ' </td></tr>';
|
||||
$ret .= '<tr class="column odd"><td>UNKNOWN, NOT_APPLICABLE, LEAVING,<br>GOING_HOME, STOPPED_IN_GARDEN </td>
|
||||
$ret .= '<tr class="column odd"><td>User defined activities </td>
|
||||
<td style="vertical-align:middle;" > otherpos </td><td style="vertical-align:middle;" > ' . $ornr . ' </td>
|
||||
<td style="vertical-align:middle;" > ' . $ornrmax . ' </td></tr>';
|
||||
$ret .= '<tr class="column even"><td>NOT_APPLICABLE with error time stamp </td><td> lasterror/positions </td><td> ' . $ernr . ' </td><td> - </td></tr>';
|
||||
|
@ -168,7 +168,7 @@ function AutomowerConnectDrawPath ( ctx, div, pos, type ) {
|
||||
ctx.setLineDash( div.getAttribute( 'data-'+ type + 'LineDash' ).split(",") );
|
||||
|
||||
ctx.moveTo(parseInt(pos[0]),parseInt(pos[1]));
|
||||
for (var i=2;i<pos.length-1;i+=2){
|
||||
for (var i=2;i<pos.length;i+=2){
|
||||
ctx.lineTo(parseInt(pos[i]),parseInt(pos[i+1]));
|
||||
}
|
||||
ctx.stroke();
|
||||
@ -196,36 +196,27 @@ function AutomowerConnectUpdateDetail (dev, type, imgsrc, picx, picy, csx, csy,
|
||||
AutomowerConnectScale( ctx, picx, picy, scalx );
|
||||
// draw charging station path
|
||||
AutomowerConnectDrawPath ( ctx, div, posc, 'chargingStationPath' );
|
||||
if ( pos.length > 2 ) {
|
||||
// draw mowing path
|
||||
AutomowerConnectDrawPath ( ctx, div, pos, 'mowingPath' );
|
||||
// draw path for other activity
|
||||
if ( poso.length > 1 ) AutomowerConnectDrawPath ( ctx, div, poso, 'otherActivityPath' );
|
||||
|
||||
if ( pos.length > 4 ) {
|
||||
// draw mowing path
|
||||
var mowpos = pos.slice(2);
|
||||
AutomowerConnectDrawPath ( ctx, div, mowpos, 'mowingPath' );
|
||||
|
||||
// draw start
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash([]);
|
||||
ctx.lineWidth=3;
|
||||
ctx.strokeStyle = 'white';
|
||||
ctx.fillStyle= 'black';
|
||||
ctx.arc(parseInt(pos[pos.length-2]), parseInt(pos[pos.length-1]), 4, 0, 2 * Math.PI, false);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
if ( div.getAttribute( 'data-mowingPathDisplayStart' ) ) {
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash([]);
|
||||
ctx.lineWidth=3;
|
||||
ctx.strokeStyle = 'white';
|
||||
ctx.fillStyle= 'black';
|
||||
ctx.arc(parseInt(pos[pos.length-2]), parseInt(pos[pos.length-1]), 4, 0, 2 * Math.PI, false);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
// draw mower icon
|
||||
AutomowerConnectIcon( ctx, pos[0], pos[1], 'bottom', 'M' );
|
||||
|
||||
//draw last line
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth=1;
|
||||
ctx.setLineDash([6, 2]);
|
||||
ctx.moveTo(parseInt(pos[0]),parseInt(pos[1]));
|
||||
ctx.lineTo(parseInt(pos[2]),parseInt(pos[3]));
|
||||
ctx.strokeStyle = '#ff0000';
|
||||
ctx.stroke();
|
||||
|
||||
}
|
||||
|
||||
// draw charging station
|
||||
|
Loading…
x
Reference in New Issue
Block a user