main #55
@@ -63,6 +63,8 @@ use warnings;
 | 
			
		||||
use POSIX;
 | 
			
		||||
use FHEM::Meta;
 | 
			
		||||
 | 
			
		||||
#use Data::Dumper;
 | 
			
		||||
 | 
			
		||||
use HttpUtils;
 | 
			
		||||
 | 
			
		||||
my $missingModul = '';
 | 
			
		||||
@@ -205,6 +207,7 @@ sub Initialize {
 | 
			
		||||
    $hash->{AttrFn} = \&Attr;
 | 
			
		||||
    $hash->{AttrList} =
 | 
			
		||||
        'debugJSON:0,1 '
 | 
			
		||||
      . 'debugDEVICE:0,1 '
 | 
			
		||||
      . 'disable:1 '
 | 
			
		||||
      . 'interval '
 | 
			
		||||
      . 'disabledForIntervals '
 | 
			
		||||
@@ -239,7 +242,7 @@ sub Define {
 | 
			
		||||
      . '/v1';
 | 
			
		||||
    $hash->{VERSION}   = version->parse($VERSION)->normal;
 | 
			
		||||
    $hash->{INTERVAL}  = 60;
 | 
			
		||||
    $hash->{NOTIFYDEV} = "global,$name";
 | 
			
		||||
    $hash->{NOTIFYDEV} = "global,$name"; 
 | 
			
		||||
 | 
			
		||||
    CommandAttr( undef, $name . ' room GardenaSmart' )
 | 
			
		||||
      if ( AttrVal( $name, 'room', 'none' ) eq 'none' );
 | 
			
		||||
@@ -258,7 +261,7 @@ sub Undef {
 | 
			
		||||
    my $hash = shift;
 | 
			
		||||
    my $name = shift;
 | 
			
		||||
 | 
			
		||||
    RemoveInternalTimer($hash);
 | 
			
		||||
    RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
			
		||||
    delete $modules{GardenaSmartBridge}{defptr}{BRIDGE}
 | 
			
		||||
      if ( defined( $modules{GardenaSmartBridge}{defptr}{BRIDGE} ) );
 | 
			
		||||
 | 
			
		||||
@@ -279,7 +282,7 @@ sub Attr {
 | 
			
		||||
 | 
			
		||||
    if ( $attrName eq 'disable' ) {
 | 
			
		||||
        if ( $cmd eq 'set' && $attrVal eq '1' ) {
 | 
			
		||||
            RemoveInternalTimer($hash);
 | 
			
		||||
            RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
			
		||||
            readingsSingleUpdate( $hash, 'state', 'inactive', 1 );
 | 
			
		||||
            Log3 $name, 3, "GardenaSmartBridge ($name) - disabled";
 | 
			
		||||
        }
 | 
			
		||||
@@ -304,13 +307,13 @@ sub Attr {
 | 
			
		||||
        if ( $cmd eq 'set' ) {
 | 
			
		||||
            return 'Interval must be greater than 0'
 | 
			
		||||
              if ( $attrVal == 0 );
 | 
			
		||||
            RemoveInternalTimer($hash);
 | 
			
		||||
            RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
			
		||||
            $hash->{INTERVAL} = $attrVal;
 | 
			
		||||
            Log3 $name, 3,
 | 
			
		||||
              "GardenaSmartBridge ($name) - set interval: $attrVal";
 | 
			
		||||
        }
 | 
			
		||||
        elsif ( $cmd eq 'del' ) {
 | 
			
		||||
            RemoveInternalTimer($hash);
 | 
			
		||||
            RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
			
		||||
            $hash->{INTERVAL} = 60;
 | 
			
		||||
            Log3 $name, 3,
 | 
			
		||||
"GardenaSmartBridge ($name) - delete User interval and set default: 60";
 | 
			
		||||
@@ -352,6 +355,7 @@ sub Notify {
 | 
			
		||||
                @{$events} or grep /^DEFINED.$name$/,
 | 
			
		||||
                @{$events} or grep /^MODIFIED.$name$/,
 | 
			
		||||
                @{$events} or grep /^ATTR.$name.gardenaAccountEmail.+/,
 | 
			
		||||
                @{$events} or grep /^DELETEATTR.$name.disable$/,
 | 
			
		||||
                @{$events}
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
@@ -363,14 +367,14 @@ sub Notify {
 | 
			
		||||
                @{$events}
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
      && $init_done
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
    getDevices($hash)
 | 
			
		||||
      if (
 | 
			
		||||
        $devtype eq 'Global'
 | 
			
		||||
        && (
 | 
			
		||||
            grep /^DELETEATTR.$name.disable$/,
 | 
			
		||||
            @{$events} or grep /^ATTR.$name.disable.0$/,
 | 
			
		||||
            grep /^ATTR.$name.disable.0$/,
 | 
			
		||||
            @{$events} or grep /^DELETEATTR.$name.interval$/,
 | 
			
		||||
            @{$events} or grep /^ATTR.$name.interval.[0-9]+/,
 | 
			
		||||
            @{$events}
 | 
			
		||||
@@ -383,11 +387,10 @@ sub Notify {
 | 
			
		||||
        && (
 | 
			
		||||
            grep /^state:.Connected$/,
 | 
			
		||||
            @{$events} or grep /^lastRequestState:.request_error$/,
 | 
			
		||||
            @{$events}
 | 
			
		||||
            @{$events} 
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        InternalTimer( gettimeofday() + $hash->{INTERVAL},
 | 
			
		||||
            "FHEM::GardenaSmartBridge::getDevices", $hash );
 | 
			
		||||
        Log3 $name, 4,
 | 
			
		||||
@@ -413,7 +416,7 @@ sub Get {
 | 
			
		||||
        my $list = "";
 | 
			
		||||
        $list .= " debug_devices_list:"
 | 
			
		||||
          .join( ',', @{ $hash->{helper}{deviceList} }) 
 | 
			
		||||
          if ( AttrVal( $name, "debugJSON", "none") ne "none" 
 | 
			
		||||
          if ( AttrVal( $name, "debugDEVICE", "none") ne "none" 
 | 
			
		||||
           && exists($hash->{helper}{deviceList}) );
 | 
			
		||||
      return "Unknown argument $cmd,choose one of $list";    
 | 
			
		||||
    }
 | 
			
		||||
@@ -481,6 +484,7 @@ sub Write {
 | 
			
		||||
        {
 | 
			
		||||
            url       => $hash->{URL} . $uri,
 | 
			
		||||
            timeout   => 15,
 | 
			
		||||
            incrementalTimeout => 1,
 | 
			
		||||
            hash      => $hash,
 | 
			
		||||
            device_id => $deviceId,
 | 
			
		||||
            data      => $payload,
 | 
			
		||||
@@ -517,8 +521,8 @@ sub ErrorHandling {
 | 
			
		||||
    my $dname = $dhash->{NAME};
 | 
			
		||||
    
 | 
			
		||||
    Log3 $name, 4, "GardenaSmartBridge ($name) - Request: $data";
 | 
			
		||||
   
 | 
			
		||||
    my $decode_json = eval { decode_json($data) };
 | 
			
		||||
 | 
			
		||||
    my $decode_json = eval { decode_json($data) } if ( length($data) > 0 );
 | 
			
		||||
    if ($@) {
 | 
			
		||||
        Log3 $name, 3, "GardenaSmartBridge ($name) - JSON error while request";
 | 
			
		||||
    }
 | 
			
		||||
@@ -708,10 +712,26 @@ sub ErrorHandling {
 | 
			
		||||
        delete $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;
 | 
			
		||||
    }
 | 
			
		||||
 if (defined($hash->{helper}{debug_device})){
 | 
			
		||||
      Log3 $name, 5, "GardenaSmartBridge DEBUG Device";
 | 
			
		||||
    elsif (defined ($decode_json->{message}) 
 | 
			
		||||
          && $decode_json->{message} eq 'Unauthorized') {
 | 
			
		||||
      Log3 $name, 3,
 | 
			
		||||
          "GardenaSmartBridge ($name) - Unauthorized -> fetch new token ";     
 | 
			
		||||
      getToken($hash);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (defined($hash->{helper}{debug_device})
 | 
			
		||||
    	&& $hash->{helper}{debug_device} ne 'none'
 | 
			
		||||
    	){
 | 
			
		||||
      Log3 $name, 4, "GardenaSmartBridge DEBUG Device";
 | 
			
		||||
      delete $hash->{helper}{debug_device};
 | 
			
		||||
      my @device_spec = ("name", "id", "category");
 | 
			
		||||
      my $devJson=$decode_json->{devices};
 | 
			
		||||
      my $output = '.:{ DEBUG OUTPUT for '.$devJson->{name}.' }:. \n';
 | 
			
		||||
@@ -731,6 +751,18 @@ sub ErrorHandling {
 | 
			
		||||
          $output .= "value: $dev_settings->{value} \n";
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      $output .= '\n=== Abilities \n';
 | 
			
		||||
      $i = 0;
 | 
			
		||||
      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;
 | 
			
		||||
@@ -771,6 +803,10 @@ sub ResponseProcessing {
 | 
			
		||||
        $hash->{helper}{session_id}     = $decode_json->{data}{id};
 | 
			
		||||
        $hash->{helper}{user_id}        = $decode_json->{data}{attributes}->{user_id};
 | 
			
		||||
        $hash->{helper}{refresh_token}  = $decode_json->{data}{attributes}->{refresh_token};
 | 
			
		||||
        $hash->{helper}{token_expired}  = gettimeofday() + $decode_json->{data}{attributes}->{expires_in};
 | 
			
		||||
 | 
			
		||||
        InternalTimer($hash->{helper}{token_expired},
 | 
			
		||||
            "FHEM::GardenaSmartBridge::getToken", $hash );
 | 
			
		||||
 | 
			
		||||
        Write( $hash, undef, undef, undef );
 | 
			
		||||
        Log3 $name, 3, "GardenaSmartBridge ($name) - fetch locations id";
 | 
			
		||||
@@ -931,7 +967,6 @@ sub WriteReadings {
 | 
			
		||||
                        elsif ( $decode_json->{abilities}[0]{properties}
 | 
			
		||||
                            [$properties]{name} eq 'wifi_status' )
 | 
			
		||||
                        {
 | 
			
		||||
                            #TODO: read valies if bridge connected to wifi
 | 
			
		||||
                            readingsBulkUpdateIfChanged( $hash,
 | 
			
		||||
                              'wifi_status-ssid', $v->{ssid} )
 | 
			
		||||
                              if (ref($v->{ssid}) ne 'HASH');
 | 
			
		||||
@@ -967,8 +1002,7 @@ sub getDevices {
 | 
			
		||||
    my $hash = shift;
 | 
			
		||||
 | 
			
		||||
    my $name = $hash->{NAME};
 | 
			
		||||
 | 
			
		||||
    RemoveInternalTimer($hash);
 | 
			
		||||
    RemoveInternalTimer($hash, "FHEM::GardenaSmartBridge::getDevices");
 | 
			
		||||
 | 
			
		||||
    if ( not IsDisabled($name) ) {
 | 
			
		||||
 | 
			
		||||
@@ -978,12 +1012,17 @@ sub getDevices {
 | 
			
		||||
        for my $gardenaDev (@list){
 | 
			
		||||
          push( @{ $hash->{helper}{deviceList} }, $gardenaDev );
 | 
			
		||||
        }
 | 
			
		||||
        Write( $hash, undef, undef, undef );
 | 
			
		||||
        Log3 $name, 4,
 | 
			
		||||
          "GardenaSmartBridge ($name) - fetch device list and device states";
 | 
			
		||||
        if ( AttrVal( $name, 'gardenaAccountEmail', 'none' ) ne 'none' 
 | 
			
		||||
          && (
 | 
			
		||||
            defined( ReadPassword( $hash, $name ) ) 
 | 
			
		||||
          )) 
 | 
			
		||||
        {
 | 
			
		||||
          Write( $hash, undef, undef, undef );
 | 
			
		||||
          Log3 $name, 4,
 | 
			
		||||
            "GardenaSmartBridge ($name) - fetch device list and device states";
 | 
			
		||||
        } # fi gardenaAccountEmail
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 | 
			
		||||
        readingsSingleUpdate( $hash, 'state', 'disabled', 1 );
 | 
			
		||||
        Log3 $name, 3, "GardenaSmartBridge ($name) - device is disabled";
 | 
			
		||||
    }
 | 
			
		||||
@@ -1013,16 +1052,6 @@ sub getToken {
 | 
			
		||||
      if ( defined( $hash->{helper}{locations_id} )
 | 
			
		||||
        && $hash->{helper}{locations_id} );
 | 
			
		||||
 | 
			
		||||
    # Write(
 | 
			
		||||
    #     $hash,
 | 
			
		||||
    #     '"sessions": {"email": "'
 | 
			
		||||
    #       . AttrVal( $name, 'gardenaAccountEmail', 'none' )
 | 
			
		||||
    #       . '","password": "'
 | 
			
		||||
    #       . ReadPassword( $hash, $name ) . '"}',
 | 
			
		||||
    #     undef,
 | 
			
		||||
    #     undef
 | 
			
		||||
    # );
 | 
			
		||||
    
 | 
			
		||||
    Write(
 | 
			
		||||
         $hash,
 | 
			
		||||
         '"data": {"type":"token", "attributes":{"username": "' 
 | 
			
		||||
@@ -1033,8 +1062,9 @@ sub getToken {
 | 
			
		||||
         undef
 | 
			
		||||
     );
 | 
			
		||||
 | 
			
		||||
Log3 $name, 4, '"data": {"type":"token", "attributes":{"username": "'      . AttrVal( $name, 'gardenaAccountEmail', 'none' )      . '","password": "'
 | 
			
		||||
          . ReadPassword( $hash, $name ) . '", "client_id":"smartgarden-jwt-client"}}';
 | 
			
		||||
    Log3 $name, 4, '"data": {"type":"token", "attributes":{"username": "'     
 | 
			
		||||
               .AttrVal( $name, 'gardenaAccountEmail', 'none' ) . '","password": "'
 | 
			
		||||
               .ReadPassword( $hash, $name ) . '", "client_id":"smartgarden-jwt-client"}}';
 | 
			
		||||
    Log3 $name, 3,
 | 
			
		||||
"GardenaSmartBridge ($name) - send credentials to fetch Token and locationId";
 | 
			
		||||
 | 
			
		||||
@@ -1200,20 +1230,21 @@ sub createHttpValueStrings {
 | 
			
		||||
    $payload = '{}' if ( !defined($payload) );
 | 
			
		||||
 | 
			
		||||
    if ( $payload eq '{}' ) {
 | 
			
		||||
        $method = 'GET';
 | 
			
		||||
        $method = 'GET' if (defined( $hash->{helper}{session_id} ) );
 | 
			
		||||
        $payload = '';
 | 
			
		||||
        $uri .= '/locations?locatioId=null&user_id=' . $hash->{helper}{user_id}
 | 
			
		||||
          if ( exists( $hash->{helper}{user_id} )
 | 
			
		||||
            && !defined( $hash->{helper}{locations_id} ) );
 | 
			
		||||
        readingsSingleUpdate( $hash, 'state', 'fetch locationId', 1 )
 | 
			
		||||
          if ( !defined( $hash->{helper}{locations_id} ) );
 | 
			
		||||
        $uri .= '/auth/token' if ( !defined( $hash->{helper}{session_id} ) );
 | 
			
		||||
          if ( exists( $hash->{helper}{user_id} )
 | 
			
		||||
            && !defined( $hash->{helper}{locations_id} ) );
 | 
			
		||||
        $uri .= '/devices'
 | 
			
		||||
          if (!defined($abilities)
 | 
			
		||||
            && defined( $hash->{helper}{locations_id} ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $uri = '/devices/'.InternalVal($hash->{helper}{debug_device}, 'DEVICEID', 0 ) if ( exists ($hash->{helper}{debug_device}));
 | 
			
		||||
    $uri = '/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} ) );
 | 
			
		||||
 | 
			
		||||
    if ( defined( $hash->{helper}{locations_id} ) ) {
 | 
			
		||||
@@ -1279,6 +1310,19 @@ sub createHttpValueStrings {
 | 
			
		||||
              . $abilities
 | 
			
		||||
              . '/properties/manual_watering_timer';
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        elsif (defined($abilities)
 | 
			
		||||
            && defined($payload)
 | 
			
		||||
            && $abilities eq 'watering_button_config' )
 | 
			
		||||
        {
 | 
			
		||||
            $method = 'PUT';
 | 
			
		||||
 | 
			
		||||
            $uri .=
 | 
			
		||||
                '/devices/'
 | 
			
		||||
              . $deviceId
 | 
			
		||||
              . '/abilities/watering'
 | 
			
		||||
              . '/properties/button_config_time';
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        elsif (defined($abilities)
 | 
			
		||||
            && defined($payload)
 | 
			
		||||
@@ -1463,7 +1507,7 @@ sub DeletePassword {
 | 
			
		||||
  ],
 | 
			
		||||
  "release_status": "stable",
 | 
			
		||||
  "license": "GPL_2",
 | 
			
		||||
  "version": "v2.4.0",
 | 
			
		||||
  "version": "v2.4.6",
 | 
			
		||||
  "author": [
 | 
			
		||||
    "Marko Oldenburg <leongaultier@gmail.com>"
 | 
			
		||||
  ],
 | 
			
		||||
 
 | 
			
		||||
@@ -209,6 +209,10 @@ sub Define {
 | 
			
		||||
    $hash->{helper}{STARTINGPOINTID}            = '';
 | 
			
		||||
    $hash->{helper}{schedules_paused_until_id}  = '';
 | 
			
		||||
    $hash->{helper}{eco_mode_id}                = '';
 | 
			
		||||
    $hash->{helper}{button_config_time_id}      = '';
 | 
			
		||||
    $hash->{helper}{winter_mode_id}             = '';
 | 
			
		||||
    
 | 
			
		||||
    $hash->{helper}{_id}             = '';
 | 
			
		||||
    # IrrigationControl valve control max 6
 | 
			
		||||
    $hash->{helper}{schedules_paused_until_1_id}  = '';
 | 
			
		||||
    $hash->{helper}{schedules_paused_until_2_id}  = '';
 | 
			
		||||
@@ -306,7 +310,7 @@ sub Set {
 | 
			
		||||
    if ( lc $cmd eq 'parkuntilfurthernotice' ) {
 | 
			
		||||
        $payload = '"name":"park_until_further_notice"';
 | 
			
		||||
        if ( $mainboard_version > 10.30 ) {
 | 
			
		||||
          $payload = ' "settings":{"name":"schedules_paused_until","value":"2040-12-31T22: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'  ;
 | 
			
		||||
          $service_id = $hash->{helper}{schedules_paused_until_id};
 | 
			
		||||
        }
 | 
			
		||||
@@ -361,6 +365,18 @@ sub Set {
 | 
			
		||||
          . $aArg->[0] * 60
 | 
			
		||||
          . ',"valve_id":1}}';
 | 
			
		||||
    }
 | 
			
		||||
    elsif ( lc $cmd eq 'manualbuttontime'){
 | 
			
		||||
      $service_id = $hash->{helper}{button_config_time_id};
 | 
			
		||||
      $payload=
 | 
			
		||||
        '"properties":{"name":"button_config_time",'
 | 
			
		||||
        .'"value":'
 | 
			
		||||
        .  $aArg->[0] * 60
 | 
			
		||||
        . ',"timestamp":"2021-05-26T19:06:23.680Z"'
 | 
			
		||||
        . ',"at_bound":null,"unit":"seconds","ability":"'
 | 
			
		||||
        . $service_id
 | 
			
		||||
        .'"}';
 | 
			
		||||
        $abilities = 'watering_button_config';
 | 
			
		||||
    }
 | 
			
		||||
    elsif ( $cmd =~ m{\AcancelOverride}xms ) {
 | 
			
		||||
 | 
			
		||||
        my $valve_id = 1;
 | 
			
		||||
@@ -377,14 +393,26 @@ sub Set {
 | 
			
		||||
          . ',"valve_id":'
 | 
			
		||||
          . $valve_id . '}}';
 | 
			
		||||
    }
 | 
			
		||||
    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'));
 | 
			
		||||
    
 | 
			
		||||
      $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' ) {
 | 
			
		||||
        my $val = (
 | 
			
		||||
            defined($aArg) && ref($aArg) eq 'ARRAY'
 | 
			
		||||
            scalar(!@$aArg == 0) && ref($aArg) eq 'ARRAY'
 | 
			
		||||
            ? $aArg->[0] * 60
 | 
			
		||||
            : lc $cmd
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $payload = '"properties":{"value":"' . $val . '"}';
 | 
			
		||||
        $payload = '"properties":{"name":"power_timer", "value":"' . $val . '"}';
 | 
			
		||||
    }
 | 
			
		||||
    ### Watering ic24
 | 
			
		||||
    elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) {
 | 
			
		||||
@@ -407,8 +435,8 @@ sub Set {
 | 
			
		||||
    }
 | 
			
		||||
    elsif ( $cmd =~ /.*ScheduleValve/ ){
 | 
			
		||||
      my $valve_id = $aArg->[0];
 | 
			
		||||
      my $duration = (( defined($aArg->[1]) ? ( ((Time::Piece->new)+(ONE_HOUR *  $aArg->[1]) - (Time::Piece->new)->tzoffset )->datetime ).'.000Z' : '2040-12-31T22: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';
 | 
			
		||||
      $service_id = $hash->{helper}->{'schedules_paused_until_'.$valve_id.'_id'};
 | 
			
		||||
      $payload = '"settings":{"name":"schedules_paused_until_'
 | 
			
		||||
@@ -441,8 +469,16 @@ sub Set {
 | 
			
		||||
            $payload   = '"name":"measure_soil_humidity"';
 | 
			
		||||
            $abilities = 'humidity';
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    ## winter sleep
 | 
			
		||||
    elsif ( lc $cmd eq 'winter_mode') {
 | 
			
		||||
        $payload = '"settings":{"name":"winter_mode","value":"'
 | 
			
		||||
        . $aArg->[0]
 | 
			
		||||
        .'","device":"'
 | 
			
		||||
        . $hash->{DEVICEID}
 | 
			
		||||
        .'"}';
 | 
			
		||||
        $abilities = 'winter_settings';
 | 
			
		||||
        $service_id = $hash->{helper}->{'winter_mode_id'};
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 | 
			
		||||
@@ -452,7 +488,7 @@ sub Set {
 | 
			
		||||
'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint'
 | 
			
		||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' );
 | 
			
		||||
 | 
			
		||||
        $list .= 'manualOverride:slider,1,1,59 cancelOverride:noArg'
 | 
			
		||||
        $list .= 'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100'
 | 
			
		||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' );
 | 
			
		||||
 | 
			
		||||
        $list .=
 | 
			
		||||
@@ -466,9 +502,10 @@ sub Set {
 | 
			
		||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' 
 | 
			
		||||
            && ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor' );
 | 
			
		||||
 | 
			
		||||
        $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,60'
 | 
			
		||||
        $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720'
 | 
			
		||||
          if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' );
 | 
			
		||||
 | 
			
		||||
        # all devices has abilitie to fall a sleep
 | 
			
		||||
        $list .= ' winter_mode:awake,hibernate';
 | 
			
		||||
        return "Unknown argument $cmd, choose one of $list";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -547,6 +584,27 @@ sub WriteReadings {
 | 
			
		||||
            for my $propertie (
 | 
			
		||||
                @{ $decode_json->{abilities}[$abilities]{properties} } )
 | 
			
		||||
            {
 | 
			
		||||
              if (   exists($decode_json->{abilities}[$abilities]{name})
 | 
			
		||||
                  && ( 
 | 
			
		||||
                      $decode_json->{abilities}[$abilities]{name} eq 'watering' )
 | 
			
		||||
                ) {
 | 
			
		||||
                  if ( $propertie->{name} eq 'button_config_time'  ) 
 | 
			
		||||
                  { 
 | 
			
		||||
                    if ( $hash->{helper}{$propertie->{name}.'_id'} ne
 | 
			
		||||
                          $decode_json->{abilities}[$abilities]{id} ) 
 | 
			
		||||
                          {
 | 
			
		||||
                            $hash->{helper}{$propertie->{name}.'_id'} =
 | 
			
		||||
                            $decode_json->{abilities}[$abilities]{id};
 | 
			
		||||
                          }
 | 
			
		||||
                          readingsBulkUpdateIfChanged(
 | 
			
		||||
                              $hash,
 | 
			
		||||
                              'manualButtonTime',
 | 
			
		||||
                              (RigReadingsValue( $hash, $propertie->{value} / 60) )
 | 
			
		||||
                          );
 | 
			
		||||
                          next;
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                readingsBulkUpdateIfChanged(
 | 
			
		||||
                    $hash,
 | 
			
		||||
                    $decode_json->{abilities}[$abilities]{name} . '-'
 | 
			
		||||
@@ -595,6 +653,21 @@ sub WriteReadings {
 | 
			
		||||
                        || $decode_json->{abilities}[$abilities]{name} . '-'
 | 
			
		||||
                        . $propertie->{name} eq 'light-light' )
 | 
			
		||||
                  );
 | 
			
		||||
                  
 | 
			
		||||
                readingsBulkUpdateIfChanged(
 | 
			
		||||
                    $hash,
 | 
			
		||||
                    $decode_json->{abilities}[$abilities]{name} . '-'
 | 
			
		||||
                      . $propertie->{name} 
 | 
			
		||||
                      . '_timestamp',
 | 
			
		||||
                      Time::Piece->strptime(RigReadingsValue( $hash, $propertie->{timestamp} ), "%Y-%m-%d %H:%M:%S")->strftime('%s')
 | 
			
		||||
                      
 | 
			
		||||
                  )
 | 
			
		||||
                  if (
 | 
			
		||||
                    defined( $propertie->{value} ) 
 | 
			
		||||
                    && (  $decode_json->{abilities}[$abilities]{name} . '-'
 | 
			
		||||
                        . $propertie->{name} eq 'mower_timer-mower_timer'
 | 
			
		||||
                  )
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                readingsBulkUpdateIfChanged(
 | 
			
		||||
                    $hash,
 | 
			
		||||
@@ -641,7 +714,8 @@ sub WriteReadings {
 | 
			
		||||
        if (   exists($decode_json->{settings}[$settings]{name})
 | 
			
		||||
          && ( 
 | 
			
		||||
            $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' )
 | 
			
		||||
           )
 | 
			
		||||
        {  
 | 
			
		||||
            if ( $hash->{helper}{$decode_json->{settings}[$settings]{name}.'_id'} ne
 | 
			
		||||
@@ -650,6 +724,12 @@ sub WriteReadings {
 | 
			
		||||
                $hash->{helper}{$decode_json->{settings}[$settings]{name}.'_id'} =
 | 
			
		||||
                  $decode_json->{settings}[$settings]{id};
 | 
			
		||||
            }
 | 
			
		||||
            # save winter mode as reading
 | 
			
		||||
            readingsBulkUpdateIfChanged(
 | 
			
		||||
                    $hash,
 | 
			
		||||
                    '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"
 | 
			
		||||
@@ -1125,6 +1205,10 @@ sub SetPredefinedStartPoints {
 | 
			
		||||
    <a name="GardenaSmartDeviceset"></a>
 | 
			
		||||
    <b>set</b>
 | 
			
		||||
    <ul>
 | 
			
		||||
      <li>winter_mode - awake | hibernate</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    <ul>
 | 
			
		||||
        <h3>mower</h3>
 | 
			
		||||
        <li>parkUntilFurtherNotice</li>
 | 
			
		||||
        <li>parkUntilNextTimer</li>
 | 
			
		||||
        <li>startOverrideTimer - (in minutes, 60 = 1h, 1440 = 24h, 4320 = 72h)</li>
 | 
			
		||||
@@ -1134,10 +1218,14 @@ sub SetPredefinedStartPoints {
 | 
			
		||||
            <li>set NAME startpoint enable 1</li>
 | 
			
		||||
            <li>set NAME startpoint disable 3 enable 1</li>
 | 
			
		||||
        </ul>
 | 
			
		||||
 | 
			
		||||
        <h3>irrigation control</h3>
 | 
			
		||||
        <li>resumeScheduleValve - start schedule irrigation on valve n</li>
 | 
			
		||||
        <li>stopScheduleValve - stop schedule irrigation on valve n  (Default: 2040-12-31T22:00:00.000Z) | optional params hours (now + hours)</li>
 | 
			
		||||
        <li>stopScheduleValve - stop schedule irrigation on valve n  (Default: 2038-01-18T00:00:00.000Z) | optional params hours (now + hours)</li>
 | 
			
		||||
        <li>closeAllValves - close all valves</li>
 | 
			
		||||
        <h3>water control</h3>
 | 
			
		||||
        <li>manualButtonTime - set manual time for button press (in minutes) 0 disable button</li>
 | 
			
		||||
        <li>stopSchedule - stop schedule for now + n hours (Default: 2038-01-18T00:00:00.000Z)</li>
 | 
			
		||||
        <li>resumeSchedule - resume schedule</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
@@ -1273,6 +1361,10 @@ sub SetPredefinedStartPoints {
 | 
			
		||||
    <a name="GardenaSmartDeviceset"></a>
 | 
			
		||||
    <b>set</b>
 | 
			
		||||
    <ul>
 | 
			
		||||
      <li>winter_mode - aufwäcken (awake)| winterschlaf (hibernate)</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    <ul>
 | 
			
		||||
        <h3>mäher</h3>
 | 
			
		||||
        <li>parkUntilFurtherNotice - Parken des Mähers unter Umgehung des Zeitplans</li>
 | 
			
		||||
        <li>parkUntilNextTimer - Parken bis zum nächsten Zeitplan</li>
 | 
			
		||||
        <li>startOverrideTimer - Manuelles mähen (in Minuten, 60 = 1h, 1440 = 24h, 4320 = 72h)</li>
 | 
			
		||||
@@ -1282,9 +1374,14 @@ sub SetPredefinedStartPoints {
 | 
			
		||||
            <li>set NAME startpoint enable 1</li>
 | 
			
		||||
            <li>set NAME startpoint disable 3 enable 1</li>
 | 
			
		||||
        </ul>
 | 
			
		||||
        <h3>irrigation control</h3>
 | 
			
		||||
        <li>resumeScheduleValve - Startet Bew&aauml;sserung am Ventil n nach Zeitplan</li>
 | 
			
		||||
        <li>stopScheduleValve - Setzt Bew&aauml;sserung am Ventil n aus (Default: 2040-12-31T22:00:00.000Z) | Optionaler Parameter Stunden (Jetzt + Stunden)</li>
 | 
			
		||||
        <li>stopScheduleValve - Setzt Bew&aauml;sserung am Ventil n aus (Default: 2038-01-18T00:00:00.000Z) | Optionaler Parameter Stunden (Jetzt + Stunden)</li>
 | 
			
		||||
        <li>closeAllValves - Stopt Bew&aauml;sserung an allen Ventilen </li> 
 | 
			
		||||
        <h3>water control</h3>
 | 
			
		||||
        <li>manualButtonTime - setzt die Dauer für den manuellen Knopf (in Minuten) 0 Schaltet den Knopf aus</li>
 | 
			
		||||
        <li>stopSchedule - Halte Zeitplan an für x Stunden - (Default: 2038-01-18T00:00:00.000Z)</li>
 | 
			
		||||
        <li>resumeSchedule - Weiterführung des Zeitplans</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
@@ -1307,7 +1404,7 @@ sub SetPredefinedStartPoints {
 | 
			
		||||
  ],
 | 
			
		||||
  "release_status": "stable",
 | 
			
		||||
  "license": "GPL_2",
 | 
			
		||||
  "version": "v2.4.0",
 | 
			
		||||
  "version": "v2.4.2",
 | 
			
		||||
  "author": [
 | 
			
		||||
    "Marko Oldenburg <leongaultier@gmail.com>"
 | 
			
		||||
  ],
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
UPD 2021-05-22_04:53:56 46135 FHEM/73_GardenaSmartBridge.pm
 | 
			
		||||
UPD 2021-05-22_04:54:14 51644 FHEM/74_GardenaSmartDevice.pm
 | 
			
		||||
UPD 2021-09-27_10:50:10 48067 FHEM/73_GardenaSmartBridge.pm
 | 
			
		||||
UPD 2021-09-27_10:50:10 56217 FHEM/74_GardenaSmartDevice.pm
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user