From c62a6585a560e1daf6a2155374baaa5d9bd37f45 Mon Sep 17 00:00:00 2001 From: Ellert Date: Tue, 25 Apr 2023 17:37:26 +0000 Subject: [PATCH] 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 --- fhem/CHANGED | 2 + fhem/FHEM/74_AutomowerConnect.pm | 271 ++++++++++++++++++--- fhem/FHEM/75_AutomowerConnectDevice.pm | 231 ++++++++++++++++-- fhem/lib/FHEM/Devices/AMConnect/Common.pm | 278 +++++++++++++++++----- fhem/www/pgm2/automowerconnect.js | 37 ++- 5 files changed, 682 insertions(+), 137 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 4e6a7856e..a12f91ccc 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -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 reboot diff --git a/fhem/FHEM/74_AutomowerConnect.pm b/fhem/FHEM/74_AutomowerConnect.pm index 197019de7..bbda92b3f 100644 --- a/fhem/FHEM/74_AutomowerConnect.pm +++ b/fhem/FHEM/74_AutomowerConnect.pm @@ -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__ -
  • mapImageCoordinatesToRegister
    attr <name> mapImageCoordinatesToRegister <upper left longitude><space><upper left latitude><line feed><lower right longitude><space><lower right latitude>
    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.
    @@ -986,8 +1086,8 @@ __END__ While in activity PARKED_IN_CS/CHARGING every 42 min a geo data set is generated.
  • weekdaysToResetWayPoints
    - attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456>
    - A combination of weekday numbers when the way point stack will be reset, default 1.
  • + attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]>
    + 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.
  • scaleToMeterXY
    attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude>
    @@ -995,6 +1095,54 @@ __END__ Longitude: (LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)
    Latitude: (LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)
  • +
  • mapZones
    + attr <name> mapZones <valid perl condition to separate Zones>
    + Provide the zones with conditions as JSON-String:
    + The waypoints are accessable by the variables $longitude und $latitude.
    + Zones have have to be separated by conditions in alphabetical order of their names.
    + The last zone is determined by the remaining waypoints.
    + Syntactical example:
    + + '{
    +     "<name_1>" : {
    +       "condition" : "<condition to separate name_1 from other zones>"
    +   },
    +     "<name_2>" : {
    +       "condition" : "<condition to separate name_2 from other zones, except name_1>"
    +   },
    +     "<name_3>" : {
    +       "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"
    +   },
    +     "<name_n-1>" : {
    +       "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"
    +   },
    +     "<name n>" : {
    +       "condition" : "Use 'undef' because the last zone remains."
    +   }
    + }'
    +

    + 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.
    + + '{
    +     "01_oben" : {
    +       "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"
    +   },
    +     "02_unten" : {
    +       "condition" : "undef"
    +   }
    + }'
    +
  • + +
  • mowerActivityToHighLight
    + attr <name> mowerActivityToHighLight <perl condition to determine a path section>
    + A perl condition to highlight a path section by mower activities.
    + The current interval activity is accessible by $act. The last intervall activity is accessible by $actold.
    + LineColor, LineDash and LineWidth are adjustable by the attribut mapDesignAttributes under otherActivityPath...
    + Example: Highlight path when leaving charging station.
    + attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/
    + Example: Highlight path when returning to charging station.
    + attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/
  • +
  • disable
  • disabledForIntervals
  • @@ -1013,6 +1161,7 @@ __END__
  • batteryPercent - battery state of charge in percent
  • mower_activity - current activity "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"
  • mower_commandStatus - Status of the last sent command cleared each status update
  • +
  • mower_currentZone - Zone name with activity MOWING in the last interval and number of way points in parenthesis.
  • mower_errorCode - last error code
  • mower_errorCodeTimestamp - last error code time stamp
  • mower_errorDescription - error description
  • @@ -1234,7 +1383,7 @@ __END__ Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (/\s|\R$/).
    Die Angabe der UTM Koordinaten muss als Dezimalzahl in Meter erfolgen.
    Das Attribut muss nach dem Attribut mapImageCoordinatesToRegister gesetzt werden.
    - Dieses Attribut berechnet die Skalierungsfaktoren. Das Attribut scaleToMeterXY wird entsprechend gesetzt + Dieses Attribut berechnet die Skalierungsfaktoren. Das Attribut scaleToMeterXY wird entsprechend gesetzt.
  • showMap
    attr <name> showMap <>1,0
    @@ -1242,7 +1391,7 @@ __END__
  • chargingStationCoordinates
    attr <name> chargingStationCoordinates <longitude><separator><latitude>
    - Longitude und Latitude der Ladestation als WGS84 (GPS) Koordinaten als Deimalzahl. <separator> ist 1 Leerzeichen
  • + Longitude und Latitude der Ladestation als WGS84 (GPS) Koordinaten als Deimalzahl. <separator> ist 1 Leerzeichen.
  • chargingStationImagePosition
    attr <name> chargingStationImagePosition <right, bottom, left, top, center>
    @@ -1258,7 +1407,7 @@ __END__
  • mowingAreaLimits
    attr <name> mowingAreaLimits <positions list>
    - Liste von Positionen, die den Mähbereich beschreiben. Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (/\s|\R$/).
    Die Liste der Positionen kann aus einer mit Google Earth erzeugten KML-Datei entnommen werden, aber ohne Höhenangaben
  • + Liste von Positionen, die den Mähbereich beschreiben. Format: Zeilenweise Paare von Longitude- u. Latitudewerten getrennt durch 1 Leerzeichen. Die Zeilen werden aufgeteilt durch (/\s|\R$/).
    Die Liste der Positionen kann aus einer mit Google Earth erzeugten KML-Datei entnommen werden, aber ohne Höhenangaben.
  • propertyLimits
    attr <name> propertyLimits <positions list>
    @@ -1266,12 +1415,12 @@ __END__
  • numberOfWayPointsToDisplay
    attr <name> numberOfWayPointsToDisplay <number of way points>
    - 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.
  • weekdaysToResetWayPoints
    - attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456>
    - Eine Kombination von Wochentagnummern an denen der Wegpunktspeicher gelöscht wird, default 1.
  • + attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]>
    + 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.
  • scaleToMeterXY
    attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude>
    @@ -1279,6 +1428,55 @@ __END__ Longitude: (LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)
    Latitude: (LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)
  • +
  • mapZones
    + attr <name> mapZones <JSON string with zone names in alpabetical order and valid perl condition to seperate the zones>
    + Die Wegpunkte stehen über die Perlvariablen $longitude und $latitude zur Verfügung.
    + Die Zonennamen und Bedingungen müssen als JSON-String angegeben werden.
    + Die Zonennamen müssen in alphabetischer Reihenfolge durch Bedingungen abgegrenzt werden.
    + Die letzte Zone ergibt sich aus den übrig gebliebenen Wegpunkten.
    + Syntaxbeispiel:
    + + '{
    +     "<name_1>" : {
    +       "condition" : "<condition to separate name_1 from other zones>"
    +   },
    +     "<name_2>" : {
    +       "condition" : "<condition to separate name_2 from other zones, except name_1>"
    +   },
    +     "<name_3>" : {
    +       "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"
    +   },
    +     "<name_n-1>" : {
    +       "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"
    +   },
    +     "<name n>" : {
    +       "condition" : "Use 'undef' because the last zone remains."
    +   }
    + }'
    +

    + 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. + + '{
    +     "01_oben" : {
    +       "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"
    +   },
    +     "02_unten" : {
    +       "condition" : "undef"
    +   }
    + }'
    +
  • + +
  • mowerActivityToHighLight
    + attr <name> mowerActivityToHighLight <perl condition to determine a path section>
    + Eine Perl Bedingung, die Aktivitäten verknüpft, um einen Pfadabschnitt festzulegen, der hervorgehoben wird.
    + Die Aktivität im aktuellen Interval steht über die Perlvariable $act und die Aktivität im letzten Intervall über $actold zur Verfügung.
    + Die Farbe, Strichstärke und Muster können über das Attribut mapDesignAttributes unter otherActivityPath... eingestellt werden.
    + Beispiel: Pfad beim Verlassen der Ladestation hervorheben.
    + attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/
    + Beispiel: Pfad beim Zurückkehren zur Ladestation hervorheben.
    + attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/
    +
  • +
  • disable
  • disabledForIntervals
  • @@ -1298,6 +1496,7 @@ __END__
  • batteryPercent - Batterieladung in Prozent
  • mower_activity - aktuelle Aktivität "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"
  • mower_commandStatus - Status des letzten uebermittelten Kommandos wird duch Statusupdate zurückgesetzt.
  • +
  • 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.
  • mower_errorCode - last error code
  • mower_errorCodeTimestamp - last error code time stamp
  • mower_errorDescription - error description
  • diff --git a/fhem/FHEM/75_AutomowerConnectDevice.pm b/fhem/FHEM/75_AutomowerConnectDevice.pm index ff026f878..08b1a7fd8 100644 --- a/fhem/FHEM/75_AutomowerConnectDevice.pm +++ b/fhem/FHEM/75_AutomowerConnectDevice.pm @@ -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. -
  • weekdaysToResetWayPoints
    - attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456>
    - A combination of weekday numbers when the way point stack will be reset, default 1.
  • - -
  • weekdaysToResetWayPoints
    - attr <name> weekdaysToResetWayPoints <any combination of weekday numbers from 0123456>
    - Eine Kombination von Wochentagnummern an denen der Wegpunktspeicher gelöscht wird, default 1.
  • +
  • weekdaysToResetWayPoints
    + attr <name> weekdaysToResetWayPoints <any combination of weekday numbers, space or minus [0123456 -]>
    + 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.
  • scaleToMeterXY
    attr <name> scaleToMeterXY <scale factor longitude><seperator><scale factor latitude>
    @@ -752,6 +850,54 @@ __END__ Longitude: (LongitudeMeter_1 - LongitudeMeter_2) / (LongitudeDegree_1 - LongitudeDegree _2)
    Latitude: (LatitudeMeter_1 - LatitudeMeter_2) / (LatitudeDegree_1 - LatitudeDegree _2)
  • +
  • mapZones
    + attr <name> mapZones <valid perl condition to separate Zones>
    + Provide the zones with conditions as JSON-String:
    + The waypoints are accessable by the variables $longitude und $latitude.
    + Zones have have to be separated by conditions in alphabetical order of their names.
    + The last zone is determined by the remaining waypoints.
    + Syntactical example:
    + + '{
    +     "<name_1>" : {
    +       "condition" : "<condition to separate name_1 from other zones>"
    +   },
    +     "<name_2>" : {
    +       "condition" : "<condition to separate name_2 from other zones, except name_1>"
    +   },
    +     "<name_3>" : {
    +       "condition" : "<condition to separate name_3 from other zones, except name_1 and name_2>"
    +   },
    +     "<name_n-1>" : {
    +       "condition" : "<condition to separate name_n-1 from other zones ,except the zones already seperated>"
    +   },
    +     "<name n>" : {
    +       "condition" : "Use undef because the last zone remains."
    +   }
    + }'
    +

    + 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.
    + + '{
    +     "01_oben" : {
    +       "condition" : "$latitude > 52.6484600648553 || $longitude > 9.54799477359984 && $latitude > 52.64839739580418"
    +   },
    +     "02_unten" : {
    +       "condition" : "undef"
    +   }
    + }'
    +
  • + +
  • mowerActivityToHighLight
    + attr <name> mowerActivityToHighLight <perl condition to determine a path section>
    + A perl condition to highlight a path section by mower activities.
    + The current interval activity is accessible by $act. The last intervall activity is accessible by $actold.
    + LineColor, LineDash and LineWidth are adjustable by the attribut mapDesignAttributes under otherActivityPath...
    + Example: Highlight path when leaving charging station.
    + attr <name> mowerActivityToHighLight $act =~ /MOWING|LEAVING/ && $actold =~ /LEAVING|PARKED_IN_CS|CHARGING/
    + Example: Highlight path when returning to charging station.
    + attr <name> mowerActivityToHighLight $act =~ /PARKED_IN_CS|CHARGING|GOING_HOME/ && $actold =~ /MOWING|GOING_HOME/
  • +
  • disable
  • disabledForIntervals
  • @@ -768,6 +914,7 @@ __END__
  • batteryPercent - battery state of charge in percent
  • mower_activity - current activity "UNKNOWN" | "NOT_APPLICABLE" | "MOWING" | "GOING_HOME" | "CHARGING" | "LEAVING" | "PARKED_IN_CS" | "STOPPED_IN_GARDEN"
  • mower_commandStatus - Status of the last sent command cleared each status update
  • +
  • mower_currentZone - Zone name with activity MOWING in the last interval and number of way points in parenthesis.
  • mower_errorCode - last error code
  • mower_errorCodeTimestamp - last error code time stamp
  • mower_errorDescription - error description
  • @@ -916,7 +1063,7 @@ __END__
    - Attributes + Attribute