diff --git a/fhem/CHANGED b/fhem/CHANGED index 7fe42fd8c..331abda99 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: 74_AutomowerConnect: attribute controlled automatic syncronizing + the mower time if DST changes - feature: 76_SolarForecast: new attr affectConsForecastLastDays and more features, changes in Flowgraphic - change: 74_XiaomiBTLESens: remove experimental switch diff --git a/fhem/FHEM/74_AutomowerConnect.pm b/fhem/FHEM/74_AutomowerConnect.pm index 042793ce8..4b5f0c07a 100644 --- a/fhem/FHEM/74_AutomowerConnect.pm +++ b/fhem/FHEM/74_AutomowerConnect.pm @@ -67,16 +67,17 @@ sub Initialize() { "mapBackgroundColor " . "mapDesignAttributes:textField-long " . "mapZones:textField-long " . - "showMap:1,0 " . "chargingStationCoordinates " . "chargingStationImagePosition:left,top,right,bottom,center " . - "scaleToMeterXY " . "mowerCuttingWidth " . "mowerPanel:textField-long,85 " . "mowerSchedule:textField-long " . "mowingAreaLimits:textField-long " . "mowingAreaHull:textField-long " . + "mowerAutoSyncTime:1,0 " . "propertyLimits:textField-long " . + "scaleToMeterXY " . + "showMap:1,0 " . "weekdaysToResetWayPoints " . "numberOfWayPointsToDisplay " . "addPollingMinInterval " . @@ -192,8 +193,8 @@ __END__ Starts immediately for <number of minutes>
  • dateTime
    - set <name> dateTime <RTC and DST time corretion / h >
    - Syncronize the mower time. The proposal is for RTC = UTC and DST for CET(MEZ)
  • + set <name> dateTime <timestamp / s>
    + Syncronize the mower time to timestamp. The default (empty Input field) timestamp is for local time of the machine the mower is defined.
  • confirmError
    set <name> confirmError
    @@ -377,6 +378,10 @@ __END__ attr <name> showMap <1,0>
    Shows Map on (1 default) or not (0).
  • +
  • mowerAutoSyncTime
    + attr <name> mowerAutoSyncTime <0,1>
    + Synchronizes mower time if DST changes, on (1) or not (0 default).
  • +
  • chargingStationCoordinates
    attr <name> chargingStationCoordinates <longitude><separator><latitude>
    Longitude and latitude of the charging station. Use WGS84 (GPS) coordinates in decimal degree notation. <separator> is one space character
  • @@ -720,8 +725,9 @@ __END__ Der Zonenname darf keine Leerzeichen beinhalten und muss mindestens einen Buchstaben enthalten.
  • dateTime
    - set <name> dateTime <RTC and DST time corretion / h >
    - Synchronisiert die Zeit im Mäher. Der im Auswahlfeld vorgeschlagene Korrekturwert geht davon aus, dass die RTC auf UTC eingestellt ist und berücksichtigt DST für CET(MEZ).
  • + set <name> dateTime <timestamp / s>
    + Synchronisiert die Zeit im Mäher. Timestamp, ist die Zeit in Sekunden seit 1. Januar 1970, 00:00 Uhr UTC unter Berücksichtigung der Zeitzone und DST. + Der Standardwert (leeres Eingabefeld) verwendet die lokale Zeit des Rechners auf dem der Mäher definiert ist, siehe auch mowerAutoSyncTime
  • confirmError
    set <name> confirmError
    @@ -890,6 +896,10 @@ __END__ attr <name> chargingStationImagePosition <right, bottom, left, top, center>
    Position der Ladestation relativ zu ihren Koordinaten.
  • +
  • mowerAutoSyncTime
    + attr <name> mowerAutoSyncTime <0,1>
    + Synchronisiert die Zeit im Mäher, bei einer Zeitumstellung, ein (1) aus (0 Standard).
  • +
  • mowerCuttingWidth
    attr <name> mowerCuttingWidth <cutting width>
    Schnittbreite in Meter zur Berechnung der gemähten Fläche. default: 0.24
  • diff --git a/fhem/lib/FHEM/Devices/AMConnect/Common.pm b/fhem/lib/FHEM/Devices/AMConnect/Common.pm index 2838c341c..2f647a5b8 100644 --- a/fhem/lib/FHEM/Devices/AMConnect/Common.pm +++ b/fhem/lib/FHEM/Devices/AMConnect/Common.pm @@ -48,6 +48,7 @@ BEGIN { CommandDeleteReading DoTrigger FmtDateTime + fhemTimeGm FW_ME FW_dir FW_wname @@ -199,6 +200,7 @@ hideSchedulerButton="" url => 'https://raw.githubusercontent.com/AndriiHeonia/hull/master/dist/hull.js' }, interval => 840, + isDst => -1, no_position_attr => $noPositionAttr, interval_ws => 7110, interval_ping => 570, @@ -211,7 +213,7 @@ hideSchedulerButton="" retry_interval_wsreopen => 2, timeout_apiauth => 5, timeout_getmower => 5, - timeout_cmd => 10, + timeout_cmd => 15, midnightCycle => 1, client_id => $client_id, grant_type => 'client_credentials', @@ -1170,8 +1172,6 @@ sub Set { my $type = $hash->{TYPE}; my $name = $hash->{NAME}; my $iam = "$type $name Set:"; - my @ti = localtime(); - my $tcorr = ($ti[8] ? '2,1,0' : '1,2,0 '); return "$iam: needs at least one argument" if ( @val < 2 ); return "Unknown argument, $iam is disabled, choose one of none:noArg" if ( IsDisabled( $name ) ); @@ -1355,7 +1355,7 @@ sub Set { } ########## - my $ret = " getNewAccessToken:noArg ParkUntilFurtherNotice:noArg ParkUntilNextSchedule:noArg Pause:noArg Start:selectnumbers,30,30,600,0,lin Park:selectnumbers,30,30,600,0,lin ResumeSchedule:noArg getUpdate:noArg client_secret dateTime:$tcorr "; + my $ret = " getNewAccessToken:noArg ParkUntilFurtherNotice:noArg ParkUntilNextSchedule:noArg Pause:noArg Start:selectnumbers,30,30,600,0,lin Park:selectnumbers,30,30,600,0,lin ResumeSchedule:noArg getUpdate:noArg client_secret dateTime "; $ret .= "mowerScheduleToAttribute:noArg sendScheduleFromAttributeToMower:noArg "; $ret .= "cuttingHeight:1,2,3,4,5,6,7,8,9 " if ( defined $hash->{helper}{mower}{attributes}{settings}{cuttingHeight} ); $ret .= "defaultDesignAttributesToAttribute:noArg mapZonesTemplateToAttribute:noArg chargingStationPositionToAttribute:noArg " if ( $hash->{helper}{mower}{attributes}{capabilities}{position} ); @@ -1398,6 +1398,7 @@ sub CMD { my $iam = "$type $name CMD:"; my $timeout = AttrVal( $name, 'timeoutCMD', $hash->{helper}->{timeout_cmd} ); my $method = 'POST'; + my $ts = TimeLocal(); $hash->{helper}{mower_commandSend} = $cmd[ 0 ] . ( $cmd[ 1 ] ? ' '.$cmd[ 1 ] : '' ) . ( $cmd[ 2 ] ? ' '.$cmd[ 2 ] : '' ); if ( IsDisabled( $name ) ) { @@ -1430,7 +1431,7 @@ my $header = "Accept: application/vnd.api+json\r\nX-Api-Key: ".$client_id."\r\nA elsif ($cmd[0] eq "StartInWorkArea" && !$cmd[2]) { $json = '{"data": {"type":"'.$cmd[0].'","attributes":{"workAreaId":'.$cmd[1].'}}}'; $post = 'actions' } elsif ($cmd[0] eq "headlight") { $json = '{"data": {"type":"settings","attributes":{"'.$cmd[0].'": {"mode": "'.$cmd[1].'"}}}}'; $post = 'settings' } - elsif ($cmd[0] eq "dateTime") { $json = '{"data": {"type":"settings","attributes":{"'.$cmd[0].'": '.int(time + $cmd[1] * 3600).'}}}'; $post = 'settings' } + elsif ($cmd[0] eq "dateTime") { $json = '{"data": {"type":"settings","attributes":{"'.$cmd[0].'": '.( $cmd[1] ? $cmd[1] : $ts ).'}}}'; $post = 'settings';$hash->{helper}{mower_commandSend} .= ( $cmd[1] ? '' : ' '.$ts ) } elsif ($cmd[0] eq "cuttingHeight") { $json = '{"data": {"type":"settings","attributes":{"'.$cmd[0].'": '.$cmd[1].'}}}'; $post = 'settings' } elsif ($cmd[0] eq "stayOutZone") { $json = '{"data": {"type":"stayOutZone","id":"'.$cmd[1].'","attributes":{"enable": '.$cmd[2].'}}}'; $post = 'stayOutZones/' . $cmd[1]; $method = 'PATCH' } elsif ($cmd[0] eq "confirmError") { $json = '{}'; $post = 'errors/confirm' } @@ -2865,10 +2866,40 @@ sub listErrorCodes { } ######################### -# Format mower timestamp assuming mower time is always set to daylight saving time, because it is the mowing period. sub FmtDateTimeGMT { - my $ti = shift // 0; - my $ret = POSIX::strftime( "%F %H:%M:%S", gmtime( $ti ) ); + # Returns a yyyy-mm-dd HH:MM:SS formated string for a UNIX like timestamp for local time (seconds since EPOCH) + my $ret = POSIX::strftime( "%F %H:%M:%S", gmtime( shift // 0 ) ); +} + +######################### +# Calculate time timestamp in seconds regarding RTC time and DST +sub TimeLocal { + # Creates a UNIX like timestamp for local time (seconds since EPOCH) + my @ti = localtime(); + return ceil( fhemTimeGm( $ti[0], $ti[1], $ti[2], $ti[3], $ti[4], $ti[5] ) ); +} + +######################### +sub autoDstSync { + my ( $hash ) = @_; + my @ti = localtime(); + my $isDstOld = $hash->{helper}{isDst}; + if ( $ti[8] ne $isDstOld && ( $ti[2] == 4 || $isDstOld eq -1 ) ) { + + $hash->{helper}{isDst} = $ti[8]; + InternalTimer( gettimeofday() + 7, \&CMDdateTime, $hash, 0 ); + + } + return +} + +######################### +sub CMDdateTime { + my ( $hash ) = @_; + my $name = $hash->{NAME}; + RemoveInternalTimer( $hash, \&CMDdateTime ); + CMD( $hash, 'dateTime' ); + return } ######################### @@ -3141,6 +3172,8 @@ sub wsRead { } + autoDstSync( $hash ) if ( AttrVal( $name, "mowerAutoSyncTime", 0 ) ); + } }