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;
 | 
				
			||||||
@@ -237,9 +236,7 @@ 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";
 | 
				
			||||||
@@ -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,13 +360,8 @@ sub Notify {
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        || (
 | 
					        || ( $devtype eq 'GardenaSmartBridge'
 | 
				
			||||||
            $devtype eq 'GardenaSmartBridge'
 | 
					            && ( grep /^gardenaAccountPassword.+/, @{$events} ) )
 | 
				
			||||||
            && (
 | 
					 | 
				
			||||||
                grep /^gardenaAccountPassword.+/,
 | 
					 | 
				
			||||||
                @{$events}
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        && $init_done
 | 
					        && $init_done
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
@@ -411,11 +407,12 @@ sub Get {
 | 
				
			|||||||
        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,7 +424,8 @@ 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!!!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -478,7 +476,8 @@ 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(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -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,32 +716,33 @@ 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,
 | 
					        Log3 $name, 3,
 | 
				
			||||||
          "GardenaSmartBridge ($name) - Unauthorized -> fetch new token ";
 | 
					          "GardenaSmartBridge ($name) - Unauthorized -> fetch new token ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        getToken($hash);
 | 
					        getToken($hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return;
 | 
					        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 @device_spec = ( "name", "id", "category" );
 | 
				
			||||||
        my $devJson     = $decode_json->{devices};
 | 
					        my $devJson     = $decode_json->{devices};
 | 
				
			||||||
        my $output = '.:{ DEBUG OUTPUT for ' . $devJson->{name} . ' }:. \n';
 | 
					        my $output = '.:{ DEBUG OUTPUT for ' . $devJson->{name} . ' }:. \n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for my $spec (@device_spec) {
 | 
					        for my $spec (@device_spec) {
 | 
				
			||||||
            $output .= "$spec : $devJson->{$spec} \n";
 | 
					            $output .= "$spec : $devJson->{$spec} \n";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #settings
 | 
					        #settings
 | 
				
			||||||
        $output .= '\n=== Settings \n';
 | 
					        $output .= '\n=== Settings \n';
 | 
				
			||||||
        my $i = 0;
 | 
					        my $i = 0;
 | 
				
			||||||
@@ -745,26 +750,35 @@ sub ErrorHandling {
 | 
				
			|||||||
            $output .= "[" . $i++ . "]id: $dev_settings->{id} \n";
 | 
					            $output .= "[" . $i++ . "]id: $dev_settings->{id} \n";
 | 
				
			||||||
            $output .= "name: $dev_settings->{name} ";
 | 
					            $output .= "name: $dev_settings->{name} ";
 | 
				
			||||||
            if (   ref( $dev_settings->{value} ) eq 'ARRAY'
 | 
					            if (   ref( $dev_settings->{value} ) eq 'ARRAY'
 | 
				
			||||||
          || ref ($dev_settings->{value}) eq 'HASH'){
 | 
					                || ref( $dev_settings->{value} ) eq 'HASH' )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                $output .= 'N/A \n';
 | 
					                $output .= 'N/A \n';
 | 
				
			||||||
        } else {
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                $output .= "value: $dev_settings->{value} \n";
 | 
					                $output .= "value: $dev_settings->{value} \n";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $output .= '\n=== Abilities \n';
 | 
					        $output .= '\n=== Abilities \n';
 | 
				
			||||||
        $i = 0;
 | 
					        $i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for my $dev_settings ( @{ $devJson->{abilities} } ) {
 | 
					        for my $dev_settings ( @{ $devJson->{abilities} } ) {
 | 
				
			||||||
            $output .= "[" . $i++ . "]id: $dev_settings->{id} \n";
 | 
					            $output .= "[" . $i++ . "]id: $dev_settings->{id} \n";
 | 
				
			||||||
            $output .= "name: $dev_settings->{name} ";
 | 
					            $output .= "name: $dev_settings->{name} ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (   ref( $dev_settings->{value} ) eq 'ARRAY'
 | 
					            if (   ref( $dev_settings->{value} ) eq 'ARRAY'
 | 
				
			||||||
          || ref ($dev_settings->{value}) eq 'HASH'){
 | 
					                || ref( $dev_settings->{value} ) eq 'HASH' )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                $output .= 'N/A \n';
 | 
					                $output .= 'N/A \n';
 | 
				
			||||||
        } else {
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                $output .= "value: $dev_settings->{value} \n";
 | 
					                $output .= "value: $dev_settings->{value} \n";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $hash->{helper}{debug_device_output} = $output;
 | 
					        $hash->{helper}{debug_device_output} = $output;
 | 
				
			||||||
        asyncOutput( $param->{cl}, $hash->{helper}{debug_device_output} );
 | 
					        asyncOutput( $param->{cl}, $hash->{helper}{debug_device_output} );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    readingsSingleUpdate( $hash, 'state', 'Connected', 1 )
 | 
					    readingsSingleUpdate( $hash, 'state', 'Connected', 1 )
 | 
				
			||||||
@@ -796,14 +810,18 @@ sub ResponseProcessing {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # print Dumper $decode_json;
 | 
					    # print Dumper $decode_json;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( defined( $decode_json->{data} ) && $decode_json->{data} 
 | 
					    if (   defined( $decode_json->{data} )
 | 
				
			||||||
 | 
					        && $decode_json->{data}
 | 
				
			||||||
        && ref( $decode_json->{data} ) eq 'HASH'
 | 
					        && ref( $decode_json->{data} ) eq 'HASH'
 | 
				
			||||||
        && !defined( $hash->{helper}->{user_id})) {
 | 
					        && !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 );
 | 
				
			||||||
@@ -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,25 +938,75 @@ 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 );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Log3 $name, 5,
 | 
					 | 
				
			||||||
                "GardenaSmartBridge ($name) - Nach Sub: Laenge JSON: "
 | 
					 | 
				
			||||||
              . length($json)
 | 
					 | 
				
			||||||
              . " Content: "
 | 
					 | 
				
			||||||
              . $json
 | 
					 | 
				
			||||||
              . " Tail: "
 | 
					 | 
				
			||||||
              . $tail;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ResponseSubprocessin muss in eine async ausgelagert werden
 | 
				
			||||||
 | 
					######################################
 | 
				
			||||||
 | 
					# Begin Childprozess
 | 
				
			||||||
 | 
					######################################
 | 
				
			||||||
 | 
					sub ResponseSubprocessing {
 | 
				
			||||||
 | 
					    my $subprocess = shift;
 | 
				
			||||||
 | 
					    my $buffer     = $subprocess->{buffer};
 | 
				
			||||||
 | 
					    my $response   = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my ( $json, $tail ) = ParseJSON($buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ($json) {
 | 
				
			||||||
 | 
					        if ( defined($tail) and $tail ) {
 | 
				
			||||||
 | 
					            push @{$response}, $json;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ( $json, $tail ) = ParseJSON($tail);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $subprocess->writeToParent($response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Log3 $name, 3, "GardenaSmartBridge ($name) - no Match for processing data";
 | 
					sub ParseJSON {
 | 
				
			||||||
 | 
					    my $buffer = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return;
 | 
					    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;
 | 
				
			||||||
@@ -941,7 +1058,8 @@ sub WriteReadings {
 | 
				
			|||||||
                          {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}
 | 
				
			||||||
@@ -1013,9 +1131,7 @@ sub getDevices {
 | 
				
			|||||||
            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,
 | 
				
			||||||
@@ -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 )
 | 
				
			||||||
 | 
					          . '", "client_id":"smartgarden-jwt-client"}}',
 | 
				
			||||||
        undef,
 | 
					        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 ) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1243,7 +1308,9 @@ 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 =
 | 
				
			||||||
 | 
					      '/devices/' . InternalVal( $hash->{helper}{debug_device}, 'DEVICEID', 0 )
 | 
				
			||||||
 | 
					      if ( defined( $hash->{helper}{debug_device} )
 | 
				
			||||||
        && defined( $hash->{helper}{locations_id} ) );
 | 
					        && defined( $hash->{helper}{locations_id} ) );
 | 
				
			||||||
    $uri = '/auth/token' if ( !defined( $hash->{helper}{session_id} ) );
 | 
					    $uri = '/auth/token' if ( !defined( $hash->{helper}{session_id} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1253,11 +1320,7 @@ 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/ );
 | 
				
			||||||
@@ -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:
 | 
				
			||||||
@@ -213,6 +213,7 @@ sub Define {
 | 
				
			|||||||
    $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} = '';
 | 
				
			||||||
@@ -287,12 +288,14 @@ sub Set {
 | 
				
			|||||||
    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'
 | 
				
			||||||
@@ -310,7 +313,9 @@ sub Set {
 | 
				
			|||||||
    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 =
 | 
				
			||||||
 | 
					' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"'
 | 
				
			||||||
 | 
					              . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
            $abilities  = 'mower_settings';
 | 
					            $abilities  = 'mower_settings';
 | 
				
			||||||
            $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
					            $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -325,7 +330,9 @@ sub Set {
 | 
				
			|||||||
    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 =
 | 
				
			||||||
 | 
					' "settings":{"name":"schedules_paused_until","value":"","device":"'
 | 
				
			||||||
 | 
					              . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
            $abilities  = 'mower_settings';
 | 
					            $abilities  = 'mower_settings';
 | 
				
			||||||
            $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
					            $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -334,21 +341,28 @@ sub Set {
 | 
				
			|||||||
        $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":'
 | 
				
			||||||
 | 
					              . $aArg->[0] * 60 . '}';
 | 
				
			||||||
            $abilities = 'mower_timer';
 | 
					            $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 =
 | 
				
			||||||
 | 
					            '"settings": {"name": "eco_mode", "value": '
 | 
				
			||||||
 | 
					          . $aArg->[0]
 | 
				
			||||||
 | 
					          . ', "device": "'
 | 
				
			||||||
 | 
					          . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
        $abilities  = 'mower_settings' if ( $mainboard_version > 10.30 );
 | 
					        $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
 | 
				
			||||||
@@ -373,8 +387,7 @@ sub Set {
 | 
				
			|||||||
          . $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 ) {
 | 
				
			||||||
@@ -394,16 +407,29 @@ sub Set {
 | 
				
			|||||||
          . $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 = (
 | 
				
			||||||
 | 
					            (
 | 
				
			||||||
 | 
					                defined( $aArg->[0] )
 | 
				
			||||||
 | 
					                ? (
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        ( Time::Piece->new ) +
 | 
				
			||||||
 | 
					                          ( ONE_HOUR * $aArg->[0] ) -
 | 
				
			||||||
 | 
					                          ( Time::Piece->new )->tzoffset
 | 
				
			||||||
 | 
					                    )->datetime
 | 
				
			||||||
 | 
					                  )
 | 
				
			||||||
 | 
					                  . '.000Z'
 | 
				
			||||||
 | 
					                : '2038-01-18T00:00:00.000Z'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $abilities  = 'wateringcomputer_settings';
 | 
					        $abilities  = 'wateringcomputer_settings';
 | 
				
			||||||
        $service_id = $hash->{helper}->{'schedules_paused_until_id'};
 | 
					        $service_id = $hash->{helper}->{'schedules_paused_until_id'};
 | 
				
			||||||
      $payload = '"settings":{"name":"schedules_paused_until"'
 | 
					        $payload =
 | 
				
			||||||
 | 
					            '"settings":{"name":"schedules_paused_until"'
 | 
				
			||||||
          . ', "value":"'
 | 
					          . ', "value":"'
 | 
				
			||||||
          . ( $cmd eq 'resumeSchedule' ? '' : $duration )
 | 
					          . ( $cmd eq 'resumeSchedule' ? '' : $duration )
 | 
				
			||||||
          . '","device":"'
 | 
					          . '","device":"'
 | 
				
			||||||
                  . $hash->{DEVICEID}
 | 
					          . $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 = (
 | 
				
			||||||
@@ -412,7 +438,8 @@ sub Set {
 | 
				
			|||||||
            : 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 ) {
 | 
				
			||||||
@@ -435,27 +462,44 @@ sub Set {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    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 = (
 | 
				
			||||||
 | 
					            (
 | 
				
			||||||
 | 
					                defined( $aArg->[1] )
 | 
				
			||||||
 | 
					                ? (
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        ( Time::Piece->new ) +
 | 
				
			||||||
 | 
					                          ( ONE_HOUR * $aArg->[1] ) -
 | 
				
			||||||
 | 
					                          ( Time::Piece->new )->tzoffset
 | 
				
			||||||
 | 
					                    )->datetime
 | 
				
			||||||
 | 
					                  )
 | 
				
			||||||
 | 
					                  . '.000Z'
 | 
				
			||||||
 | 
					                : '2038-01-18T00:00:00.000Z'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $abilities = 'irrigation_settings';
 | 
					        $abilities = 'irrigation_settings';
 | 
				
			||||||
      $service_id = $hash->{helper}->{'schedules_paused_until_'.$valve_id.'_id'};
 | 
					        $service_id =
 | 
				
			||||||
      $payload = '"settings":{"name":"schedules_paused_until_'
 | 
					          $hash->{helper}->{ 'schedules_paused_until_' . $valve_id . '_id' };
 | 
				
			||||||
 | 
					        $payload =
 | 
				
			||||||
 | 
					            '"settings":{"name":"schedules_paused_until_'
 | 
				
			||||||
          . $valve_id
 | 
					          . $valve_id
 | 
				
			||||||
          . '", "value":"'
 | 
					          . '", "value":"'
 | 
				
			||||||
          . ( $cmd eq 'resumeScheduleValve' ? '' : $duration )
 | 
					          . ( $cmd eq 'resumeScheduleValve' ? '' : $duration )
 | 
				
			||||||
          . '","device":"'
 | 
					          . '","device":"'
 | 
				
			||||||
                  . $hash->{DEVICEID}
 | 
					          . $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
 | 
				
			||||||
 | 
					                'sensor' )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                $payload   = '"name":"measure_ambient_temperature"';
 | 
					                $payload   = '"name":"measure_ambient_temperature"';
 | 
				
			||||||
                $abilities = 'ambient_temperature';
 | 
					                $abilities = 'ambient_temperature';
 | 
				
			||||||
            } else {
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                $payload   = '"name":"measure_soil_temperature"';
 | 
					                $payload   = '"name":"measure_soil_temperature"';
 | 
				
			||||||
                $abilities = 'soil_temperature';
 | 
					                $abilities = 'soil_temperature';
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -472,11 +516,11 @@ 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 =
 | 
				
			||||||
 | 
					            '"settings":{"name":"winter_mode","value":"'
 | 
				
			||||||
          . $aArg->[0]
 | 
					          . $aArg->[0]
 | 
				
			||||||
          . '","device":"'
 | 
					          . '","device":"'
 | 
				
			||||||
        . $hash->{DEVICEID}
 | 
					          . $hash->{DEVICEID} . '"}';
 | 
				
			||||||
        .'"}';
 | 
					 | 
				
			||||||
        $abilities  = 'winter_settings';
 | 
					        $abilities  = 'winter_settings';
 | 
				
			||||||
        $service_id = $hash->{helper}->{'winter_mode_id'};
 | 
					        $service_id = $hash->{helper}->{'winter_mode_id'};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -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,12 +632,13 @@ 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 ( $propertie->{name} eq 'button_config_time' ) {
 | 
				
			||||||
                        if ( $hash->{helper}{ $propertie->{name} . '_id' } ne
 | 
					                        if ( $hash->{helper}{ $propertie->{name} . '_id' } ne
 | 
				
			||||||
                            $decode_json->{abilities}[$abilities]{id} )
 | 
					                            $decode_json->{abilities}[$abilities]{id} )
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
@@ -599,7 +648,11 @@ sub WriteReadings {
 | 
				
			|||||||
                        readingsBulkUpdateIfChanged(
 | 
					                        readingsBulkUpdateIfChanged(
 | 
				
			||||||
                            $hash,
 | 
					                            $hash,
 | 
				
			||||||
                            'manualButtonTime',
 | 
					                            'manualButtonTime',
 | 
				
			||||||
                              (RigReadingsValue( $hash, $propertie->{value} / 60) )
 | 
					                            (
 | 
				
			||||||
 | 
					                                RigReadingsValue(
 | 
				
			||||||
 | 
					                                    $hash, $propertie->{value} / 60
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                        next;
 | 
					                        next;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -659,14 +712,15 @@ sub WriteReadings {
 | 
				
			|||||||
                    $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(
 | 
				
			||||||
@@ -711,25 +765,27 @@ sub WriteReadings {
 | 
				
			|||||||
#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} =~
 | 
				
			||||||
 | 
					                   /schedules_paused_until_?\d?$/
 | 
				
			||||||
                || $decode_json->{settings}[$settings]{name} eq 'eco_mode'
 | 
					                || $decode_json->{settings}[$settings]{name} eq 'eco_mode'
 | 
				
			||||||
                || $decode_json->{settings}[$settings]{name} eq 'winter_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"
 | 
				
			||||||
@@ -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: '
 | 
				
			||||||
 | 
					          . ReadingsVal( $name, 'ambient_temperature-temperature',
 | 
				
			||||||
 | 
					            'readingsValError' )
 | 
				
			||||||
 | 
					          . '°C, '
 | 
				
			||||||
 | 
					          : 'T: '
 | 
				
			||||||
 | 
					          . ReadingsVal( $name, 'soil_temperature-temperature',
 | 
				
			||||||
 | 
					            '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') {
 | 
					# if ( $online_state eq 'offline') {
 | 
				
			||||||
#   readingsBulkUpdate( $hash, 'humidity-humidity', '-1' );
 | 
					#   readingsBulkUpdate( $hash, 'humidity-humidity', '-1' );
 | 
				
			||||||
#   readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
					#   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, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor');
 | 
				
			||||||
# }
 | 
					# }
 | 
				
			||||||
      readingsBulkUpdate($hash, 'state', $online_state eq 'online' ? $state_string : 'offline' )
 | 
					        readingsBulkUpdate( $hash, 'state',
 | 
				
			||||||
 | 
					            $online_state eq 'online' ? $state_string : 'offline' );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    readingsBulkUpdate(
 | 
					    readingsBulkUpdate(
 | 
				
			||||||
@@ -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