patch-async_run_parseJson #48
@@ -1,8 +1,8 @@
 | 
				
			|||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Developed with Kate
 | 
					# Developed with VSCodium and richterger perl plugin.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  (c) 2017-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
 | 
					#  (c) 2017-2022 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
 | 
				
			||||||
#  All rights reserved
 | 
					#  All rights reserved
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#   Special thanks goes to comitters:
 | 
					#   Special thanks goes to comitters:
 | 
				
			||||||
@@ -57,7 +57,6 @@
 | 
				
			|||||||
package FHEM::GardenaSmartBridge;
 | 
					package FHEM::GardenaSmartBridge;
 | 
				
			||||||
use GPUtils qw(GP_Import GP_Export);
 | 
					use GPUtils qw(GP_Import GP_Export);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
use strict;
 | 
					use strict;
 | 
				
			||||||
use warnings;
 | 
					use warnings;
 | 
				
			||||||
use POSIX;
 | 
					use POSIX;
 | 
				
			||||||
@@ -183,7 +182,7 @@ BEGIN {
 | 
				
			|||||||
#-- Export to main context with different name
 | 
					#-- Export to main context with different name
 | 
				
			||||||
GP_Export(
 | 
					GP_Export(
 | 
				
			||||||
    qw(
 | 
					    qw(
 | 
				
			||||||
        Initialize
 | 
					      Initialize
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -237,12 +236,10 @@ sub Define {
 | 
				
			|||||||
    my $name = shift @$aArg;
 | 
					    my $name = shift @$aArg;
 | 
				
			||||||
    $hash->{BRIDGE} = 1;
 | 
					    $hash->{BRIDGE} = 1;
 | 
				
			||||||
    $hash->{URL} =
 | 
					    $hash->{URL} =
 | 
				
			||||||
      AttrVal( $name, 'gardenaBaseURL',
 | 
					      AttrVal( $name, 'gardenaBaseURL', 'https://smart.gardena.com' ) . '/v1';
 | 
				
			||||||
        'https://smart.gardena.com' )
 | 
					 | 
				
			||||||
      . '/v1';
 | 
					 | 
				
			||||||
    $hash->{VERSION}   = version->parse($VERSION)->normal;
 | 
					    $hash->{VERSION}   = version->parse($VERSION)->normal;
 | 
				
			||||||
    $hash->{INTERVAL}  = 60;
 | 
					    $hash->{INTERVAL}  = 60;
 | 
				
			||||||
    $hash->{NOTIFYDEV} = "global,$name"; 
 | 
					    $hash->{NOTIFYDEV} = "global,$name";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CommandAttr( undef, $name . ' room GardenaSmart' )
 | 
					    CommandAttr( undef, $name . ' room GardenaSmart' )
 | 
				
			||||||
      if ( AttrVal( $name, 'room', 'none' ) eq 'none' );
 | 
					      if ( AttrVal( $name, 'room', 'none' ) eq 'none' );
 | 
				
			||||||
@@ -261,7 +258,7 @@ sub Undef {
 | 
				
			|||||||
    my $hash = shift;
 | 
					    my $hash = shift;
 | 
				
			||||||
    my $name = shift;
 | 
					    my $name = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
					    RemoveInternalTimer( $hash, "FHEM::GardenaSmartBridge::getDevices" );
 | 
				
			||||||
    delete $modules{GardenaSmartBridge}{defptr}{BRIDGE}
 | 
					    delete $modules{GardenaSmartBridge}{defptr}{BRIDGE}
 | 
				
			||||||
      if ( defined( $modules{GardenaSmartBridge}{defptr}{BRIDGE} ) );
 | 
					      if ( defined( $modules{GardenaSmartBridge}{defptr}{BRIDGE} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -282,7 +279,8 @@ sub Attr {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if ( $attrName eq 'disable' ) {
 | 
					    if ( $attrName eq 'disable' ) {
 | 
				
			||||||
        if ( $cmd eq 'set' && $attrVal eq '1' ) {
 | 
					        if ( $cmd eq 'set' && $attrVal eq '1' ) {
 | 
				
			||||||
            RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
					            RemoveInternalTimer( $hash,
 | 
				
			||||||
 | 
					                "FHEM::GardenaSmartBridge::getDevices" );
 | 
				
			||||||
            readingsSingleUpdate( $hash, 'state', 'inactive', 1 );
 | 
					            readingsSingleUpdate( $hash, 'state', 'inactive', 1 );
 | 
				
			||||||
            Log3 $name, 3, "GardenaSmartBridge ($name) - disabled";
 | 
					            Log3 $name, 3, "GardenaSmartBridge ($name) - disabled";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -307,13 +305,15 @@ sub Attr {
 | 
				
			|||||||
        if ( $cmd eq 'set' ) {
 | 
					        if ( $cmd eq 'set' ) {
 | 
				
			||||||
            return 'Interval must be greater than 0'
 | 
					            return 'Interval must be greater than 0'
 | 
				
			||||||
              if ( $attrVal == 0 );
 | 
					              if ( $attrVal == 0 );
 | 
				
			||||||
            RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
					            RemoveInternalTimer( $hash,
 | 
				
			||||||
 | 
					                "FHEM::GardenaSmartBridge::getDevices" );
 | 
				
			||||||
            $hash->{INTERVAL} = $attrVal;
 | 
					            $hash->{INTERVAL} = $attrVal;
 | 
				
			||||||
            Log3 $name, 3,
 | 
					            Log3 $name, 3,
 | 
				
			||||||
              "GardenaSmartBridge ($name) - set interval: $attrVal";
 | 
					              "GardenaSmartBridge ($name) - set interval: $attrVal";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elsif ( $cmd eq 'del' ) {
 | 
					        elsif ( $cmd eq 'del' ) {
 | 
				
			||||||
            RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
					            RemoveInternalTimer( $hash,
 | 
				
			||||||
 | 
					                "FHEM::GardenaSmartBridge::getDevices" );
 | 
				
			||||||
            $hash->{INTERVAL} = 60;
 | 
					            $hash->{INTERVAL} = 60;
 | 
				
			||||||
            Log3 $name, 3,
 | 
					            Log3 $name, 3,
 | 
				
			||||||
"GardenaSmartBridge ($name) - delete User interval and set default: 60";
 | 
					"GardenaSmartBridge ($name) - delete User interval and set default: 60";
 | 
				
			||||||
@@ -360,14 +360,9 @@ sub Notify {
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        || (
 | 
					        || ( $devtype eq 'GardenaSmartBridge'
 | 
				
			||||||
            $devtype eq 'GardenaSmartBridge'
 | 
					            && ( grep /^gardenaAccountPassword.+/, @{$events} ) )
 | 
				
			||||||
            && (
 | 
					        && $init_done
 | 
				
			||||||
                grep /^gardenaAccountPassword.+/,
 | 
					 | 
				
			||||||
                @{$events}
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
      && $init_done
 | 
					 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getDevices($hash)
 | 
					    getDevices($hash)
 | 
				
			||||||
@@ -387,7 +382,7 @@ sub Notify {
 | 
				
			|||||||
        && (
 | 
					        && (
 | 
				
			||||||
            grep /^state:.Connected$/,
 | 
					            grep /^state:.Connected$/,
 | 
				
			||||||
            @{$events} or grep /^lastRequestState:.request_error$/,
 | 
					            @{$events} or grep /^lastRequestState:.request_error$/,
 | 
				
			||||||
            @{$events} 
 | 
					            @{$events}
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -399,6 +394,7 @@ sub Notify {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Get {
 | 
					sub Get {
 | 
				
			||||||
    my $hash = shift // return;
 | 
					    my $hash = shift // return;
 | 
				
			||||||
    my $aArg = shift // return;
 | 
					    my $aArg = shift // return;
 | 
				
			||||||
@@ -410,15 +406,16 @@ sub Get {
 | 
				
			|||||||
    if ( lc $cmd eq 'debug_devices_list' ) {
 | 
					    if ( lc $cmd eq 'debug_devices_list' ) {
 | 
				
			||||||
        my $device = shift @$aArg;
 | 
					        my $device = shift @$aArg;
 | 
				
			||||||
        $hash->{helper}{debug_device} = $device;
 | 
					        $hash->{helper}{debug_device} = $device;
 | 
				
			||||||
        Write($hash, undef, undef, undef, undef); 
 | 
					        Write( $hash, undef, undef, undef, undef );
 | 
				
			||||||
        return undef;
 | 
					        return;
 | 
				
			||||||
    } else {
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
        my $list = "";
 | 
					        my $list = "";
 | 
				
			||||||
        $list .= " debug_devices_list:"
 | 
					        $list .=
 | 
				
			||||||
          .join( ',', @{ $hash->{helper}{deviceList} }) 
 | 
					          " debug_devices_list:" . join( ',', @{ $hash->{helper}{deviceList} } )
 | 
				
			||||||
          if ( AttrVal( $name, "debugDEVICE", "none") ne "none" 
 | 
					          if ( AttrVal( $name, "debugDEVICE", "none" ) ne "none"
 | 
				
			||||||
           && exists($hash->{helper}{deviceList}) );
 | 
					            && exists( $hash->{helper}{deviceList} ) );
 | 
				
			||||||
      return "Unknown argument $cmd,choose one of $list";    
 | 
					        return "Unknown argument $cmd,choose one of $list";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -427,8 +424,9 @@ sub Set {
 | 
				
			|||||||
    my $aArg = shift // return;
 | 
					    my $aArg = shift // return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name = shift @$aArg // return;
 | 
					    my $name = shift @$aArg // return;
 | 
				
			||||||
    my $cmd  = shift @$aArg // return qq{"set $name" needs at least one argument};
 | 
					    my $cmd  = shift @$aArg
 | 
				
			||||||
    
 | 
					      // return qq{"set $name" needs at least one argument};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#     Das Argument für das Passwort, also das Passwort an sich darf keine = enthalten!!!
 | 
					#     Das Argument für das Passwort, also das Passwort an sich darf keine = enthalten!!!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( lc $cmd eq 'getdevicesstate' ) {
 | 
					    if ( lc $cmd eq 'getdevicesstate' ) {
 | 
				
			||||||
@@ -478,21 +476,22 @@ sub Write {
 | 
				
			|||||||
    my ( $session_id, $header, $uri, $method );
 | 
					    my ( $session_id, $header, $uri, $method );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ( $payload, $session_id, $header, $uri, $method, $deviceId, $service_id ) =
 | 
					    ( $payload, $session_id, $header, $uri, $method, $deviceId, $service_id ) =
 | 
				
			||||||
      createHttpValueStrings( $hash, $payload, $deviceId, $abilities, $service_id );
 | 
					      createHttpValueStrings( $hash, $payload, $deviceId, $abilities,
 | 
				
			||||||
 | 
					        $service_id );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    HttpUtils_NonblockingGet(
 | 
					    HttpUtils_NonblockingGet(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            url       => $hash->{URL} . $uri,
 | 
					            url                => $hash->{URL} . $uri,
 | 
				
			||||||
            timeout   => 15,
 | 
					            timeout            => 15,
 | 
				
			||||||
            incrementalTimeout => 1,
 | 
					            incrementalTimeout => 1,
 | 
				
			||||||
            hash      => $hash,
 | 
					            hash               => $hash,
 | 
				
			||||||
            device_id => $deviceId,
 | 
					            device_id          => $deviceId,
 | 
				
			||||||
            data      => $payload,
 | 
					            data               => $payload,
 | 
				
			||||||
            method    => $method,
 | 
					            method             => $method,
 | 
				
			||||||
            header    => $header,
 | 
					            header             => $header,
 | 
				
			||||||
            doTrigger => 1,
 | 
					            doTrigger          => 1,
 | 
				
			||||||
            cl        => $hash->{CL},
 | 
					            cl                 => $hash->{CL},
 | 
				
			||||||
            callback  => \&ErrorHandling
 | 
					            callback           => \&ErrorHandling
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -500,8 +499,8 @@ sub Write {
 | 
				
			|||||||
"GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: secret!, DATA: secret!, METHOD: $method"
 | 
					"GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: secret!, DATA: secret!, METHOD: $method"
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #  Log3($name, 3,
 | 
					#  Log3($name, 3,
 | 
				
			||||||
    #      "GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: $header, DATA: $payload, METHOD: $method");
 | 
					#      "GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: $header, DATA: $payload, METHOD: $method");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -519,7 +518,7 @@ sub ErrorHandling {
 | 
				
			|||||||
      if ( defined( $param->{'device_id'} ) );
 | 
					      if ( defined( $param->{'device_id'} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $dname = $dhash->{NAME};
 | 
					    my $dname = $dhash->{NAME};
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    Log3 $name, 4, "GardenaSmartBridge ($name) - Request: $data";
 | 
					    Log3 $name, 4, "GardenaSmartBridge ($name) - Request: $data";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $decode_json = eval { decode_json($data) } if ( length($data) > 0 );
 | 
					    my $decode_json = eval { decode_json($data) } if ( length($data) > 0 );
 | 
				
			||||||
@@ -702,6 +701,11 @@ sub ErrorHandling {
 | 
				
			|||||||
              . $param->{code};
 | 
					              . $param->{code};
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( !defined( $hash->{helper}{session_id} ) ) {
 | 
				
			||||||
 | 
					            readingsSingleUpdate( $hash, 'token', 'none', 1 );
 | 
				
			||||||
 | 
					            InternalTimer( gettimeofday() + 5,
 | 
				
			||||||
 | 
					                "FHEM::GardenaSmartBridge::getToken", $hash );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        readingsEndUpdate( $dhash, 1 );
 | 
					        readingsEndUpdate( $dhash, 1 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Log3 $dname, 5,
 | 
					        Log3 $dname, 5,
 | 
				
			||||||
@@ -712,60 +716,70 @@ sub ErrorHandling {
 | 
				
			|||||||
        delete $dhash->{helper}{deviceAction}
 | 
					        delete $dhash->{helper}{deviceAction}
 | 
				
			||||||
          if ( defined( $dhash->{helper}{deviceAction} ) );
 | 
					          if ( defined( $dhash->{helper}{deviceAction} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        readingsSingleUpdate( $hash, 'token', 'none', 1 )
 | 
					 | 
				
			||||||
          if ( !defined( $hash->{helper}{session_id} ) );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        getToken($hash) 
 | 
					 | 
				
			||||||
          if ( !defined( $hash->{helper}{session_id} ) );
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif (defined ($decode_json->{message}) 
 | 
					    elsif ( defined( $decode_json->{message} )
 | 
				
			||||||
          && $decode_json->{message} eq 'Unauthorized') {
 | 
					        && $decode_json->{message} eq 'Unauthorized' )
 | 
				
			||||||
      Log3 $name, 3,
 | 
					    {
 | 
				
			||||||
          "GardenaSmartBridge ($name) - Unauthorized -> fetch new token ";     
 | 
					        Log3 $name, 3,
 | 
				
			||||||
      getToken($hash);
 | 
					          "GardenaSmartBridge ($name) - Unauthorized -> fetch new token ";
 | 
				
			||||||
      return;
 | 
					
 | 
				
			||||||
 | 
					        getToken($hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (defined($hash->{helper}{debug_device})
 | 
					    if ( defined( $hash->{helper}{debug_device} )
 | 
				
			||||||
    	&& $hash->{helper}{debug_device} ne 'none'
 | 
					        && $hash->{helper}{debug_device} ne 'none' )
 | 
				
			||||||
    	){
 | 
					    {
 | 
				
			||||||
      Log3 $name, 4, "GardenaSmartBridge DEBUG Device";
 | 
					        Log3 $name, 4, "GardenaSmartBridge DEBUG Device";
 | 
				
			||||||
      delete $hash->{helper}{debug_device};
 | 
					        delete $hash->{helper}{debug_device};
 | 
				
			||||||
      my @device_spec = ("name", "id", "category");
 | 
					
 | 
				
			||||||
      my $devJson=$decode_json->{devices};
 | 
					        my @device_spec = ( "name", "id", "category" );
 | 
				
			||||||
      my $output = '.:{ DEBUG OUTPUT for '.$devJson->{name}.' }:. \n';
 | 
					        my $devJson     = $decode_json->{devices};
 | 
				
			||||||
      for my $spec (@device_spec) {
 | 
					        my $output = '.:{ DEBUG OUTPUT for ' . $devJson->{name} . ' }:. \n';
 | 
				
			||||||
        $output .= "$spec : $devJson->{$spec} \n";
 | 
					
 | 
				
			||||||
      }
 | 
					        for my $spec (@device_spec) {
 | 
				
			||||||
      #settings
 | 
					            $output .= "$spec : $devJson->{$spec} \n";
 | 
				
			||||||
      $output .= '\n=== Settings \n';
 | 
					 | 
				
			||||||
      my $i = 0;
 | 
					 | 
				
			||||||
      for my $dev_settings ( @ { $devJson->{settings} } ) {
 | 
					 | 
				
			||||||
        $output .= "[".$i++."]id: $dev_settings->{id} \n";
 | 
					 | 
				
			||||||
        $output .= "name: $dev_settings->{name} ";
 | 
					 | 
				
			||||||
        if (ref ($dev_settings->{value}) eq 'ARRAY' 
 | 
					 | 
				
			||||||
          || ref ($dev_settings->{value}) eq 'HASH'){
 | 
					 | 
				
			||||||
          $output .= 'N/A \n';
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          $output .= "value: $dev_settings->{value} \n";
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      $output .= '\n=== Abilities \n';
 | 
					        #settings
 | 
				
			||||||
      $i = 0;
 | 
					        $output .= '\n=== Settings \n';
 | 
				
			||||||
      for my $dev_settings ( @ { $devJson->{abilities} } ) {
 | 
					        my $i = 0;
 | 
				
			||||||
        $output .= "[".$i++."]id: $dev_settings->{id} \n";
 | 
					        for my $dev_settings ( @{ $devJson->{settings} } ) {
 | 
				
			||||||
        $output .= "name: $dev_settings->{name} ";
 | 
					            $output .= "[" . $i++ . "]id: $dev_settings->{id} \n";
 | 
				
			||||||
        if (ref ($dev_settings->{value}) eq 'ARRAY' 
 | 
					            $output .= "name: $dev_settings->{name} ";
 | 
				
			||||||
          || ref ($dev_settings->{value}) eq 'HASH'){
 | 
					            if (   ref( $dev_settings->{value} ) eq 'ARRAY'
 | 
				
			||||||
          $output .= 'N/A \n';
 | 
					                || ref( $dev_settings->{value} ) eq 'HASH' )
 | 
				
			||||||
        } else {
 | 
					            {
 | 
				
			||||||
          $output .= "value: $dev_settings->{value} \n";
 | 
					                $output .= 'N/A \n';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                $output .= "value: $dev_settings->{value} \n";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      $hash->{helper}{debug_device_output} = $output;
 | 
					        $output .= '\n=== Abilities \n';
 | 
				
			||||||
      asyncOutput($param->{cl},  $hash->{helper}{debug_device_output});
 | 
					        $i = 0;
 | 
				
			||||||
      return;
 | 
					
 | 
				
			||||||
 | 
					        for my $dev_settings ( @{ $devJson->{abilities} } ) {
 | 
				
			||||||
 | 
					            $output .= "[" . $i++ . "]id: $dev_settings->{id} \n";
 | 
				
			||||||
 | 
					            $output .= "name: $dev_settings->{name} ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (   ref( $dev_settings->{value} ) eq 'ARRAY'
 | 
				
			||||||
 | 
					                || ref( $dev_settings->{value} ) eq 'HASH' )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $output .= 'N/A \n';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                $output .= "value: $dev_settings->{value} \n";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $hash->{helper}{debug_device_output} = $output;
 | 
				
			||||||
 | 
					        asyncOutput( $param->{cl}, $hash->{helper}{debug_device_output} );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    readingsSingleUpdate( $hash, 'state', 'Connected', 1 )
 | 
					    readingsSingleUpdate( $hash, 'state', 'Connected', 1 )
 | 
				
			||||||
      if ( defined( $hash->{helper}{locations_id} ) );
 | 
					      if ( defined( $hash->{helper}{locations_id} ) );
 | 
				
			||||||
@@ -796,16 +810,20 @@ sub ResponseProcessing {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # print Dumper $decode_json;
 | 
					    # print Dumper $decode_json;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( defined( $decode_json->{data} ) && $decode_json->{data} 
 | 
					    if (   defined( $decode_json->{data} )
 | 
				
			||||||
        && ref($decode_json->{data}) eq 'HASH'
 | 
					        && $decode_json->{data}
 | 
				
			||||||
        && !defined( $hash->{helper}->{user_id})) {
 | 
					        && ref( $decode_json->{data} ) eq 'HASH'
 | 
				
			||||||
 | 
					        && !defined( $hash->{helper}->{user_id} ) )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $hash->{helper}{session_id}     = $decode_json->{data}{id};
 | 
					        $hash->{helper}{session_id} = $decode_json->{data}{id};
 | 
				
			||||||
        $hash->{helper}{user_id}        = $decode_json->{data}{attributes}->{user_id};
 | 
					        $hash->{helper}{user_id} = $decode_json->{data}{attributes}->{user_id};
 | 
				
			||||||
        $hash->{helper}{refresh_token}  = $decode_json->{data}{attributes}->{refresh_token};
 | 
					        $hash->{helper}{refresh_token} =
 | 
				
			||||||
        $hash->{helper}{token_expired}  = gettimeofday() + $decode_json->{data}{attributes}->{expires_in};
 | 
					          $decode_json->{data}{attributes}->{refresh_token};
 | 
				
			||||||
 | 
					        $hash->{helper}{token_expired} =
 | 
				
			||||||
 | 
					          gettimeofday() + $decode_json->{data}{attributes}->{expires_in};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        InternalTimer($hash->{helper}{token_expired},
 | 
					        InternalTimer( $hash->{helper}{token_expired},
 | 
				
			||||||
            "FHEM::GardenaSmartBridge::getToken", $hash );
 | 
					            "FHEM::GardenaSmartBridge::getToken", $hash );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Write( $hash, undef, undef, undef );
 | 
					        Write( $hash, undef, undef, undef );
 | 
				
			||||||
@@ -838,27 +856,76 @@ sub ResponseProcessing {
 | 
				
			|||||||
        && ref( $decode_json->{devices} ) eq 'ARRAY'
 | 
					        && ref( $decode_json->{devices} ) eq 'ARRAY'
 | 
				
			||||||
        && scalar( @{ $decode_json->{devices} } ) > 0 )
 | 
					        && scalar( @{ $decode_json->{devices} } ) > 0 )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        my @buffer = split( '"devices":\[', $json );
 | 
					        my @buffer = split( '"devices":\[', $json );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        my ( $json, $tail ) = ParseJSON( $hash, $buffer[1] );
 | 
					        require SubProcess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while ($json) {
 | 
					        my $subprocess =
 | 
				
			||||||
 | 
					          SubProcess->new( { onRun => \&ResponseSubprocessing } );
 | 
				
			||||||
 | 
					        $subprocess->{buffer} = $buffer[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Log3 $name, 5,
 | 
					        my $pid = $subprocess->run();
 | 
				
			||||||
                "GardenaSmartBridge ($name) - Decoding JSON message. Length: "
 | 
					 | 
				
			||||||
              . length($json)
 | 
					 | 
				
			||||||
              . " Content: "
 | 
					 | 
				
			||||||
              . $json;
 | 
					 | 
				
			||||||
            Log3 $name, 5,
 | 
					 | 
				
			||||||
                "GardenaSmartBridge ($name) - Vor Sub: Laenge JSON: "
 | 
					 | 
				
			||||||
              . length($json)
 | 
					 | 
				
			||||||
              . " Content: "
 | 
					 | 
				
			||||||
              . $json
 | 
					 | 
				
			||||||
              . " Tail: "
 | 
					 | 
				
			||||||
              . $tail;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ( defined($tail) and $tail ) {
 | 
					        if ( !defined($pid) ) {
 | 
				
			||||||
 | 
					            Log3( $name, 1,
 | 
				
			||||||
 | 
					qq{GardenaSmartBridge ($name) - Cannot execute parse json asynchronously}
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            CleanSubprocess($hash);
 | 
				
			||||||
 | 
					            readingsSingleUpdate( $hash, 'state',
 | 
				
			||||||
 | 
					                'Cannot execute parse json asynchronously', 1 );
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Log3( $name, 4,
 | 
				
			||||||
 | 
					qq{GardenaSmartBridge ($name) - execute parse json asynchronously (PID="$pid")}
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $hash->{".fhem"}{subprocess} = $subprocess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        InternalTimer( gettimeofday() + 1,
 | 
				
			||||||
 | 
					            "FHEM::GardenaSmartBridge::PollChild", $hash );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Log3 $name, 3, "GardenaSmartBridge ($name) - no Match for processing data";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub PollChild {
 | 
				
			||||||
 | 
					    my $hash = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $name = $hash->{NAME};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ( defined( $hash->{".fhem"}{subprocess} ) ) {
 | 
				
			||||||
 | 
					        my $subprocess = $hash->{".fhem"}{subprocess};
 | 
				
			||||||
 | 
					        my $response   = $subprocess->readFromChild();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( !defined($response) ) {
 | 
				
			||||||
 | 
					            Log3( $name, 5,
 | 
				
			||||||
 | 
					qq{GardenaSmartBridge ($name) - still waiting ($subprocess->{lasterror}).}
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            InternalTimer( gettimeofday() + 1,
 | 
				
			||||||
 | 
					                "FHEM::GardenaSmartBridge::PollChild", $hash );
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            Log3( $name, 4,
 | 
				
			||||||
 | 
					qq{GardenaSmartBridge ($name) - got result from asynchronous parsing}
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            my $decode_json;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $subprocess->wait();
 | 
				
			||||||
 | 
					            Log3( $name, 4,
 | 
				
			||||||
 | 
					                qq{GardenaSmartBridge ($name) - asynchronous finished.} );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            CleanSubprocess($hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for my $json ( @{$response} ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                #################
 | 
				
			||||||
                $decode_json = eval { decode_json($json) };
 | 
					                $decode_json = eval { decode_json($json) };
 | 
				
			||||||
                if ($@) {
 | 
					                if ($@) {
 | 
				
			||||||
                    Log3 $name, 5,
 | 
					                    Log3 $name, 5,
 | 
				
			||||||
@@ -871,26 +938,76 @@ sub ResponseProcessing {
 | 
				
			|||||||
                  if ( defined( $decode_json->{category} )
 | 
					                  if ( defined( $decode_json->{category} )
 | 
				
			||||||
                    && $decode_json->{category} eq 'gateway' );
 | 
					                    && $decode_json->{category} eq 'gateway' );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ( $json, $tail ) = ParseJSON( $hash, $tail );
 | 
					# ResponseSubprocessin muss in eine async ausgelagert werden
 | 
				
			||||||
 | 
					######################################
 | 
				
			||||||
 | 
					# Begin Childprozess
 | 
				
			||||||
 | 
					######################################
 | 
				
			||||||
 | 
					sub ResponseSubprocessing {
 | 
				
			||||||
 | 
					    my $subprocess = shift;
 | 
				
			||||||
 | 
					    my $buffer     = $subprocess->{buffer};
 | 
				
			||||||
 | 
					    my $response   = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Log3 $name, 5,
 | 
					    my ( $json, $tail ) = ParseJSON($buffer);
 | 
				
			||||||
                "GardenaSmartBridge ($name) - Nach Sub: Laenge JSON: "
 | 
					
 | 
				
			||||||
              . length($json)
 | 
					    while ($json) {
 | 
				
			||||||
              . " Content: "
 | 
					        if ( defined($tail) and $tail ) {
 | 
				
			||||||
              . $json
 | 
					            push @{$response}, $json;
 | 
				
			||||||
              . " Tail: "
 | 
					 | 
				
			||||||
              . $tail;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return;
 | 
					        ( $json, $tail ) = ParseJSON($tail);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Log3 $name, 3, "GardenaSmartBridge ($name) - no Match for processing data";
 | 
					    $subprocess->writeToParent($response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub ParseJSON {
 | 
				
			||||||
 | 
					    my $buffer = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $open  = 0;
 | 
				
			||||||
 | 
					    my $close = 0;
 | 
				
			||||||
 | 
					    my $msg   = '';
 | 
				
			||||||
 | 
					    my $tail  = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($buffer) {
 | 
				
			||||||
 | 
					        for my $c ( split //, $buffer ) {
 | 
				
			||||||
 | 
					            if ( $open == $close && $open > 0 ) {
 | 
				
			||||||
 | 
					                $tail .= $c;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ( $c eq '{' ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $open++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                elsif ( $c eq '}' ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $close++;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $msg .= $c;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( $open != $close ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $tail = $msg;
 | 
				
			||||||
 | 
					            $msg  = '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ( $msg, $tail );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					######################################
 | 
				
			||||||
 | 
					# End Childprozess
 | 
				
			||||||
 | 
					######################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub WriteReadings {
 | 
					sub WriteReadings {
 | 
				
			||||||
    my $hash        = shift;
 | 
					    my $hash        = shift;
 | 
				
			||||||
    my $decode_json = shift;
 | 
					    my $decode_json = shift;
 | 
				
			||||||
@@ -940,8 +1057,9 @@ sub WriteReadings {
 | 
				
			|||||||
                        $decode_json->{abilities}[0]{properties}[$properties]
 | 
					                        $decode_json->{abilities}[0]{properties}[$properties]
 | 
				
			||||||
                          {name} . '-' . $t,
 | 
					                          {name} . '-' . $t,
 | 
				
			||||||
                        $v
 | 
					                        $v
 | 
				
			||||||
                      )                     
 | 
					                      )
 | 
				
			||||||
                      if ($decode_json->{abilities}[0]{properties}[$properties]{name} !~ /ethernet_status|wifi_status/ );
 | 
					                      if ( $decode_json->{abilities}[0]{properties}[$properties]
 | 
				
			||||||
 | 
					                        {name} !~ /ethernet_status|wifi_status/ );
 | 
				
			||||||
                    if (
 | 
					                    if (
 | 
				
			||||||
                        (
 | 
					                        (
 | 
				
			||||||
                            $decode_json->{abilities}[0]{properties}
 | 
					                            $decode_json->{abilities}[0]{properties}
 | 
				
			||||||
@@ -968,8 +1086,8 @@ sub WriteReadings {
 | 
				
			|||||||
                            [$properties]{name} eq 'wifi_status' )
 | 
					                            [$properties]{name} eq 'wifi_status' )
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            readingsBulkUpdateIfChanged( $hash,
 | 
					                            readingsBulkUpdateIfChanged( $hash,
 | 
				
			||||||
                              'wifi_status-ssid', $v->{ssid} )
 | 
					                                'wifi_status-ssid', $v->{ssid} )
 | 
				
			||||||
                              if (ref($v->{ssid}) ne 'HASH');
 | 
					                              if ( ref( $v->{ssid} ) ne 'HASH' );
 | 
				
			||||||
                            readingsBulkUpdateIfChanged( $hash,
 | 
					                            readingsBulkUpdateIfChanged( $hash,
 | 
				
			||||||
                                'wifi_status-mac', $v->{mac} );
 | 
					                                'wifi_status-mac', $v->{mac} );
 | 
				
			||||||
                            readingsBulkUpdateIfChanged( $hash,
 | 
					                            readingsBulkUpdateIfChanged( $hash,
 | 
				
			||||||
@@ -1002,25 +1120,23 @@ sub getDevices {
 | 
				
			|||||||
    my $hash = shift;
 | 
					    my $hash = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name = $hash->{NAME};
 | 
					    my $name = $hash->{NAME};
 | 
				
			||||||
    RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
					    RemoveInternalTimer( $hash, "FHEM::GardenaSmartBridge::getDevices" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( not IsDisabled($name) ) {
 | 
					    if ( not IsDisabled($name) ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        delete $hash->{helper}{deviceList};
 | 
					        delete $hash->{helper}{deviceList};
 | 
				
			||||||
        my @list;
 | 
					        my @list;
 | 
				
			||||||
        @list = devspec2array('TYPE=GardenaSmartDevice');
 | 
					        @list = devspec2array('TYPE=GardenaSmartDevice');
 | 
				
			||||||
        for my $gardenaDev (@list){
 | 
					        for my $gardenaDev (@list) {
 | 
				
			||||||
          push( @{ $hash->{helper}{deviceList} }, $gardenaDev );
 | 
					            push( @{ $hash->{helper}{deviceList} }, $gardenaDev );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if ( AttrVal( $name, 'gardenaAccountEmail', 'none' ) ne 'none' 
 | 
					        if ( AttrVal( $name, 'gardenaAccountEmail', 'none' ) ne 'none'
 | 
				
			||||||
          && (
 | 
					            && ( defined( ReadPassword( $hash, $name ) ) ) )
 | 
				
			||||||
            defined( ReadPassword( $hash, $name ) ) 
 | 
					 | 
				
			||||||
          )) 
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          Write( $hash, undef, undef, undef );
 | 
					            Write( $hash, undef, undef, undef );
 | 
				
			||||||
          Log3 $name, 4,
 | 
					            Log3 $name, 4,
 | 
				
			||||||
            "GardenaSmartBridge ($name) - fetch device list and device states";
 | 
					"GardenaSmartBridge ($name) - fetch device list and device states";
 | 
				
			||||||
        } # fi gardenaAccountEmail
 | 
					        }    # fi gardenaAccountEmail
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        readingsSingleUpdate( $hash, 'state', 'disabled', 1 );
 | 
					        readingsSingleUpdate( $hash, 'state', 'disabled', 1 );
 | 
				
			||||||
@@ -1044,27 +1160,29 @@ sub getToken {
 | 
				
			|||||||
    readingsSingleUpdate( $hash, 'state', 'get token', 1 );
 | 
					    readingsSingleUpdate( $hash, 'state', 'get token', 1 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delete $hash->{helper}{session_id}
 | 
					    delete $hash->{helper}{session_id}
 | 
				
			||||||
      if ( defined( $hash->{helper}{session_id} )
 | 
					      if ( exists( $hash->{helper}{session_id} ) );
 | 
				
			||||||
        && $hash->{helper}{session_id} );
 | 
					 | 
				
			||||||
    delete $hash->{helper}{user_id}
 | 
					    delete $hash->{helper}{user_id}
 | 
				
			||||||
      if ( defined( $hash->{helper}{user_id} ) && $hash->{helper}{user_id} );
 | 
					      if ( exists( $hash->{helper}{user_id} ) );
 | 
				
			||||||
    delete $hash->{helper}{locations_id}
 | 
					    delete $hash->{helper}{locations_id}
 | 
				
			||||||
      if ( defined( $hash->{helper}{locations_id} )
 | 
					      if ( exists( $hash->{helper}{locations_id} ) );
 | 
				
			||||||
        && $hash->{helper}{locations_id} );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Write(
 | 
					    Write(
 | 
				
			||||||
         $hash,
 | 
					        $hash,
 | 
				
			||||||
         '"data": {"type":"token", "attributes":{"username": "' 
 | 
					        '"data": {"type":"token", "attributes":{"username": "'
 | 
				
			||||||
            . AttrVal( $name, 'gardenaAccountEmail', 'none' )      
 | 
					          . AttrVal( $name, 'gardenaAccountEmail', 'none' )
 | 
				
			||||||
            . '","password": "'
 | 
					          . '","password": "'
 | 
				
			||||||
            . ReadPassword( $hash, $name ) . '", "client_id":"smartgarden-jwt-client"}}',
 | 
					          . ReadPassword( $hash, $name )
 | 
				
			||||||
         undef,
 | 
					          . '", "client_id":"smartgarden-jwt-client"}}',
 | 
				
			||||||
         undef
 | 
					        undef,
 | 
				
			||||||
     );
 | 
					        undef
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Log3 $name, 4, '"data": {"type":"token", "attributes":{"username": "'     
 | 
					    Log3 $name, 4,
 | 
				
			||||||
               .AttrVal( $name, 'gardenaAccountEmail', 'none' ) . '","password": "'
 | 
					        '"data": {"type":"token", "attributes":{"username": "'
 | 
				
			||||||
               .ReadPassword( $hash, $name ) . '", "client_id":"smartgarden-jwt-client"}}';
 | 
					      . AttrVal( $name, 'gardenaAccountEmail', 'none' )
 | 
				
			||||||
 | 
					      . '","password": "'
 | 
				
			||||||
 | 
					      . ReadPassword( $hash, $name )
 | 
				
			||||||
 | 
					      . '", "client_id":"smartgarden-jwt-client"}}';
 | 
				
			||||||
    Log3 $name, 3,
 | 
					    Log3 $name, 3,
 | 
				
			||||||
"GardenaSmartBridge ($name) - send credentials to fetch Token and locationId";
 | 
					"GardenaSmartBridge ($name) - send credentials to fetch Token and locationId";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1115,7 +1233,7 @@ sub ReadPassword {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Log3 $name, 3,
 | 
					        Log3 $name, 3,
 | 
				
			||||||
"GardenaSmartBridge ($name) - unable to read password from file: $err";
 | 
					"GardenaSmartBridge ($name) - unable to read password from file: $err";
 | 
				
			||||||
        return undef;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1141,7 +1259,7 @@ sub ReadPassword {
 | 
				
			|||||||
    else {
 | 
					    else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Log3 $name, 3, "GardenaSmartBridge ($name) - No password in file";
 | 
					        Log3 $name, 3, "GardenaSmartBridge ($name) - No password in file";
 | 
				
			||||||
        return undef;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
@@ -1159,59 +1277,6 @@ sub Rename {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub ParseJSON {
 | 
					 | 
				
			||||||
    my $hash   = shift;
 | 
					 | 
				
			||||||
    my $buffer = shift;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    my $name  = $hash->{NAME};
 | 
					 | 
				
			||||||
    my $open  = 0;
 | 
					 | 
				
			||||||
    my $close = 0;
 | 
					 | 
				
			||||||
    my $msg   = '';
 | 
					 | 
				
			||||||
    my $tail  = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ($buffer) {
 | 
					 | 
				
			||||||
        for my $c ( split //, $buffer ) {
 | 
					 | 
				
			||||||
            if ( $open == $close && $open > 0 ) {
 | 
					 | 
				
			||||||
                $tail .= $c;
 | 
					 | 
				
			||||||
                Log3 $name, 5,
 | 
					 | 
				
			||||||
                  "GardenaSmartBridge ($name) - $open == $close and $open > 0";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            elsif ( ( $open == $close ) && ( $c ne '{' ) ) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Log3 $name, 5,
 | 
					 | 
				
			||||||
"GardenaSmartBridge ($name) - Garbage character before message: "
 | 
					 | 
				
			||||||
                  . $c;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if ( $c eq '{' ) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    $open++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                elsif ( $c eq '}' ) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    $close++;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $msg .= $c;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ( $open != $close ) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $tail = $msg;
 | 
					 | 
				
			||||||
            $msg  = '';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Log3 $name, 5,
 | 
					 | 
				
			||||||
      "GardenaSmartBridge ($name) - return msg: $msg and tail: $tail";
 | 
					 | 
				
			||||||
    return ( $msg, $tail );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
sub createHttpValueStrings {
 | 
					sub createHttpValueStrings {
 | 
				
			||||||
    my ( $hash, $payload, $deviceId, $abilities, $service_id ) = @_;
 | 
					    my ( $hash, $payload, $deviceId, $abilities, $service_id ) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1220,17 +1285,17 @@ sub createHttpValueStrings {
 | 
				
			|||||||
    my $uri        = '';
 | 
					    my $uri        = '';
 | 
				
			||||||
    my $method     = 'POST';
 | 
					    my $method     = 'POST';
 | 
				
			||||||
    $header .= "\r\nAuthorization: Bearer $session_id"
 | 
					    $header .= "\r\nAuthorization: Bearer $session_id"
 | 
				
			||||||
      if ( defined($hash->{helper}{session_id}) );
 | 
					      if ( defined( $hash->{helper}{session_id} ) );
 | 
				
			||||||
    $header .= "\r\nAuthorization-Provider: husqvarna"
 | 
					    $header .= "\r\nAuthorization-Provider: husqvarna"
 | 
				
			||||||
      if ( defined($hash->{helper}{session_id}) );
 | 
					      if ( defined( $hash->{helper}{session_id} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #  $header .= "\r\nx-api-key: $session_id"
 | 
					    #  $header .= "\r\nx-api-key: $session_id"
 | 
				
			||||||
    #    if ( defined( $hash->{helper}{session_id} ) );
 | 
					    #    if ( defined( $hash->{helper}{session_id} ) );
 | 
				
			||||||
    $payload = '{' . $payload . '}' if ( defined($payload) );
 | 
					    $payload = '{' . $payload . '}' if ( defined($payload) );
 | 
				
			||||||
    $payload = '{}' if ( !defined($payload) );
 | 
					    $payload = '{}'                 if ( !defined($payload) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( $payload eq '{}' ) {
 | 
					    if ( $payload eq '{}' ) {
 | 
				
			||||||
        $method = 'GET' if (defined( $hash->{helper}{session_id} ) );
 | 
					        $method  = 'GET' if ( defined( $hash->{helper}{session_id} ) );
 | 
				
			||||||
        $payload = '';
 | 
					        $payload = '';
 | 
				
			||||||
        $uri .= '/locations?locatioId=null&user_id=' . $hash->{helper}{user_id}
 | 
					        $uri .= '/locations?locatioId=null&user_id=' . $hash->{helper}{user_id}
 | 
				
			||||||
          if ( exists( $hash->{helper}{user_id} )
 | 
					          if ( exists( $hash->{helper}{user_id} )
 | 
				
			||||||
@@ -1243,8 +1308,10 @@ sub createHttpValueStrings {
 | 
				
			|||||||
            && defined( $hash->{helper}{locations_id} ) );
 | 
					            && defined( $hash->{helper}{locations_id} ) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $uri = '/devices/'.InternalVal($hash->{helper}{debug_device}, 'DEVICEID', 0 ) if ( defined ($hash->{helper}{debug_device})  
 | 
					    $uri =
 | 
				
			||||||
                                                                                       && defined( $hash->{helper}{locations_id} ) );
 | 
					      '/devices/' . InternalVal( $hash->{helper}{debug_device}, 'DEVICEID', 0 )
 | 
				
			||||||
 | 
					      if ( defined( $hash->{helper}{debug_device} )
 | 
				
			||||||
 | 
					        && defined( $hash->{helper}{locations_id} ) );
 | 
				
			||||||
    $uri = '/auth/token' if ( !defined( $hash->{helper}{session_id} ) );
 | 
					    $uri = '/auth/token' if ( !defined( $hash->{helper}{session_id} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( defined( $hash->{helper}{locations_id} ) ) {
 | 
					    if ( defined( $hash->{helper}{locations_id} ) ) {
 | 
				
			||||||
@@ -1252,17 +1319,13 @@ sub createHttpValueStrings {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $method = 'PUT';
 | 
					            $method = 'PUT';
 | 
				
			||||||
            my $dhash = $modules{GardenaSmartDevice}{defptr}{$deviceId};
 | 
					            my $dhash = $modules{GardenaSmartDevice}{defptr}{$deviceId};
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            $uri .=
 | 
					            $uri .= '/devices/' . $deviceId . '/settings/' . $service_id
 | 
				
			||||||
                '/devices/'
 | 
					 | 
				
			||||||
              . $deviceId
 | 
					 | 
				
			||||||
              . '/settings/'
 | 
					 | 
				
			||||||
              . $service_id
 | 
					 | 
				
			||||||
              if ( defined($abilities)
 | 
					              if ( defined($abilities)
 | 
				
			||||||
                && defined($payload)
 | 
					                && defined($payload)
 | 
				
			||||||
                && $abilities =~ /.*_settings/ );
 | 
					                && $abilities =~ /.*_settings/ );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } # park until next schedules or override
 | 
					        }    # park until next schedules or override
 | 
				
			||||||
        elsif (defined($abilities)
 | 
					        elsif (defined($abilities)
 | 
				
			||||||
            && defined($payload)
 | 
					            && defined($payload)
 | 
				
			||||||
            && $abilities eq 'mower_timer' )
 | 
					            && $abilities eq 'mower_timer' )
 | 
				
			||||||
@@ -1285,7 +1348,7 @@ sub createHttpValueStrings {
 | 
				
			|||||||
            my $valve_id;
 | 
					            my $valve_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ( $payload =~ m#watering_timer_(\d)# ) {
 | 
					            if ( $payload =~ m#watering_timer_(\d)# ) {
 | 
				
			||||||
                $method = 'PUT';
 | 
					                $method   = 'PUT';
 | 
				
			||||||
                $valve_id = $1;
 | 
					                $valve_id = $1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $uri .=
 | 
					            $uri .=
 | 
				
			||||||
@@ -1293,7 +1356,11 @@ sub createHttpValueStrings {
 | 
				
			|||||||
              . $deviceId
 | 
					              . $deviceId
 | 
				
			||||||
              . '/abilities/'
 | 
					              . '/abilities/'
 | 
				
			||||||
              . $abilities
 | 
					              . $abilities
 | 
				
			||||||
              . ( defined($valve_id) ? '/properties/watering_timer_'. $valve_id : '/command')
 | 
					              . (
 | 
				
			||||||
 | 
					                defined($valve_id)
 | 
				
			||||||
 | 
					                ? '/properties/watering_timer_' . $valve_id
 | 
				
			||||||
 | 
					                : '/command'
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elsif (defined($abilities)
 | 
					        elsif (defined($abilities)
 | 
				
			||||||
@@ -1507,9 +1574,9 @@ sub DeletePassword {
 | 
				
			|||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "release_status": "stable",
 | 
					  "release_status": "stable",
 | 
				
			||||||
  "license": "GPL_2",
 | 
					  "license": "GPL_2",
 | 
				
			||||||
  "version": "v2.4.6",
 | 
					  "version": "v2.4.7",
 | 
				
			||||||
  "author": [
 | 
					  "author": [
 | 
				
			||||||
    "Marko Oldenburg <leongaultier@gmail.com>"
 | 
					    "Marko Oldenburg <fhemdevelopment@cooltux.net>"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "x_fhem_maintainer": [
 | 
					  "x_fhem_maintainer": [
 | 
				
			||||||
    "CoolTux"
 | 
					    "CoolTux"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Developed with Kate
 | 
					# Developed with VSCodium and richterger perl plugin.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  (c) 2017-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
 | 
					#  (c) 2017-2022 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
 | 
				
			||||||
#  All rights reserved
 | 
					#  All rights reserved
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#   Special thanks goes to comitters:
 | 
					#   Special thanks goes to comitters:
 | 
				
			||||||
@@ -164,7 +164,7 @@ BEGIN {
 | 
				
			|||||||
#-- Export to main context with different name
 | 
					#-- Export to main context with different name
 | 
				
			||||||
GP_Export(
 | 
					GP_Export(
 | 
				
			||||||
    qw(
 | 
					    qw(
 | 
				
			||||||
        Initialize
 | 
					      Initialize
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -204,22 +204,23 @@ sub Define {
 | 
				
			|||||||
    my $deviceId = $aArg->[2];
 | 
					    my $deviceId = $aArg->[2];
 | 
				
			||||||
    my $category = $aArg->[3];
 | 
					    my $category = $aArg->[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $hash->{DEVICEID}                           = $deviceId;
 | 
					    $hash->{DEVICEID}                = $deviceId;
 | 
				
			||||||
    $hash->{VERSION}                            = version->parse($VERSION)->normal;
 | 
					    $hash->{VERSION}                 = version->parse($VERSION)->normal;
 | 
				
			||||||
    $hash->{helper}{STARTINGPOINTID}            = '';
 | 
					    $hash->{helper}{STARTINGPOINTID} = '';
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_id} = '';
 | 
				
			||||||
    $hash->{helper}{eco_mode_id}                = '';
 | 
					    $hash->{helper}{eco_mode_id}               = '';
 | 
				
			||||||
    $hash->{helper}{button_config_time_id}      = '';
 | 
					    $hash->{helper}{button_config_time_id}     = '';
 | 
				
			||||||
    $hash->{helper}{winter_mode_id}             = '';
 | 
					    $hash->{helper}{winter_mode_id}            = '';
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    $hash->{helper}{_id}             = '';
 | 
					    $hash->{helper}{_id} = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # IrrigationControl valve control max 6
 | 
					    # IrrigationControl valve control max 6
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_1_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_1_id} = '';
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_2_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_2_id} = '';
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_3_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_3_id} = '';
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_4_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_4_id} = '';
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_5_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_5_id} = '';
 | 
				
			||||||
    $hash->{helper}{schedules_paused_until_6_id}  = '';
 | 
					    $hash->{helper}{schedules_paused_until_6_id} = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CommandAttr( undef,
 | 
					    CommandAttr( undef,
 | 
				
			||||||
        "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" )
 | 
					        "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" )
 | 
				
			||||||
@@ -283,16 +284,18 @@ sub Attr {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub Set {
 | 
					sub Set {
 | 
				
			||||||
    my $hash                = shift // return;
 | 
					    my $hash = shift // return;
 | 
				
			||||||
    my $aArg                = shift // return;
 | 
					    my $aArg = shift // return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name                = shift @$aArg;
 | 
					    my $name = shift @$aArg;
 | 
				
			||||||
    my $cmd                 = shift @$aArg // return qq{"set $name" needs at least one argument};
 | 
					    my $cmd  = shift @$aArg
 | 
				
			||||||
 | 
					      // return qq{"set $name" needs at least one argument};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $payload;
 | 
					    my $payload;
 | 
				
			||||||
    my $abilities;
 | 
					    my $abilities;
 | 
				
			||||||
    my $service_id;
 | 
					    my $service_id;
 | 
				
			||||||
    my $mainboard_version   = ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 );
 | 
					    my $mainboard_version =
 | 
				
			||||||
 | 
					      ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #set default abilitie ... overwrite in cmd to change
 | 
					    #set default abilitie ... overwrite in cmd to change
 | 
				
			||||||
    $abilities = 'mower'
 | 
					    $abilities = 'mower'
 | 
				
			||||||
@@ -305,51 +308,62 @@ sub Set {
 | 
				
			|||||||
    $abilities = 'manual_watering'
 | 
					    $abilities = 'manual_watering'
 | 
				
			||||||
      if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' );
 | 
					      if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ### mower  
 | 
					    ### mower
 | 
				
			||||||
    # service_id (eco, parkuntilfurhternotice, startpoints)
 | 
					    # service_id (eco, parkuntilfurhternotice, startpoints)
 | 
				
			||||||
    if ( lc $cmd eq 'parkuntilfurthernotice' ) {
 | 
					    if ( lc $cmd eq 'parkuntilfurthernotice' ) {
 | 
				
			||||||
        $payload = '"name":"park_until_further_notice"';
 | 
					        $payload = '"name":"park_until_further_notice"';
 | 
				
			||||||
        if ( $mainboard_version > 10.30 ) {
 | 
					        if ( $mainboard_version > 10.30 ) {
 | 
				
			||||||
          $payload = ' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"'.$hash->{DEVICEID}.'"}';
 | 
					            $payload =
 | 
				
			||||||
          $abilities = 'mower_settings'  ;
 | 
					' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"'
 | 
				
			||||||
          $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
					              . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
 | 
					            $abilities  = 'mower_settings';
 | 
				
			||||||
 | 
					            $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'parkuntilnexttimer' ) { 
 | 
					    elsif ( lc $cmd eq 'parkuntilnexttimer' ) {
 | 
				
			||||||
        $payload = '"name":"park_until_next_timer"';
 | 
					        $payload = '"name":"park_until_next_timer"';
 | 
				
			||||||
        if ( $mainboard_version > 10.30 ){
 | 
					        if ( $mainboard_version > 10.30 ) {
 | 
				
			||||||
          $payload = '"properties":{"name":"mower_timer","value":0}' ;
 | 
					            $payload   = '"properties":{"name":"mower_timer","value":0}';
 | 
				
			||||||
          $abilities = 'mower_timer'; 
 | 
					            $abilities = 'mower_timer';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'startresumeschedule' ) {
 | 
					    elsif ( lc $cmd eq 'startresumeschedule' ) {
 | 
				
			||||||
        $payload = '"name":"start_resume_schedule"';
 | 
					        $payload = '"name":"start_resume_schedule"';
 | 
				
			||||||
        if ( $mainboard_version > 10.30 ) {
 | 
					        if ( $mainboard_version > 10.30 ) {
 | 
				
			||||||
          $payload = ' "settings":{"name":"schedules_paused_until","value":"","device":"'.$hash->{DEVICEID}.'"}';
 | 
					            $payload =
 | 
				
			||||||
          $abilities = 'mower_settings'  ;
 | 
					' "settings":{"name":"schedules_paused_until","value":"","device":"'
 | 
				
			||||||
          $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
					              . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
 | 
					            $abilities  = 'mower_settings';
 | 
				
			||||||
 | 
					            $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'startoverridetimer' ) {
 | 
					    elsif ( lc $cmd eq 'startoverridetimer' ) {
 | 
				
			||||||
        $payload = '"name":"start_override_timer","parameters":{"duration":'
 | 
					        $payload = '"name":"start_override_timer","parameters":{"duration":'
 | 
				
			||||||
          . $aArg->[0] * 60 . '}';
 | 
					          . $aArg->[0] * 60 . '}';
 | 
				
			||||||
        if ( $mainboard_version > 10.30 ){
 | 
					        if ( $mainboard_version > 10.30 ) {
 | 
				
			||||||
          $payload = '"properties":{"name":"mower_timer","value":'.$aArg->[0] * 60 .'}';
 | 
					            $payload = '"properties":{"name":"mower_timer","value":'
 | 
				
			||||||
          $abilities = 'mower_timer'; 
 | 
					              . $aArg->[0] * 60 . '}';
 | 
				
			||||||
 | 
					            $abilities = 'mower_timer';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'startpoint' ) {
 | 
					    elsif ( lc $cmd eq 'startpoint' ) {
 | 
				
			||||||
        my $err;
 | 
					        my $err;
 | 
				
			||||||
        ( $err, $payload, $abilities ) = SetPredefinedStartPoints( $hash, $aArg );
 | 
					        ( $err, $payload, $abilities ) =
 | 
				
			||||||
 | 
					          SetPredefinedStartPoints( $hash, $aArg );
 | 
				
			||||||
        $service_id = $hash->{helper}{STARTINGPOINTID};
 | 
					        $service_id = $hash->{helper}{STARTINGPOINTID};
 | 
				
			||||||
        return $err if ( defined($err) );
 | 
					        return $err if ( defined($err) );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'eco' ) {
 | 
					    elsif ( lc $cmd eq 'eco' ) {
 | 
				
			||||||
        $payload = '"settings": {"name": "eco_mode", "value": '.$aArg->[0].', "device": "'.$hash->{DEVICEID}.'"}';
 | 
					        $payload =
 | 
				
			||||||
        $abilities = 'mower_settings'  if ( $mainboard_version > 10.30 );
 | 
					            '"settings": {"name": "eco_mode", "value": '
 | 
				
			||||||
 | 
					          . $aArg->[0]
 | 
				
			||||||
 | 
					          . ', "device": "'
 | 
				
			||||||
 | 
					          . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
 | 
					        $abilities  = 'mower_settings' if ( $mainboard_version > 10.30 );
 | 
				
			||||||
        $service_id = $hash->{helper}{eco_mode_id};
 | 
					        $service_id = $hash->{helper}{eco_mode_id};
 | 
				
			||||||
        #$abilities['service_id'] = $hash->{helper}{SCHEDULESID}  if ( $mainboard_version > 10.30 );
 | 
					
 | 
				
			||||||
 | 
					#$abilities['service_id'] = $hash->{helper}{SCHEDULESID}  if ( $mainboard_version > 10.30 );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ### electronic_pressure_pump
 | 
					    ### electronic_pressure_pump
 | 
				
			||||||
    elsif ( lc $cmd eq 'pumptimer' ) {
 | 
					    elsif ( lc $cmd eq 'pumptimer' ) {
 | 
				
			||||||
@@ -365,16 +379,15 @@ sub Set {
 | 
				
			|||||||
          . $aArg->[0] * 60
 | 
					          . $aArg->[0] * 60
 | 
				
			||||||
          . ',"valve_id":1}}';
 | 
					          . ',"valve_id":1}}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'manualbuttontime'){
 | 
					    elsif ( lc $cmd eq 'manualbuttontime' ) {
 | 
				
			||||||
      $service_id = $hash->{helper}{button_config_time_id};
 | 
					        $service_id = $hash->{helper}{button_config_time_id};
 | 
				
			||||||
      $payload=
 | 
					        $payload =
 | 
				
			||||||
        '"properties":{"name":"button_config_time",'
 | 
					            '"properties":{"name":"button_config_time",'
 | 
				
			||||||
        .'"value":'
 | 
					          . '"value":'
 | 
				
			||||||
        .  $aArg->[0] * 60
 | 
					          . $aArg->[0] * 60
 | 
				
			||||||
        . ',"timestamp":"2021-05-26T19:06:23.680Z"'
 | 
					          . ',"timestamp":"2021-05-26T19:06:23.680Z"'
 | 
				
			||||||
        . ',"at_bound":null,"unit":"seconds","ability":"'
 | 
					          . ',"at_bound":null,"unit":"seconds","ability":"'
 | 
				
			||||||
        . $service_id
 | 
					          . $service_id . '"}';
 | 
				
			||||||
        .'"}';
 | 
					 | 
				
			||||||
        $abilities = 'watering_button_config';
 | 
					        $abilities = 'watering_button_config';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( $cmd =~ m{\AcancelOverride}xms ) {
 | 
					    elsif ( $cmd =~ m{\AcancelOverride}xms ) {
 | 
				
			||||||
@@ -393,26 +406,40 @@ sub Set {
 | 
				
			|||||||
          . ',"valve_id":'
 | 
					          . ',"valve_id":'
 | 
				
			||||||
          . $valve_id . '}}';
 | 
					          . $valve_id . '}}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( $cmd =~ /.*Schedule/ ){
 | 
					    elsif ( $cmd =~ /.*Schedule/ ) {
 | 
				
			||||||
      my $duration = (( defined($aArg->[0]) ? ( ((Time::Piece->new)+(ONE_HOUR *  $aArg->[0]) - (Time::Piece->new)->tzoffset )->datetime ).'.000Z' : '2038-01-18T00:00:00.000Z'));
 | 
					        my $duration = (
 | 
				
			||||||
    
 | 
					            (
 | 
				
			||||||
      $abilities = 'wateringcomputer_settings';
 | 
					                defined( $aArg->[0] )
 | 
				
			||||||
      $service_id = $hash->{helper}->{'schedules_paused_until_id'};
 | 
					                ? (
 | 
				
			||||||
      $payload = '"settings":{"name":"schedules_paused_until"'
 | 
					                    (
 | 
				
			||||||
                  . ', "value":"'
 | 
					                        ( Time::Piece->new ) +
 | 
				
			||||||
                  . ($cmd eq 'resumeSchedule' ? '' : $duration )
 | 
					                          ( ONE_HOUR * $aArg->[0] ) -
 | 
				
			||||||
                  . '","device":"'
 | 
					                          ( Time::Piece->new )->tzoffset
 | 
				
			||||||
                  . $hash->{DEVICEID}
 | 
					                    )->datetime
 | 
				
			||||||
                  . '"}';
 | 
					                  )
 | 
				
			||||||
 | 
					                  . '.000Z'
 | 
				
			||||||
 | 
					                : '2038-01-18T00:00:00.000Z'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $abilities  = 'wateringcomputer_settings';
 | 
				
			||||||
 | 
					        $service_id = $hash->{helper}->{'schedules_paused_until_id'};
 | 
				
			||||||
 | 
					        $payload =
 | 
				
			||||||
 | 
					            '"settings":{"name":"schedules_paused_until"'
 | 
				
			||||||
 | 
					          . ', "value":"'
 | 
				
			||||||
 | 
					          . ( $cmd eq 'resumeSchedule' ? '' : $duration )
 | 
				
			||||||
 | 
					          . '","device":"'
 | 
				
			||||||
 | 
					          . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( lc $cmd eq 'on' || lc $cmd eq 'off' || lc $cmd eq 'on-for-timer' ) {
 | 
					    elsif ( lc $cmd eq 'on' || lc $cmd eq 'off' || lc $cmd eq 'on-for-timer' ) {
 | 
				
			||||||
        my $val = (
 | 
					        my $val = (
 | 
				
			||||||
            scalar(!@$aArg == 0) && ref($aArg) eq 'ARRAY'
 | 
					            scalar( !@$aArg == 0 ) && ref($aArg) eq 'ARRAY'
 | 
				
			||||||
            ? $aArg->[0] * 60
 | 
					            ? $aArg->[0] * 60
 | 
				
			||||||
            : lc $cmd
 | 
					            : lc $cmd
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $payload = '"properties":{"name":"power_timer", "value":"' . $val . '"}';
 | 
					        $payload =
 | 
				
			||||||
 | 
					          '"properties":{"name":"power_timer", "value":"' . $val . '"}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ### Watering ic24
 | 
					    ### Watering ic24
 | 
				
			||||||
    elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) {
 | 
					    elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) {
 | 
				
			||||||
@@ -430,34 +457,51 @@ sub Set {
 | 
				
			|||||||
          . ',"valve_id":'
 | 
					          . ',"valve_id":'
 | 
				
			||||||
          . $valve_id . '}}';
 | 
					          . $valve_id . '}}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( $cmd eq 'closeAllValves' ){
 | 
					    elsif ( $cmd eq 'closeAllValves' ) {
 | 
				
			||||||
      $payload = '"name":"close_all_valves","parameters":{}';
 | 
					        $payload = '"name":"close_all_valves","parameters":{}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    elsif ( $cmd =~ /.*ScheduleValve/ ){
 | 
					    elsif ( $cmd =~ /.*ScheduleValve/ ) {
 | 
				
			||||||
      my $valve_id = $aArg->[0];
 | 
					        my $valve_id = $aArg->[0];
 | 
				
			||||||
      my $duration = (( defined($aArg->[1]) ? ( ((Time::Piece->new)+(ONE_HOUR *  $aArg->[1]) - (Time::Piece->new)->tzoffset )->datetime ).'.000Z' : '2038-01-18T00:00:00.000Z'));
 | 
					        my $duration = (
 | 
				
			||||||
    
 | 
					            (
 | 
				
			||||||
      $abilities = 'irrigation_settings';
 | 
					                defined( $aArg->[1] )
 | 
				
			||||||
      $service_id = $hash->{helper}->{'schedules_paused_until_'.$valve_id.'_id'};
 | 
					                ? (
 | 
				
			||||||
      $payload = '"settings":{"name":"schedules_paused_until_'
 | 
					                    (
 | 
				
			||||||
                  . $valve_id
 | 
					                        ( Time::Piece->new ) +
 | 
				
			||||||
                  . '", "value":"'
 | 
					                          ( ONE_HOUR * $aArg->[1] ) -
 | 
				
			||||||
                  . ($cmd eq 'resumeScheduleValve' ? '' : $duration )
 | 
					                          ( Time::Piece->new )->tzoffset
 | 
				
			||||||
                  . '","device":"'
 | 
					                    )->datetime
 | 
				
			||||||
                  . $hash->{DEVICEID}
 | 
					                  )
 | 
				
			||||||
                  . '"}';
 | 
					                  . '.000Z'
 | 
				
			||||||
 | 
					                : '2038-01-18T00:00:00.000Z'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $abilities = 'irrigation_settings';
 | 
				
			||||||
 | 
					        $service_id =
 | 
				
			||||||
 | 
					          $hash->{helper}->{ 'schedules_paused_until_' . $valve_id . '_id' };
 | 
				
			||||||
 | 
					        $payload =
 | 
				
			||||||
 | 
					            '"settings":{"name":"schedules_paused_until_'
 | 
				
			||||||
 | 
					          . $valve_id
 | 
				
			||||||
 | 
					          . '", "value":"'
 | 
				
			||||||
 | 
					          . ( $cmd eq 'resumeScheduleValve' ? '' : $duration )
 | 
				
			||||||
 | 
					          . '","device":"'
 | 
				
			||||||
 | 
					          . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ### Sensors
 | 
					    ### Sensors
 | 
				
			||||||
    elsif ( lc $cmd eq 'refresh' ) {
 | 
					    elsif ( lc $cmd eq 'refresh' ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        my $sensname = $aArg->[0];
 | 
					        my $sensname = $aArg->[0];
 | 
				
			||||||
        if ( lc $sensname eq 'temperature' ) {
 | 
					        if ( lc $sensname eq 'temperature' ) {
 | 
				
			||||||
            if ( ReadingsVal( $name, 'device_info-category', 'sensor' ) eq 'sensor') {
 | 
					            if ( ReadingsVal( $name, 'device_info-category', 'sensor' ) eq
 | 
				
			||||||
              $payload   = '"name":"measure_ambient_temperature"';
 | 
					                'sensor' )
 | 
				
			||||||
              $abilities = 'ambient_temperature';
 | 
					            {
 | 
				
			||||||
            } else {
 | 
					                $payload   = '"name":"measure_ambient_temperature"';
 | 
				
			||||||
              $payload   = '"name":"measure_soil_temperature"';
 | 
					                $abilities = 'ambient_temperature';
 | 
				
			||||||
              $abilities = 'soil_temperature';
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                $payload   = '"name":"measure_soil_temperature"';
 | 
				
			||||||
 | 
					                $abilities = 'soil_temperature';
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elsif ( lc $sensname eq 'light' ) {
 | 
					        elsif ( lc $sensname eq 'light' ) {
 | 
				
			||||||
@@ -471,13 +515,13 @@ sub Set {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ## winter sleep
 | 
					    ## winter sleep
 | 
				
			||||||
    elsif ( lc $cmd eq 'winter_mode') {
 | 
					    elsif ( lc $cmd eq 'winter_mode' ) {
 | 
				
			||||||
        $payload = '"settings":{"name":"winter_mode","value":"'
 | 
					        $payload =
 | 
				
			||||||
        . $aArg->[0]
 | 
					            '"settings":{"name":"winter_mode","value":"'
 | 
				
			||||||
        .'","device":"'
 | 
					          . $aArg->[0]
 | 
				
			||||||
        . $hash->{DEVICEID}
 | 
					          . '","device":"'
 | 
				
			||||||
        .'"}';
 | 
					          . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
        $abilities = 'winter_settings';
 | 
					        $abilities  = 'winter_settings';
 | 
				
			||||||
        $service_id = $hash->{helper}->{'winter_mode_id'};
 | 
					        $service_id = $hash->{helper}->{'winter_mode_id'};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
@@ -488,7 +532,8 @@ sub Set {
 | 
				
			|||||||
'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint'
 | 
					'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint'
 | 
				
			||||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' );
 | 
					          if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $list .= 'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100'
 | 
					        $list .=
 | 
				
			||||||
 | 
					'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100'
 | 
				
			||||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' );
 | 
					          if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $list .=
 | 
					        $list .=
 | 
				
			||||||
@@ -497,13 +542,16 @@ sub Set {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $list .= 'refresh:temperature,humidity'
 | 
					        $list .= 'refresh:temperature,humidity'
 | 
				
			||||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' );
 | 
					          if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # add light for old sensors
 | 
					        # add light for old sensors
 | 
				
			||||||
        $list .= ',light'
 | 
					        $list .= ',light'
 | 
				
			||||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' 
 | 
					          if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor'
 | 
				
			||||||
            && ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor' );
 | 
					            && ReadingsVal( $name, 'device_info-category', 'unknown' ) eq
 | 
				
			||||||
 | 
					            'sensor' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720'
 | 
					        $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720'
 | 
				
			||||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' );
 | 
					          if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # all devices has abilitie to fall a sleep
 | 
					        # all devices has abilitie to fall a sleep
 | 
				
			||||||
        $list .= ' winter_mode:awake,hibernate';
 | 
					        $list .= ' winter_mode:awake,hibernate';
 | 
				
			||||||
        return "Unknown argument $cmd, choose one of $list";
 | 
					        return "Unknown argument $cmd, choose one of $list";
 | 
				
			||||||
@@ -584,25 +632,30 @@ sub WriteReadings {
 | 
				
			|||||||
            for my $propertie (
 | 
					            for my $propertie (
 | 
				
			||||||
                @{ $decode_json->{abilities}[$abilities]{properties} } )
 | 
					                @{ $decode_json->{abilities}[$abilities]{properties} } )
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              if (   exists($decode_json->{abilities}[$abilities]{name})
 | 
					                if (
 | 
				
			||||||
                  && ( 
 | 
					                    exists( $decode_json->{abilities}[$abilities]{name} )
 | 
				
			||||||
                      $decode_json->{abilities}[$abilities]{name} eq 'watering' )
 | 
					                    && ( $decode_json->{abilities}[$abilities]{name} eq
 | 
				
			||||||
                ) {
 | 
					                        'watering' )
 | 
				
			||||||
                  if ( $propertie->{name} eq 'button_config_time'  ) 
 | 
					                  )
 | 
				
			||||||
                  { 
 | 
					                {
 | 
				
			||||||
                    if ( $hash->{helper}{$propertie->{name}.'_id'} ne
 | 
					                    if ( $propertie->{name} eq 'button_config_time' ) {
 | 
				
			||||||
                          $decode_json->{abilities}[$abilities]{id} ) 
 | 
					                        if ( $hash->{helper}{ $propertie->{name} . '_id' } ne
 | 
				
			||||||
                          {
 | 
					                            $decode_json->{abilities}[$abilities]{id} )
 | 
				
			||||||
                            $hash->{helper}{$propertie->{name}.'_id'} =
 | 
					                        {
 | 
				
			||||||
                            $decode_json->{abilities}[$abilities]{id};
 | 
					                            $hash->{helper}{ $propertie->{name} . '_id' } =
 | 
				
			||||||
                          }
 | 
					                              $decode_json->{abilities}[$abilities]{id};
 | 
				
			||||||
                          readingsBulkUpdateIfChanged(
 | 
					                        }
 | 
				
			||||||
                              $hash,
 | 
					                        readingsBulkUpdateIfChanged(
 | 
				
			||||||
                              'manualButtonTime',
 | 
					                            $hash,
 | 
				
			||||||
                              (RigReadingsValue( $hash, $propertie->{value} / 60) )
 | 
					                            'manualButtonTime',
 | 
				
			||||||
                          );
 | 
					                            (
 | 
				
			||||||
                          next;
 | 
					                                RigReadingsValue(
 | 
				
			||||||
                  }
 | 
					                                    $hash, $propertie->{value} / 60
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                        next;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                readingsBulkUpdateIfChanged(
 | 
					                readingsBulkUpdateIfChanged(
 | 
				
			||||||
@@ -653,21 +706,22 @@ sub WriteReadings {
 | 
				
			|||||||
                        || $decode_json->{abilities}[$abilities]{name} . '-'
 | 
					                        || $decode_json->{abilities}[$abilities]{name} . '-'
 | 
				
			||||||
                        . $propertie->{name} eq 'light-light' )
 | 
					                        . $propertie->{name} eq 'light-light' )
 | 
				
			||||||
                  );
 | 
					                  );
 | 
				
			||||||
                  
 | 
					
 | 
				
			||||||
                readingsBulkUpdateIfChanged(
 | 
					                readingsBulkUpdateIfChanged(
 | 
				
			||||||
                    $hash,
 | 
					                    $hash,
 | 
				
			||||||
                    $decode_json->{abilities}[$abilities]{name} . '-'
 | 
					                    $decode_json->{abilities}[$abilities]{name} . '-'
 | 
				
			||||||
                      . $propertie->{name} 
 | 
					                      . $propertie->{name}
 | 
				
			||||||
                      . '_timestamp',
 | 
					                      . '_timestamp',
 | 
				
			||||||
                      Time::Piece->strptime(RigReadingsValue( $hash, $propertie->{timestamp} ), "%Y-%m-%d %H:%M:%S")->strftime('%s')
 | 
					                    Time::Piece->strptime(
 | 
				
			||||||
                      
 | 
					                        RigReadingsValue( $hash, $propertie->{timestamp} ),
 | 
				
			||||||
 | 
					                        "%Y-%m-%d %H:%M:%S" )->strftime('%s')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
                  if (
 | 
					                  if (
 | 
				
			||||||
                    defined( $propertie->{value} ) 
 | 
					                    defined( $propertie->{value} )
 | 
				
			||||||
                    && (  $decode_json->{abilities}[$abilities]{name} . '-'
 | 
					                    && (  $decode_json->{abilities}[$abilities]{name} . '-'
 | 
				
			||||||
                        . $propertie->{name} eq 'mower_timer-mower_timer'
 | 
					                        . $propertie->{name} eq 'mower_timer-mower_timer' )
 | 
				
			||||||
                  )
 | 
					                  );
 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                readingsBulkUpdateIfChanged(
 | 
					                readingsBulkUpdateIfChanged(
 | 
				
			||||||
                    $hash,
 | 
					                    $hash,
 | 
				
			||||||
@@ -707,31 +761,33 @@ sub WriteReadings {
 | 
				
			|||||||
    } while ( $abilities >= 0 );
 | 
					    } while ( $abilities >= 0 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        #Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name};
 | 
					#Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name};
 | 
				
			||||||
        #Log3 $name, 1, " - KEIN ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) ne "ARRAY");
 | 
					#Log3 $name, 1, " - KEIN ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) ne "ARRAY");
 | 
				
			||||||
        #Log3 $name, 1, " - IST ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY");
 | 
					#Log3 $name, 1, " - IST ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (   exists($decode_json->{settings}[$settings]{name})
 | 
					        if (
 | 
				
			||||||
          && ( 
 | 
					            exists( $decode_json->{settings}[$settings]{name} )
 | 
				
			||||||
            $decode_json->{settings}[$settings]{name} =~ /schedules_paused_until_?\d?$/
 | 
					            && ( $decode_json->{settings}[$settings]{name} =~
 | 
				
			||||||
            || $decode_json->{settings}[$settings]{name} eq 'eco_mode' 
 | 
					                   /schedules_paused_until_?\d?$/
 | 
				
			||||||
            || $decode_json->{settings}[$settings]{name} eq 'winter_mode' )
 | 
					                || $decode_json->{settings}[$settings]{name} eq 'eco_mode'
 | 
				
			||||||
           )
 | 
					                || $decode_json->{settings}[$settings]{name} eq 'winter_mode' )
 | 
				
			||||||
        {  
 | 
					          )
 | 
				
			||||||
            if ( $hash->{helper}{$decode_json->{settings}[$settings]{name}.'_id'} ne
 | 
					        {
 | 
				
			||||||
 | 
					            if ( $hash->{helper}
 | 
				
			||||||
 | 
					                { $decode_json->{settings}[$settings]{name} . '_id' } ne
 | 
				
			||||||
                $decode_json->{settings}[$settings]{id} )
 | 
					                $decode_json->{settings}[$settings]{id} )
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                $hash->{helper}{$decode_json->{settings}[$settings]{name}.'_id'} =
 | 
					                $hash->{helper}
 | 
				
			||||||
 | 
					                  { $decode_json->{settings}[$settings]{name} . '_id' } =
 | 
				
			||||||
                  $decode_json->{settings}[$settings]{id};
 | 
					                  $decode_json->{settings}[$settings]{id};
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # save winter mode as reading
 | 
					            # save winter mode as reading
 | 
				
			||||||
            readingsBulkUpdateIfChanged(
 | 
					            readingsBulkUpdateIfChanged( $hash, 'winter_mode',
 | 
				
			||||||
                    $hash,
 | 
					                $decode_json->{settings}[$settings]{value} )
 | 
				
			||||||
                    'winter_mode',
 | 
					              if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' );
 | 
				
			||||||
                    $decode_json->{settings}[$settings]{value}
 | 
					 | 
				
			||||||
                ) if ($decode_json->{settings}[$settings]{name} eq 'winter_mode');
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY"
 | 
					        if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY"
 | 
				
			||||||
            && $decode_json->{settings}[$settings]{name} eq 'starting_points' )
 | 
					            && $decode_json->{settings}[$settings]{name} eq 'starting_points' )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -763,36 +819,50 @@ sub WriteReadings {
 | 
				
			|||||||
        $settings--;
 | 
					        $settings--;
 | 
				
			||||||
    } while ( $settings >= 0 );
 | 
					    } while ( $settings >= 0 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    my $online_state =
 | 
				
			||||||
    my $online_state = ReadingsVal($name , 'device_info-connection_status', 'unknown');
 | 
					      ReadingsVal( $name, 'device_info-connection_status', 'unknown' );
 | 
				
			||||||
      
 | 
					
 | 
				
			||||||
    readingsBulkUpdate( $hash, 'state',
 | 
					    readingsBulkUpdate( $hash, 'state',
 | 
				
			||||||
        $online_state eq 'online' ?
 | 
					        $online_state eq 'online'
 | 
				
			||||||
          ReadingsVal( $name, 'mower-status', 'readingsValError') : 'offline'
 | 
					        ? ReadingsVal( $name, 'mower-status', 'readingsValError' )
 | 
				
			||||||
        )
 | 
					        : 'offline' )
 | 
				
			||||||
      if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' );
 | 
					      if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' );
 | 
				
			||||||
    readingsBulkUpdate(
 | 
					    readingsBulkUpdate(
 | 
				
			||||||
        $hash, 'state',
 | 
					        $hash, 'state',
 | 
				
			||||||
        (
 | 
					        (
 | 
				
			||||||
                ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )
 | 
					            ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 ) =~
 | 
				
			||||||
                  =~ m{\A[1-9]([0-9]+)?\z}xms
 | 
					              m{\A[1-9]([0-9]+)?\z}xms
 | 
				
			||||||
            ? RigReadingsValue( $hash, 'open' )
 | 
					            ? RigReadingsValue( $hash, 'open' )
 | 
				
			||||||
            : RigReadingsValue( $hash, 'closed' )
 | 
					            : RigReadingsValue( $hash, 'closed' )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' );
 | 
					    ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' ) {
 | 
					    if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' ) {
 | 
				
			||||||
      my $state_string = ( ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor') ?  'T: ' .ReadingsVal( $name, 'ambient_temperature-temperature', 'readingsValError' ) . '°C, ' :  'T: ' .ReadingsVal( $name, 'soil_temperature-temperature', 'readingsValError' ) . '°C, ' ;
 | 
					        my $state_string =
 | 
				
			||||||
      $state_string .=  'H: '. ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ). '%';
 | 
					          ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq
 | 
				
			||||||
      $state_string .= ', L: ' . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux' if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
					              'sensor' )
 | 
				
			||||||
      
 | 
					          ? 'T: '
 | 
				
			||||||
      # if ( $online_state eq 'offline') {
 | 
					          . ReadingsVal( $name, 'ambient_temperature-temperature',
 | 
				
			||||||
      #   readingsBulkUpdate( $hash, 'humidity-humidity', '-1' );
 | 
					            'readingsValError' )
 | 
				
			||||||
      #   readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
					          . '°C, '
 | 
				
			||||||
      #   readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
					          : 'T: '
 | 
				
			||||||
      # }
 | 
					          . ReadingsVal( $name, 'soil_temperature-temperature',
 | 
				
			||||||
      readingsBulkUpdate($hash, 'state', $online_state eq 'online' ? $state_string : 'offline' )
 | 
					            'readingsValError' )
 | 
				
			||||||
 | 
					          . '°C, ';
 | 
				
			||||||
 | 
					        $state_string .= 'H: '
 | 
				
			||||||
 | 
					          . ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ) . '%';
 | 
				
			||||||
 | 
					        $state_string .= ', L: '
 | 
				
			||||||
 | 
					          . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux'
 | 
				
			||||||
 | 
					          if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq
 | 
				
			||||||
 | 
					            'sensor' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# if ( $online_state eq 'offline') {
 | 
				
			||||||
 | 
					#   readingsBulkUpdate( $hash, 'humidity-humidity', '-1' );
 | 
				
			||||||
 | 
					#   readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
				
			||||||
 | 
					#   readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
				
			||||||
 | 
					# }
 | 
				
			||||||
 | 
					        readingsBulkUpdate( $hash, 'state',
 | 
				
			||||||
 | 
					            $online_state eq 'online' ? $state_string : 'offline' );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    readingsBulkUpdate(
 | 
					    readingsBulkUpdate(
 | 
				
			||||||
@@ -977,7 +1047,7 @@ sub Zulu2LocalString {
 | 
				
			|||||||
        return (
 | 
					        return (
 | 
				
			||||||
            sprintf(
 | 
					            sprintf(
 | 
				
			||||||
                "%04d-%02d-%02d %02d:%02d:%s",
 | 
					                "%04d-%02d-%02d %02d:%02d:%s",
 | 
				
			||||||
                $lyear, $lmonth, $lday,
 | 
					                $lyear, $lmonth,  $lday,
 | 
				
			||||||
                $lhour, $datemin, substr( $rest, 0, 2 )
 | 
					                $lhour, $datemin, substr( $rest, 0, 2 )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
@@ -998,10 +1068,10 @@ sub Zulu2LocalString {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub SetPredefinedStartPoints {
 | 
					sub SetPredefinedStartPoints {
 | 
				
			||||||
    my $hash                                                = shift;
 | 
					    my $hash = shift;
 | 
				
			||||||
    my $aArg                                                = shift;
 | 
					    my $aArg = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my ($startpoint_state,$startpoint_num,@morestartpoints) = @{$aArg};
 | 
					    my ( $startpoint_state, $startpoint_num, @morestartpoints ) = @{$aArg};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my $name = $hash->{NAME};
 | 
					    my $name = $hash->{NAME};
 | 
				
			||||||
    my $payload;
 | 
					    my $payload;
 | 
				
			||||||
@@ -1049,6 +1119,7 @@ sub SetPredefinedStartPoints {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $payload   = '"settings": ' . encode_json($decode_json_settings);
 | 
					            $payload   = '"settings": ' . encode_json($decode_json_settings);
 | 
				
			||||||
            $abilities = 'mower_settings';
 | 
					            $abilities = 'mower_settings';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #$abilities['service_id'] = $hash->{helper}{STARTINGPOINTID};
 | 
					            #$abilities['service_id'] = $hash->{helper}{STARTINGPOINTID};
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
@@ -1406,7 +1477,7 @@ sub SetPredefinedStartPoints {
 | 
				
			|||||||
  "license": "GPL_2",
 | 
					  "license": "GPL_2",
 | 
				
			||||||
  "version": "v2.4.2",
 | 
					  "version": "v2.4.2",
 | 
				
			||||||
  "author": [
 | 
					  "author": [
 | 
				
			||||||
    "Marko Oldenburg <leongaultier@gmail.com>"
 | 
					    "Marko Oldenburg <fhemdevelopment@cooltux.net>"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "x_fhem_maintainer": [
 | 
					  "x_fhem_maintainer": [
 | 
				
			||||||
    "CoolTux"
 | 
					    "CoolTux"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,2 +1,2 @@
 | 
				
			|||||||
UPD 2021-09-27_10:50:10 48067 FHEM/73_GardenaSmartBridge.pm
 | 
					UPD 2022-01-31_19:35:20 49370 FHEM/73_GardenaSmartBridge.pm
 | 
				
			||||||
UPD 2021-09-27_10:50:10 56217 FHEM/74_GardenaSmartDevice.pm
 | 
					UPD 2022-01-31_19:35:42 56993 FHEM/74_GardenaSmartDevice.pm
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user