diff --git a/73_GardenaSmartBridge.pm b/73_GardenaSmartBridge.pm index d88f43f..dc2c811 100644 --- a/73_GardenaSmartBridge.pm +++ b/73_GardenaSmartBridge.pm @@ -2,7 +2,7 @@ # # Developed with Kate # -# (c) 2017 Copyright: Marko Oldenburg (leongaultier at gmail dot com) +# (c) 2017-2018 Copyright: Marko Oldenburg (leongaultier at gmail dot com) # All rights reserved # # Special thanks goes to comitters: @@ -68,7 +68,7 @@ eval "use JSON;1" or $missingModul .= "JSON "; eval "use IO::Socket::SSL;1" or $missingModul .= "IO::Socket::SSL "; -my $version = "0.4.1"; +my $version = "1.0.0"; @@ -88,9 +88,10 @@ sub GardenaSmartBridge_WriteReadings($$); sub GardenaSmartBridge_ParseJSON($$); sub GardenaSmartBridge_getDevices($); sub GardenaSmartBridge_getToken($); -#sub GardenaSmartBridge_InternalTimerGetDeviceData($); sub GardenaSmartBridge_createHttpValueStrings($@); sub GardenaSmartBridge_Notify($$); +sub GardenaSmartBridge_StorePassword($$); +sub GardenaSmartBridge_ReadPassword($); @@ -117,6 +118,7 @@ sub GardenaSmartBridge_Initialize($) { "disable:1 ". "interval ". "disabledForIntervals ". + "gardenaAccountEmail ". $readingFnAttributes; foreach my $d(sort keys %{$modules{GardenaSmartBridge}{defptr}}) { @@ -133,35 +135,26 @@ sub GardenaSmartBridge_Define($$) { my @a = split( "[ \t][ \t]*", $def ); - return "too few parameters: define GardenaSmartBridge " if( @a != 4 ) ; + return "too few parameters: define GardenaSmartBridge" if( @a < 2 or @a > 4 ); return "Cannot define Gardena Bridge device. Perl modul ${missingModul}is missing." if ( $missingModul ); my $name = $a[0]; - my $user = $a[2]; - my $pass = $a[3]; $hash->{BRIDGE} = 1; $hash->{URL} = 'https://sg-api.dss.husqvarnagroup.net/sg-1'; $hash->{VERSION} = $version; $hash->{INTERVAL} = 300; $hash->{NOTIFYDEV} = "global,$name"; - - my $username = GardenaSmartBridge_encrypt($user); - my $password = GardenaSmartBridge_encrypt($pass); - Log3 $name, 3, "GardenaSmartBridge ($name) - encrypt $user/$pass to $username/$password" if($user ne $username || $pass ne $password); - $hash->{DEF} = "$username $password"; - - $hash->{helper}{username} = $username; - $hash->{helper}{password} = $password; - - $attr{$name}{room} = "GardenaSmart" if( !defined( $attr{$name}{room} ) ); + CommandAttr(undef,$name.' room GardenaSmart') if( AttrVal($name,'room','none') eq 'none' ); - readingsSingleUpdate($hash,'state','initialized',1); + CommandDefMod(undef,$name.' '.$hash->{TYPE}) if(@a > 2); # fix new define + readingsSingleUpdate($hash,'token','none',1); - Log3 $name, 3, "GardenaSmartBridge ($name) - defined GardenaSmartBridge and crypt your credentials"; - + readingsSingleUpdate($hash,'state','initialized',1); + Log3 $name, 3, "GardenaSmartBridge ($name) - defined GardenaSmartBridge"; + $modules{GardenaSmartBridge}{defptr}{BRIDGE} = $hash; return undef; @@ -172,7 +165,10 @@ sub GardenaSmartBridge_Undef($$) { my ( $hash, $arg ) = @_; + my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd"; + RemoveInternalTimer($hash); + setKeyValue($index,undef); delete $modules{GardenaSmartBridge}{defptr}{BRIDGE} if( defined($modules{GardenaSmartBridge}{defptr}{BRIDGE}) ); return undef; @@ -248,12 +244,14 @@ sub GardenaSmartBridge_Notify($$) { and (grep /^INITIALIZED$/,@{$events} or grep /^DEFINED.$name$/,@{$events} or grep /^MODIFIED.$name$/,@{$events} + or grep /^ATTR.$name.gardenaAccountEmail.+/,@{$events} ) ) or ($devtype eq 'GardenaSmartBridge' - and ReadingsVal('$devname','token','') eq 'none') + and (grep /^gardenaAccountPassword.+/,@{$events} + or ReadingsVal('$devname','token','') eq 'none') ) ); GardenaSmartBridge_getDevices($hash) if ( $devtype eq 'Global' @@ -276,49 +274,36 @@ sub GardenaSmartBridge_Notify($$) { sub GardenaSmartBridge_Set($@) { my ($hash, $name, $cmd, @args) = @_; - my ($arg, @params) = @args; + #my ($arg, @params) = @args; if( lc $cmd eq 'getdevicesstate' ) { - GardenaSmartBridge_getDevices($hash); } elsif( lc $cmd eq 'gettoken' ) { - + return "please set Attribut gardenaAccountEmail first" if(AttrVal($name,'gardenaAccountEmail','none') eq 'none'); + return "please set gardenaAccountPassword first" if( not defined(GardenaSmartBridge_ReadPassword($hash)) ); return "token is up to date" if( defined($hash->{helper}{session_id}) ); + GardenaSmartBridge_getToken($hash); + + } elsif( lc $cmd eq 'gardenaaccountpassword' ) { + return "please set Attribut gardenaAccountEmail first" if(AttrVal($name,'gardenaAccountEmail','none') eq 'none'); + return "usage: $cmd " if( @args != 1 ); + + my $passwd = join(' ',@args); + GardenaSmartBridge_StorePassword($hash,$passwd); } else { - my $list = "getDevicesState:noArg getToken:noArg"; + my $list = "getDevicesState:noArg getToken:noArg" if( defined(GardenaSmartBridge_ReadPassword($hash)) ); + $list .= " gardenaAccountPassword" if( not defined(GardenaSmartBridge_ReadPassword($hash)) ); return "Unknown argument $cmd, choose one of $list"; } return undef; } -# sub GardenaSmartBridge_InternalTimerGetDeviceData($) { -# -# my $hash = shift; -# my $name = $hash->{NAME}; -# -# -# #RemoveInternalTimer($hash); -# -# if( not IsDisabled($name) ) { -# -# GardenaSmartBridge_getDevices($hash); -# Log3 $name, 4, "GardenaSmartBridge ($name) - set internal timer function for recall InternalTimerGetDeviceData sub"; -# -# } else { -# -# readingsSingleUpdate($hash,'state','disabled',1); -# Log3 $name, 3, "GardenaSmartBridge ($name) - device is disabled"; -# } -# -# InternalTimer( gettimeofday()+$hash->{INTERVAL},"GardenaSmartBridge_InternalTimerGetDeviceData", $hash); -# } - sub GardenaSmartBridge_Write($@) { my ($hash,$payload,$deviceId,$abilities) = @_; @@ -396,7 +381,7 @@ sub GardenaSmartBridge_ErrorHandling($$$) { } } - if( $data eq "" and exists( $param->{code} ) && $param->{code} != 200 ) { + if( $data eq "" and exists( $param->{code} ) and $param->{code} != 200 ) { readingsBeginUpdate( $dhash ); readingsBulkUpdate( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dname, "state", 1 ) ne "initialized" ); @@ -528,7 +513,7 @@ sub GardenaSmartBridge_ResponseProcessing($$) { GardenaSmartBridge_WriteReadings($hash,$location); } - Log3 $name, 3, "GardenaSmartBridge ($name) - processed locations id. ID ist " . $hash->{helper}{locations_id}; + Log3 $name, 3, "GardenaSmartBridge ($name) - processed locations id. ID is " . $hash->{helper}{locations_id}; GardenaSmartBridge_Write($hash,undef,undef,undef); return; @@ -605,6 +590,8 @@ sub GardenaSmartBridge_getDevices($) { my $name = $hash->{NAME}; + RemoveInternalTimer($hash); + if( not IsDisabled($name) ) { GardenaSmartBridge_Write($hash,undef,undef,undef); @@ -620,52 +607,91 @@ sub GardenaSmartBridge_getToken($) { my $hash = shift; my $name = $hash->{NAME}; - + + + return readingsSingleUpdate($hash,'state','please set Attribut gardenaAccountEmail first',1) if(AttrVal($name,'gardenaAccountEmail','none') eq 'none'); + return readingsSingleUpdate($hash,'state','please set gardena account password first',1) if( not defined(GardenaSmartBridge_ReadPassword($hash)) ); readingsSingleUpdate($hash,'state','get token',1); - + delete $hash->{helper}{session_id} if( defined($hash->{helper}{session_id}) and $hash->{helper}{session_id} ); delete $hash->{helper}{user_id} if( defined($hash->{helper}{user_id}) and $hash->{helper}{user_id} ); delete $hash->{helper}{locations_id} if( defined($hash->{helper}{locations_id}) and $hash->{helper}{locations_id} ); - GardenaSmartBridge_Write($hash,'"sessions": {"email": "'.GardenaSmartBridge_decrypt($hash->{helper}{username}).'","password": "'.GardenaSmartBridge_decrypt($hash->{helper}{password}).'"}',undef,undef); + GardenaSmartBridge_Write($hash,'"sessions": {"email": "'.AttrVal($name,'gardenaAccountEmail','none').'","password": "'.GardenaSmartBridge_ReadPassword($hash).'"}',undef,undef); Log3 $name, 3, "GardenaSmartBridge ($name) - send credentials to fetch Token and locationId"; } -sub GardenaSmartBridge_encrypt($) { +sub GardenaSmartBridge_StorePassword($$) { + + my ($hash, $password) = @_; + my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd"; + my $key = getUniqueId().$index; + my $enc_pwd = ""; - my ($decoded) = @_; - my $key = getUniqueId(); - my $encoded; - - return $decoded if( $decoded =~ /crypt:/ ); - - for my $char (split //, $decoded) { - my $encode = chop($key); - $encoded .= sprintf("%.2x",ord($char)^ord($encode)); - $key = $encode.$key; + + if(eval "use Digest::MD5;1") { + + $key = Digest::MD5::md5_hex(unpack "H*", $key); + $key .= Digest::MD5::md5_hex($key); } + + for my $char (split //, $password) { + + my $encode=chop($key); + $enc_pwd.=sprintf("%.2x",ord($char)^ord($encode)); + $key=$encode.$key; + } + + my $err = setKeyValue($index, $enc_pwd); + return "error while saving the password - $err" if(defined($err)); - return 'crypt:'.$encoded; + return "password successfully saved"; } -sub GardenaSmartBridge_decrypt($) { +sub GardenaSmartBridge_ReadPassword($) { + + my ($hash) = @_; + my $name = $hash->{NAME}; + my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd"; + my $key = getUniqueId().$index; + my ($password, $err); - my ($encoded) = @_; - my $key = getUniqueId(); - my $decoded; + + Log3 $name, 4, "GardenaSmartBridge ($name) - Read password from file"; + + ($err, $password) = getKeyValue($index); - return $encoded if( $encoded !~ /crypt:/ ); - - $encoded = $1 if( $encoded =~ /crypt:(.*)/ ); - - for my $char (map { pack('C', hex($_)) } ($encoded =~ /(..)/g)) { - my $decode = chop($key); - $decoded .= chr(ord($char)^ord($decode)); - $key = $decode.$key; + if ( defined($err) ) { + + Log3 $name, 3, "GardenaSmartBridge ($name) - unable to read password from file: $err"; + return undef; + + } + + if ( defined($password) ) { + if ( eval "use Digest::MD5;1" ) { + + $key = Digest::MD5::md5_hex(unpack "H*", $key); + $key .= Digest::MD5::md5_hex($key); + } + + my $dec_pwd = ''; + + for my $char (map { pack('C', hex($_)) } ($password =~ /(..)/g)) { + + my $decode=chop($key); + $dec_pwd.=chr(ord($char)^ord($decode)); + $key=$decode.$key; + } + + return $dec_pwd; + + } else { + + Log3 $name, 3, "GardenaSmartBridge ($name) - No password in file"; + return undef; } - - return $decoded; } sub GardenaSmartBridge_ParseJSON($$) { @@ -681,11 +707,11 @@ sub GardenaSmartBridge_ParseJSON($$) { if($buffer) { foreach my $c (split //, $buffer) { - if($open == $close && $open > 0) { + if($open == $close and $open > 0) { $tail .= $c; - Log3 $name, 5, "GardenaSmartBridge ($name) - $open == $close && $open > 0"; + Log3 $name, 5, "GardenaSmartBridge ($name) - $open == $close and $open > 0"; - } elsif(($open == $close) && ($c ne '{')) { + } elsif(($open == $close) and ($c ne '{')) { Log3 $name, 5, "GardenaSmartBridge ($name) - Garbage character before message: " . $c; @@ -738,7 +764,16 @@ sub GardenaSmartBridge_createHttpValueStrings($@) { $uri .= '/sessions' if( not defined($hash->{helper}{session_id})); if( defined($hash->{helper}{locations_id}) ) { - $uri .= '/devices/' . $deviceId . '/abilities/' . $abilities . '/command' if( defined($abilities) and defined($payload) ); + #$uri .= '/devices/' . $deviceId . '/abilities/' . $abilities . '/command' if( defined($abilities) and defined($payload) ); + if ( defined($abilities) and $abilities eq 'mower_settings') { + + $method = 'PUT'; + my $dhash = $modules{GardenaSmartDevice}{defptr}{$deviceId}; + $uri .= '/devices/' . $deviceId . '/settings/' . $dhash->{helper}{STARTINGPOINTID} if( defined($abilities) and defined($payload) and $abilities eq 'mower_settings'); + } else { + $uri .= '/devices/' . $deviceId . '/abilities/' . $abilities . '/command' if( defined($abilities) and defined($payload) and $abilities ne 'mower_settings'); + } + $uri .= '?locationId=' . $hash->{helper}{locations_id}; } diff --git a/74_GardenaSmartDevice.pm b/74_GardenaSmartDevice.pm index 68e10ba..5490a1a 100644 --- a/74_GardenaSmartDevice.pm +++ b/74_GardenaSmartDevice.pm @@ -2,12 +2,13 @@ # # Developed with Kate # -# (c) 2017 Copyright: Marko Oldenburg (leongaultier at gmail dot com) +# (c) 2017-2018 Copyright: Marko Oldenburg (leongaultier at gmail dot com) # All rights reserved # # Special thanks goes to comitters: # - Michael (mbrak) Thanks for Commandref # - Matthias (Kenneth) Thanks for Wiki entry +# - BioS Thanks for predefined start points Code # # # This script is free software; you can redistribute it and/or modify @@ -65,7 +66,7 @@ use Time::Local; eval "use JSON;1" or $missingModul .= "JSON "; -my $version = "0.4.1"; +my $version = "1.0.0"; @@ -81,6 +82,7 @@ sub GardenaSmartDevice_Parse($$); sub GardenaSmartDevice_ReadingLangGerman($$); sub GardenaSmartDevice_RigRadingsValue($$); sub GardenaSmartDevice_Zulu2LocalString($); +sub GardenaSmartDevice_SetPredefinedStartPoints($@); @@ -111,25 +113,26 @@ sub GardenaSmartDevice_Initialize($) { sub GardenaSmartDevice_Define($$) { - my ( $hash, $def ) = @_; - my @a = split( "[ \t]+", $def ); + my ( $hash, $def ) = @_; + my @a = split( "[ \t]+", $def ); return "too few parameters: define GardenaSmartDevice " if( @a < 3 ) ; return "Cannot define Gardena Bridge device. Perl modul $missingModul is missing." if ( $missingModul ); - my $name = $a[0]; - my $deviceId = $a[2]; - my $category = $a[3]; + my $name = $a[0]; + my $deviceId = $a[2]; + my $category = $a[3]; - $hash->{DEVICEID} = $deviceId; - $hash->{VERSION} = $version; + $hash->{DEVICEID} = $deviceId; + $hash->{VERSION} = $version; + $hash->{helper}{STARTINGPOINTID} = ''; CommandAttr(undef,"$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}") if(AttrVal($name,'IODev','none') eq 'none'); - my $iodev = AttrVal($name,'IODev','none'); + my $iodev = AttrVal($name,'IODev','none'); AssignIoPort($hash,$iodev) if( !$hash->{IODev} ); @@ -144,11 +147,13 @@ sub GardenaSmartDevice_Define($$) { my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId}; return "GardenaSmartDevice device $name on GardenaSmartBridge $iodev already defined." - if( defined($d) && $d->{IODev} == $hash->{IODev} && $d->{NAME} ne $name ); + if( defined($d) and $d->{IODev} == $hash->{IODev} and $d->{NAME} ne $name ); - $attr{$name}{room} = "GardenaSmart" if( not defined( $attr{$name}{room} ) ); - $attr{$name}{model} = $category if( not defined( $attr{$name}{model} ) ); + #$attr{$name}{room} = "GardenaSmart" if( not defined( $attr{$name}{room} ) ); + CommandAttr(undef,$name.' room GardenaSmart') if( AttrVal($name,'room','none') eq 'none'); + #$attr{$name}{model} = $category if( not defined( $attr{$name}{model} ) ); + CommandAttr(undef,$name.' model '.$category) if( AttrVal($name,'model','none') eq 'none'); Log3 $name, 3, "GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId"; readingsSingleUpdate($hash,'state','initialized',1); @@ -182,7 +187,7 @@ sub GardenaSmartDevice_Attr(@) { sub GardenaSmartDevice_Set($@) { my ($hash, $name, $cmd, @args) = @_; - my ($arg, @params) = @args; + #my ($arg, @params) = @args; my $payload; my $abilities; @@ -205,7 +210,13 @@ sub GardenaSmartDevice_Set($@) { my $duration = join( " ", @args ); $payload = '"name":"start_override_timer","parameters":{"duration":' . $duration . '}'; - + + } elsif( lc $cmd eq 'startpoint' ) { + my $err; + + ($err,$payload,$abilities) = GardenaSmartDevice_SetPredefinedStartPoints($hash,@args); + return $err if( defined($err) ); + ### watering_computer } elsif( lc $cmd eq 'manualoverride' ) { @@ -232,33 +243,18 @@ sub GardenaSmartDevice_Set($@) { $payload = '"name":"measure_humidity"'; $abilities = 'humidity'; } - - } elsif( lc $cmd eq '' ) { - - } elsif( lc $cmd eq '' ) { - - } elsif( lc $cmd eq '' ) { - - } elsif( lc $cmd eq '' ) { - - - } elsif( lc $cmd eq '' ) { - - - } elsif( lc $cmd eq '' ) { - - + } else { my $list = ''; - $list .= 'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,60,1440' if( AttrVal($name,'model','unknown') eq 'mower' ); + $list .= 'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,60,1440 startpoint' if( AttrVal($name,'model','unknown') eq 'mower' ); $list .= 'manualOverride:slider,0,1,59 cancelOverride:noArg' if( AttrVal($name,'model','unknown') eq 'watering_computer' ); $list .= 'refresh:temperature,light' if( AttrVal($name,'model','unknown') eq 'sensor' ); return "Unknown argument $cmd, choose one of $list"; } - $abilities = 'mower' if( AttrVal($name,'model','unknown') eq 'mower' ); + $abilities = 'mower' if( AttrVal($name,'model','unknown') eq 'mower' ) and $abilities ne 'mower_settings'; $abilities = 'outlet' if( AttrVal($name,'model','unknown') eq 'watering_computer' ); @@ -310,10 +306,11 @@ sub GardenaSmartDevice_Parse($$) { sub GardenaSmartDevice_WriteReadings($$) { - my ($hash,$decode_json) = @_; + my ($hash,$decode_json) = @_; - my $name = $hash->{NAME}; - my $abilities = scalar (@{$decode_json->{abilities}}); + my $name = $hash->{NAME}; + my $abilities = scalar (@{$decode_json->{abilities}}); + my $settings = scalar (@{$decode_json->{settings}}); readingsBeginUpdate($hash); @@ -344,6 +341,27 @@ sub GardenaSmartDevice_WriteReadings($$) { $abilities--; } while ($abilities >= 0); + + + do { + + if( ref($decode_json->{settings}[$settings]{value}) eq "ARRAY" and $decode_json->{settings}[$settings]{name} eq 'starting_points' ) {; + #save the startingpointid needed to update the startingpoints + if ($hash->{helper}{STARTINGPOINTID} ne $decode_json->{settings}[$settings]{id}) { + $hash->{helper}{STARTINGPOINTID} = $decode_json->{settings}[$settings]{id}; + } + + $hash->{helper}{STARTINGPOINTS} = '{ "name": "starting_points", "value": '. encode_json($decode_json->{settings}[$settings]{value}) . '}'; + my $startpoint_cnt = 0; + + foreach my $startingpoint (@{$decode_json->{settings}[$settings]{value}}) { + $startpoint_cnt++; + readingsBulkUpdateIfChanged($hash,'startpoint-'.$startpoint_cnt.'-enabled',$startingpoint->{enabled}); + } + } + + $settings--; + } while ($settings >= 0); readingsBulkUpdate($hash,'state',ReadingsVal($name,'mower-status','readingsValError')) if( AttrVal($name,'model','unknown') eq 'mower' ); @@ -509,6 +527,52 @@ sub GardenaSmartDevice_Zulu2LocalString($) { } } +sub GardenaSmartDevice_SetPredefinedStartPoints($@) { + + my ($hash,$startpoint_state,$startpoint_num,@morestartpoints) = @_; + my $name = $hash->{NAME}; + my $payload; + my $abilities; + + + if (defined($startpoint_state) and defined($startpoint_num) ) { + if (defined($hash->{helper}{STARTINGPOINTS}) and $hash->{helper}{STARTINGPOINTS} ne '') { + # add needed parameters to saved settings config and change the value in request + my $decode_json_settings = eval{decode_json($hash->{helper}{STARTINGPOINTS})}; + if($@){ + Log3 $name, 3, "GardenaSmartBridge ($name) - JSON error while setting startpoint: $@"; + } + + $decode_json_settings->{device} = $hash->{DEVICEID}; + my $setval = $startpoint_state eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[$startpoint_num-1]{enabled} = $setval; + + #set more startpoints + if (defined scalar(@morestartpoints) and (scalar(@morestartpoints) == 2 or scalar(@morestartpoints) == 4 )) { + if (scalar(@morestartpoints) == 2) { + $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[$morestartpoints[1]-1]{enabled} = $setval; + + } elsif (scalar(@morestartpoints) == 4) { + $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[$morestartpoints[1]-1]{enabled} = $setval; + $setval = $morestartpoints[2] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[$morestartpoints[3]-1]{enabled} = $setval; + } + } + + $payload = '"settings": '. encode_json($decode_json_settings); + $abilities = 'mower_settings'; + } else { + return "startingpoints not loaded yet, please wait a couple of minutes",undef,undef; + } + } else { + return "startpoint usage: set ".$hash->{NAME}." startpoint disable 1 [enable 2] [disable 3]",undef,undef; + } + + return undef,$payload,$abilities; +} + @@ -654,8 +718,13 @@ sub GardenaSmartDevice_Zulu2LocalString($) {
  • parkUntilFurtherNotice
  • parkUntilNextTimer
  • -
  • startOverrideTimer - 0 to 59 Minutes
  • +
  • startOverrideTimer - (in minutes, 60 = 1h, 1440 = 24h, 4320 = 72h)
  • startResumeSchedule
  • +
  • startpoint enable|disable 1|2|3 - enables or disables one or more predefined start points
  • +
      +
    • set NAME startpoint enable 1
    • +
    • set NAME startpoint disable 3 enable 1
    • +
@@ -793,8 +862,13 @@ sub GardenaSmartDevice_Zulu2LocalString($) {
  • parkUntilFurtherNotice - Parken des Mähers unter Umgehung des Zeitplans
  • parkUntilNextTimer - Parken bis zum nächsten Zeitplan
  • -
  • startOverrideTimer - Manuelles mähen (0 bis 59 Minuten)
  • +
  • startOverrideTimer - Manuelles mähen (in Minuten, 60 = 1h, 1440 = 24h, 4320 = 72h)
  • startResumeSchedule - Weiterführung des Zeitplans
  • +
  • startpoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
  • +
      +
    • set NAME startpoint enable 1
    • +
    • set NAME startpoint disable 3 enable 1
    • +