rewrite parts of Bridge Modul and add Support for predefined start points

This commit is contained in:
Marko Oldenburg 2018-04-03 14:15:16 +02:00
parent 13b817d820
commit fe3f0758b4
2 changed files with 228 additions and 119 deletions

View File

@ -2,7 +2,7 @@
# #
# Developed with Kate # 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 # All rights reserved
# #
# Special thanks goes to comitters: # 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 "; 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_ParseJSON($$);
sub GardenaSmartBridge_getDevices($); sub GardenaSmartBridge_getDevices($);
sub GardenaSmartBridge_getToken($); sub GardenaSmartBridge_getToken($);
#sub GardenaSmartBridge_InternalTimerGetDeviceData($);
sub GardenaSmartBridge_createHttpValueStrings($@); sub GardenaSmartBridge_createHttpValueStrings($@);
sub GardenaSmartBridge_Notify($$); sub GardenaSmartBridge_Notify($$);
sub GardenaSmartBridge_StorePassword($$);
sub GardenaSmartBridge_ReadPassword($);
@ -117,6 +118,7 @@ sub GardenaSmartBridge_Initialize($) {
"disable:1 ". "disable:1 ".
"interval ". "interval ".
"disabledForIntervals ". "disabledForIntervals ".
"gardenaAccountEmail ".
$readingFnAttributes; $readingFnAttributes;
foreach my $d(sort keys %{$modules{GardenaSmartBridge}{defptr}}) { foreach my $d(sort keys %{$modules{GardenaSmartBridge}{defptr}}) {
@ -133,35 +135,26 @@ sub GardenaSmartBridge_Define($$) {
my @a = split( "[ \t][ \t]*", $def ); my @a = split( "[ \t][ \t]*", $def );
return "too few parameters: define <NAME> GardenaSmartBridge <Email> <Passwort>" if( @a != 4 ) ; return "too few parameters: define <NAME> GardenaSmartBridge" if( @a < 2 or @a > 4 );
return "Cannot define Gardena Bridge device. Perl modul ${missingModul}is missing." if ( $missingModul ); return "Cannot define Gardena Bridge device. Perl modul ${missingModul}is missing." if ( $missingModul );
my $name = $a[0]; my $name = $a[0];
my $user = $a[2];
my $pass = $a[3];
$hash->{BRIDGE} = 1; $hash->{BRIDGE} = 1;
$hash->{URL} = 'https://sg-api.dss.husqvarnagroup.net/sg-1'; $hash->{URL} = 'https://sg-api.dss.husqvarnagroup.net/sg-1';
$hash->{VERSION} = $version; $hash->{VERSION} = $version;
$hash->{INTERVAL} = 300; $hash->{INTERVAL} = 300;
$hash->{NOTIFYDEV} = "global,$name"; $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); 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; $modules{GardenaSmartBridge}{defptr}{BRIDGE} = $hash;
return undef; return undef;
@ -172,7 +165,10 @@ sub GardenaSmartBridge_Undef($$) {
my ( $hash, $arg ) = @_; my ( $hash, $arg ) = @_;
my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd";
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
setKeyValue($index,undef);
delete $modules{GardenaSmartBridge}{defptr}{BRIDGE} if( defined($modules{GardenaSmartBridge}{defptr}{BRIDGE}) ); delete $modules{GardenaSmartBridge}{defptr}{BRIDGE} if( defined($modules{GardenaSmartBridge}{defptr}{BRIDGE}) );
return undef; return undef;
@ -248,12 +244,14 @@ sub GardenaSmartBridge_Notify($$) {
and (grep /^INITIALIZED$/,@{$events} and (grep /^INITIALIZED$/,@{$events}
or grep /^DEFINED.$name$/,@{$events} or grep /^DEFINED.$name$/,@{$events}
or grep /^MODIFIED.$name$/,@{$events} or grep /^MODIFIED.$name$/,@{$events}
or grep /^ATTR.$name.gardenaAccountEmail.+/,@{$events}
) )
) )
or or
($devtype eq 'GardenaSmartBridge' ($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' GardenaSmartBridge_getDevices($hash) if ( $devtype eq 'Global'
@ -276,49 +274,36 @@ sub GardenaSmartBridge_Notify($$) {
sub GardenaSmartBridge_Set($@) { sub GardenaSmartBridge_Set($@) {
my ($hash, $name, $cmd, @args) = @_; my ($hash, $name, $cmd, @args) = @_;
my ($arg, @params) = @args; #my ($arg, @params) = @args;
if( lc $cmd eq 'getdevicesstate' ) { if( lc $cmd eq 'getdevicesstate' ) {
GardenaSmartBridge_getDevices($hash); GardenaSmartBridge_getDevices($hash);
} elsif( lc $cmd eq 'gettoken' ) { } 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}) ); return "token is up to date" if( defined($hash->{helper}{session_id}) );
GardenaSmartBridge_getToken($hash); GardenaSmartBridge_getToken($hash);
} elsif( lc $cmd eq 'gardenaaccountpassword' ) {
return "please set Attribut gardenaAccountEmail first" if(AttrVal($name,'gardenaAccountEmail','none') eq 'none');
return "usage: $cmd <password>" if( @args != 1 );
my $passwd = join(' ',@args);
GardenaSmartBridge_StorePassword($hash,$passwd);
} else { } 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 "Unknown argument $cmd, choose one of $list";
} }
return undef; 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($@) { sub GardenaSmartBridge_Write($@) {
my ($hash,$payload,$deviceId,$abilities) = @_; 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 ); readingsBeginUpdate( $dhash );
readingsBulkUpdate( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dname, "state", 1 ) ne "initialized" ); readingsBulkUpdate( $dhash, "state", $param->{code}, 1 ) if( ReadingsVal( $dname, "state", 1 ) ne "initialized" );
@ -528,7 +513,7 @@ sub GardenaSmartBridge_ResponseProcessing($$) {
GardenaSmartBridge_WriteReadings($hash,$location); 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); GardenaSmartBridge_Write($hash,undef,undef,undef);
return; return;
@ -605,6 +590,8 @@ sub GardenaSmartBridge_getDevices($) {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
RemoveInternalTimer($hash);
if( not IsDisabled($name) ) { if( not IsDisabled($name) ) {
GardenaSmartBridge_Write($hash,undef,undef,undef); GardenaSmartBridge_Write($hash,undef,undef,undef);
@ -620,52 +607,91 @@ sub GardenaSmartBridge_getToken($) {
my $hash = shift; my $hash = shift;
my $name = $hash->{NAME}; 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); 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}{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}{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} ); 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"; 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(); if(eval "use Digest::MD5;1") {
my $encoded;
$key = Digest::MD5::md5_hex(unpack "H*", $key);
return $decoded if( $decoded =~ /crypt:/ ); $key .= Digest::MD5::md5_hex($key);
for my $char (split //, $decoded) {
my $encode = chop($key);
$encoded .= sprintf("%.2x",ord($char)^ord($encode));
$key = $encode.$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(); Log3 $name, 4, "GardenaSmartBridge ($name) - Read password from file";
my $decoded;
($err, $password) = getKeyValue($index);
return $encoded if( $encoded !~ /crypt:/ ); if ( defined($err) ) {
$encoded = $1 if( $encoded =~ /crypt:(.*)/ ); Log3 $name, 3, "GardenaSmartBridge ($name) - unable to read password from file: $err";
return undef;
for my $char (map { pack('C', hex($_)) } ($encoded =~ /(..)/g)) {
my $decode = chop($key); }
$decoded .= chr(ord($char)^ord($decode));
$key = $decode.$key; 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($$) { sub GardenaSmartBridge_ParseJSON($$) {
@ -681,11 +707,11 @@ sub GardenaSmartBridge_ParseJSON($$) {
if($buffer) { if($buffer) {
foreach my $c (split //, $buffer) { foreach my $c (split //, $buffer) {
if($open == $close && $open > 0) { if($open == $close and $open > 0) {
$tail .= $c; $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; 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})); $uri .= '/sessions' if( not defined($hash->{helper}{session_id}));
if( defined($hash->{helper}{locations_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}; $uri .= '?locationId=' . $hash->{helper}{locations_id};
} }

View File

@ -2,12 +2,13 @@
# #
# Developed with Kate # 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 # All rights reserved
# #
# Special thanks goes to comitters: # Special thanks goes to comitters:
# - Michael (mbrak) Thanks for Commandref # - Michael (mbrak) Thanks for Commandref
# - Matthias (Kenneth) Thanks for Wiki entry # - 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 # 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 "; 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_ReadingLangGerman($$);
sub GardenaSmartDevice_RigRadingsValue($$); sub GardenaSmartDevice_RigRadingsValue($$);
sub GardenaSmartDevice_Zulu2LocalString($); sub GardenaSmartDevice_Zulu2LocalString($);
sub GardenaSmartDevice_SetPredefinedStartPoints($@);
@ -111,25 +113,26 @@ sub GardenaSmartDevice_Initialize($) {
sub GardenaSmartDevice_Define($$) { sub GardenaSmartDevice_Define($$) {
my ( $hash, $def ) = @_; my ( $hash, $def ) = @_;
my @a = split( "[ \t]+", $def ); my @a = split( "[ \t]+", $def );
return "too few parameters: define <NAME> GardenaSmartDevice <device_Id> <model>" if( @a < 3 ) ; return "too few parameters: define <NAME> GardenaSmartDevice <device_Id> <model>" if( @a < 3 ) ;
return "Cannot define Gardena Bridge device. Perl modul $missingModul is missing." if ( $missingModul ); return "Cannot define Gardena Bridge device. Perl modul $missingModul is missing." if ( $missingModul );
my $name = $a[0]; my $name = $a[0];
my $deviceId = $a[2]; my $deviceId = $a[2];
my $category = $a[3]; my $category = $a[3];
$hash->{DEVICEID} = $deviceId; $hash->{DEVICEID} = $deviceId;
$hash->{VERSION} = $version; $hash->{VERSION} = $version;
$hash->{helper}{STARTINGPOINTID} = '';
CommandAttr(undef,"$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}") if(AttrVal($name,'IODev','none') eq 'none'); 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} ); AssignIoPort($hash,$iodev) if( !$hash->{IODev} );
@ -144,11 +147,13 @@ sub GardenaSmartDevice_Define($$) {
my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId}; my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId};
return "GardenaSmartDevice device $name on GardenaSmartBridge $iodev already defined." 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}{room} = "GardenaSmart" if( not defined( $attr{$name}{room} ) );
$attr{$name}{model} = $category if( not defined( $attr{$name}{model} ) ); 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"; Log3 $name, 3, "GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId";
readingsSingleUpdate($hash,'state','initialized',1); readingsSingleUpdate($hash,'state','initialized',1);
@ -182,7 +187,7 @@ sub GardenaSmartDevice_Attr(@) {
sub GardenaSmartDevice_Set($@) { sub GardenaSmartDevice_Set($@) {
my ($hash, $name, $cmd, @args) = @_; my ($hash, $name, $cmd, @args) = @_;
my ($arg, @params) = @args; #my ($arg, @params) = @args;
my $payload; my $payload;
my $abilities; my $abilities;
@ -205,7 +210,13 @@ sub GardenaSmartDevice_Set($@) {
my $duration = join( " ", @args ); my $duration = join( " ", @args );
$payload = '"name":"start_override_timer","parameters":{"duration":' . $duration . '}'; $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 ### watering_computer
} elsif( lc $cmd eq 'manualoverride' ) { } elsif( lc $cmd eq 'manualoverride' ) {
@ -232,33 +243,18 @@ sub GardenaSmartDevice_Set($@) {
$payload = '"name":"measure_humidity"'; $payload = '"name":"measure_humidity"';
$abilities = '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 { } else {
my $list = ''; 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 .= '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' ); $list .= 'refresh:temperature,light' if( AttrVal($name,'model','unknown') eq 'sensor' );
return "Unknown argument $cmd, choose one of $list"; 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' ); $abilities = 'outlet' if( AttrVal($name,'model','unknown') eq 'watering_computer' );
@ -310,10 +306,11 @@ sub GardenaSmartDevice_Parse($$) {
sub GardenaSmartDevice_WriteReadings($$) { sub GardenaSmartDevice_WriteReadings($$) {
my ($hash,$decode_json) = @_; my ($hash,$decode_json) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $abilities = scalar (@{$decode_json->{abilities}}); my $abilities = scalar (@{$decode_json->{abilities}});
my $settings = scalar (@{$decode_json->{settings}});
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
@ -344,6 +341,27 @@ sub GardenaSmartDevice_WriteReadings($$) {
$abilities--; $abilities--;
} while ($abilities >= 0); } 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' ); 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($) {
<ul> <ul>
<li>parkUntilFurtherNotice</li> <li>parkUntilFurtherNotice</li>
<li>parkUntilNextTimer</li> <li>parkUntilNextTimer</li>
<li>startOverrideTimer - 0 to 59 Minutes</li> <li>startOverrideTimer - (in minutes, 60 = 1h, 1440 = 24h, 4320 = 72h)</li>
<li>startResumeSchedule</li> <li>startResumeSchedule</li>
<li>startpoint enable|disable 1|2|3 - enables or disables one or more predefined start points</li>
<ul>
<li>set NAME startpoint enable 1</li>
<li>set NAME startpoint disable 3 enable 1</li>
</ul>
</ul> </ul>
</ul> </ul>
@ -793,8 +862,13 @@ sub GardenaSmartDevice_Zulu2LocalString($) {
<ul> <ul>
<li>parkUntilFurtherNotice - Parken des M&auml;hers unter Umgehung des Zeitplans</li> <li>parkUntilFurtherNotice - Parken des M&auml;hers unter Umgehung des Zeitplans</li>
<li>parkUntilNextTimer - Parken bis zum n&auml;chsten Zeitplan</li> <li>parkUntilNextTimer - Parken bis zum n&auml;chsten Zeitplan</li>
<li>startOverrideTimer - Manuelles m&auml;hen (0 bis 59 Minuten)</li> <li>startOverrideTimer - Manuelles m&auml;hen (in Minuten, 60 = 1h, 1440 = 24h, 4320 = 72h)</li>
<li>startResumeSchedule - Weiterf&uuml;hrung des Zeitplans</li> <li>startResumeSchedule - Weiterf&uuml;hrung des Zeitplans</li>
<li>startpoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich</li>
<ul>
<li>set NAME startpoint enable 1</li>
<li>set NAME startpoint disable 3 enable 1</li>
</ul>
</ul> </ul>
</ul> </ul>