diff --git a/fhem/CHANGED b/fhem/CHANGED index aa51976c8..c0ec6001f 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - bugfix: 73_GardenaSmartBridge: multiple bugfixes, + changed published gateway informations - feature: 76_SolarForecast: new Attr graphicHeaderOwnspecValForm - feature: 58_RPI_1Wire: added on-for-timer and validated DS2408 - change: 10_KNX.pm: minor changes, see Forum #122582 diff --git a/fhem/FHEM/73_GardenaSmartBridge.pm b/fhem/FHEM/73_GardenaSmartBridge.pm index d3bec0906..fe21726ce 100644 --- a/fhem/FHEM/73_GardenaSmartBridge.pm +++ b/fhem/FHEM/73_GardenaSmartBridge.pm @@ -75,9 +75,9 @@ eval { use IO::Socket::SSL; 1 } # try to use JSON::MaybeXS wrapper # for chance of better performance + open code eval { - require JSON::MaybeXS; - import JSON::MaybeXS qw( decode_json encode_json ); - 1; + require JSON::MaybeXS; + import JSON::MaybeXS qw( decode_json encode_json ); + 1; } or do { # try to use JSON wrapper @@ -166,7 +166,7 @@ BEGIN { GP_Export( qw( Initialize - ) + ) ); sub Initialize { @@ -437,12 +437,14 @@ sub Set { DeletePassword($hash); } - elsif ( lc $cmd eq 'debughelper') { - return "usage: $cmd" if ( scalar( @{$aArg} ) != 2 ); - my $new_helper = $aArg->[0]; - my $new_helper_value = $aArg->[1]; - Log3( $name, 5, "[DEBUG] - GardenaSmartBridge ($name) - override helper $new_helper with $new_helper_value"); - $hash->{helper}{$new_helper} = $new_helper_value; + elsif ( lc $cmd eq 'debughelper' ) { + return "usage: $cmd" if ( scalar( @{$aArg} ) != 2 ); + my $new_helper = $aArg->[0]; + my $new_helper_value = $aArg->[1]; + Log3( $name, 5, +"[DEBUG] - GardenaSmartBridge ($name) - override helper $new_helper with $new_helper_value" + ); + $hash->{helper}{$new_helper} = $new_helper_value; } else { @@ -488,8 +490,8 @@ sub Write { "GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: secret!, DATA: secret!, METHOD: $method" ); - # Log3($name, 3, - # "GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: $header, DATA: $payload, METHOD: $method"); +# Log3($name, 3, +# "GardenaSmartBridge ($name) - Send with URL: $hash->{URL}$uri, HEADER: $header, DATA: $payload, METHOD: $method"); return; } @@ -611,8 +613,7 @@ sub ErrorHandling { } if ( - $data =~ /Error/ - && $data !~ /lastLonaErrorCode/ + $data =~ /Error/ && $data !~ /lastLonaErrorCode/ || ( defined($decode_json) && ref($decode_json) eq 'HASH' && defined( $decode_json->{errors} ) ) @@ -627,26 +628,32 @@ sub ErrorHandling { if ( $param->{code} == 400 ) { if ($decode_json) { if ( ref( $decode_json->{errors} ) eq "ARRAY" - && defined( $decode_json->{errors} ) ) + && exists( $decode_json->{errors} ) ) + # replace defined with exists + # && defined( $decode_json->{errors} ) ) { - readingsBulkUpdate( + # $decode_json->{errors} -> ARRAY + # $decode_json->{errors}[0] -> HASH + if (exists ($decode_json->{errors}[0]{error}) ) { + readingsBulkUpdate( $dhash, "state", $decode_json->{errors}[0]{error} . ' ' . $decode_json->{errors}[0]{attribute}, 1 - ); - readingsBulkUpdate( - $dhash, - "lastRequestState", - $decode_json->{errors}[0]{error} . ' ' - . $decode_json->{errors}[0]{attribute}, - 1 - ); - Log3 $dname, 5, - "GardenaSmartBridge ($dname) - RequestERROR: " - . $decode_json->{errors}[0]{error} . " " - . $decode_json->{errors}[0]{attribute}; + ); + readingsBulkUpdate( + $dhash, + "lastRequestState", + $decode_json->{errors}[0]{error} . ' ' + . $decode_json->{errors}[0]{attribute}, + 1 + ); + Log3 $dname, 5, + "GardenaSmartBridge ($dname) - RequestERROR: " + . $decode_json->{errors}[0]{error} . " " + . $decode_json->{errors}[0]{attribute}; + } # fi exists error } } else { @@ -737,7 +744,7 @@ sub ErrorHandling { my $i = 0; for my $dev_settings ( @{ $devJson->{settings} } ) { $output .= "[" . $i++ . "]id: $dev_settings->{id} \n"; - $output .= "name: $dev_settings->{name} "; + $output .= "name: $dev_settings->{name} \n"; if ( ref( $dev_settings->{value} ) eq 'ARRAY' || ref( $dev_settings->{value} ) eq 'HASH' ) { @@ -753,16 +760,7 @@ sub ErrorHandling { 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"; - } + $output .= "name: $dev_settings->{name} \n"; } $hash->{helper}{debug_device_output} = $output; @@ -1078,36 +1076,16 @@ sub WriteReadings { ) && ref($v) eq 'HASH' ) - { - if ( $decode_json->{abilities}[0]{properties} - [$properties]{name} eq 'ethernet_status' ) - { - readingsBulkUpdateIfChanged( $hash, - 'ethernet_status-mac', $v->{mac} ); - readingsBulkUpdateIfChanged( $hash, - 'ethernet_status-ip', $v->{ip} ) - if ( ref( $v->{ip} ) ne 'HASH' ); - readingsBulkUpdateIfChanged( $hash, - 'ethernet_status-isconnected', - $v->{isConnected} ); + { + if ($v->{is_connected} ) { + readingsBulkUpdateIfChanged( $hash, + $decode_json->{abilities}[0]{properties}[$properties]{name}.'-ip', $v->{ip} ) + if ( ref( $v->{ip} ) ne 'HASH' ); + readingsBulkUpdateIfChanged( $hash, + $decode_json->{abilities}[0]{properties}[$properties]{name}.'-isconnected', $v->{is_connected} ) + if ( $v->{is_connected} ); } - elsif ( $decode_json->{abilities}[0]{properties} - [$properties]{name} eq 'wifi_status' ) - { - readingsBulkUpdateIfChanged( $hash, - 'wifi_status-ssid', $v->{ssid} ) - if ( ref( $v->{ssid} ) ne 'HASH' ); - readingsBulkUpdateIfChanged( $hash, - 'wifi_status-mac', $v->{mac} ); - readingsBulkUpdateIfChanged( $hash, - 'wifi_status-ip', $v->{ip} ) - if ( ref( $v->{ip} ) ne 'HASH' ); - readingsBulkUpdateIfChanged( $hash, - 'wifi_status-isconnected', $v->{isConnected} ); - readingsBulkUpdateIfChanged( $hash, - 'wifi_status-signal', $v->{signal} ); - } - } + } # fi ethernet and wifi } $properties--; @@ -1583,7 +1561,7 @@ sub DeletePassword { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.5.2", + "version": "v2.6.1", "author": [ "Marko Oldenburg " ], diff --git a/fhem/FHEM/74_GardenaSmartDevice.pm b/fhem/FHEM/74_GardenaSmartDevice.pm index ad9299335..7cff62549 100644 --- a/fhem/FHEM/74_GardenaSmartDevice.pm +++ b/fhem/FHEM/74_GardenaSmartDevice.pm @@ -7,6 +7,7 @@ # # Special thanks goes to comitters: # - Michael (mbrak) Thanks for Commandref +# - Christian (zife) Thanks for Commandref # - Matthias (Kenneth) Thanks for Wiki entry # - BioS Thanks for predefined start points Code # - fettgu Thanks for Debugging Irrigation Control data flow @@ -66,6 +67,8 @@ use Time::Local; use Time::Piece; use Time::Seconds; +use SetExtensions; + # try to use JSON::MaybeXS wrapper # for chance of better performance + open code eval { @@ -141,7 +144,8 @@ BEGIN { modules IOWrite defs - makeDeviceName) + makeDeviceName + SetExtensions) ); } @@ -149,7 +153,7 @@ BEGIN { GP_Export( qw( Initialize - ) + ) ); sub Initialize { @@ -166,6 +170,7 @@ sub Initialize { $hash->{AttrList} = "readingValueLanguage:de,en " . "model:watering_computer,sensor,sensor2,mower,ic24,power,electronic_pressure_pump " + . "extendedState:0,1 " . "IODev " . $readingFnAttributes; $hash->{parseParams} = 1; @@ -195,11 +200,11 @@ sub Define { $hash->{helper}{eco_mode_id} = ''; $hash->{helper}{button_config_time_id} = ''; $hash->{helper}{winter_mode_id} = ''; - # Electroni Pressure Pump - $hash->{helper}{operating_mode_id} = ''; - $hash->{helper}{leakage_detection_id} = ''; - $hash->{helper}{turn_on_pressure_id} = ''; + # Electroni Pressure Pump + $hash->{helper}{operating_mode_id} = ''; + $hash->{helper}{leakage_detection_id} = ''; + $hash->{helper}{turn_on_pressure_id} = ''; $hash->{helper}{_id} = ''; @@ -285,9 +290,11 @@ sub Set { my $service_id; my $mainboard_version = ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 ); - - my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, - $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); + + my ( + $Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, + $Jahr, $Wochentag, $Jahrestag, $Sommerzeit + ) = localtime(time); my $timezone_offset = $Sommerzeit ? 0 : ( Time::Piece->new )->tzoffset; @@ -483,40 +490,45 @@ sub Set { . $hash->{DEVICEID} . '"}'; } ### Watering_pressure_pump - elsif ( lc $cmd eq 'operating_mode') { - my $op_mode = $aArg->[0]; - $payload = '"settings":{"name":"operating_mode",' - .'"value":"'.$op_mode.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'operating_mode_id' }; + elsif ( lc $cmd eq 'operating_mode' ) { + my $op_mode = $aArg->[0]; + $payload = + '"settings":{"name":"operating_mode",' + . '"value":"' + . $op_mode . '",' + . '"device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{'operating_mode_id'}; } - elsif ( lc $cmd eq 'leakage_detection') { - my $leakdetection_mode = $aArg->[0]; - $payload = '"settings":{"name":"leakage_detection",' - .'"value":"'.$leakdetection_mode.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'leakage_detection_id' }; + elsif ( lc $cmd eq 'leakage_detection' ) { + my $leakdetection_mode = $aArg->[0]; + $payload = + '"settings":{"name":"leakage_detection",' + . '"value":"' + . $leakdetection_mode . '",' + . '"device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{'leakage_detection_id'}; } - elsif ( lc $cmd eq 'turn_on_pressure') { - my $turnonpressure = $aArg->[0]; - $payload = '"settings":{"name":"turn_on_pressure",' - .'"value":"'.$turnonpressure.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'turn_on_pressure_id' }; + elsif ( lc $cmd eq 'turn_on_pressure' ) { + my $turnonpressure = $aArg->[0]; + $payload = + '"settings":{"name":"turn_on_pressure",' + . '"value":"' + . $turnonpressure . '",' + . '"device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{'turn_on_pressure_id'}; } - elsif ( lc $cmd eq 'resetvalveerrors') { - $payload = '"name":"reset_valve_errors",' - .' "parameters": {}'; - $abilities = 'error'; + elsif ( lc $cmd eq 'resetvalveerrors' ) { + $payload = '"name":"reset_valve_errors",' . ' "parameters": {}'; + $abilities = 'error'; } - ### Sensors + ### Sensors elsif ( lc $cmd eq 'refresh' ) { my $sensname = $aArg->[0]; @@ -552,6 +564,7 @@ sub Set { $abilities = 'winter_settings'; $service_id = $hash->{helper}->{'winter_mode_id'}; } + else { my $list = ''; @@ -561,15 +574,34 @@ sub Set { if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); $list .= -'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100' +'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100 resetValveErrors:noArg' if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); $list .= -'closeAllValves:noArg stopScheduleValve:selectnumbers,1,1,6,0,lin resumeScheduleValve:selectnumbers,1,1,6,0,lin manualDurationValve1:slider,1,1,90 manualDurationValve2:slider,1,1,90 manualDurationValve3:slider,1,1,90 manualDurationValve4:slider,1,1,90 manualDurationValve5:slider,1,1,90 manualDurationValve6:slider,1,1,90 cancelOverrideValve1:noArg cancelOverrideValve2:noArg cancelOverrideValve3:noArg cancelOverrideValve4:noArg cancelOverrideValve5:noArg cancelOverrideValve6:noArg' +'manualOverride:slider,1,1,90 cancelOverride:noArg operating_mode:automatic,scheduled leakage_detection:watering,washing_machine,domestic_water_supply,off turn_on_pressure:slider,2,0.2,3.0,1 resetValveErrors:noArg' + if ( AttrVal( $name, 'model', 'unknown' ) eq + 'electronic_pressure_pump' ); + + $list .= +'closeAllValves:noArg resetValveErrors:noArg stopScheduleValve:select,' + . ReadingsVal( $name, 'ic24-valves_connected', '1' ) + . ' resumeScheduleValve:select,' + . ReadingsVal( $name, 'ic24-valves_connected', '1' ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - $list .= 'manualOverride:slider,1,1,90 cancelOverride:noArg operating_mode:automatic,scheduled leakage_detection:watering,washing_machine,domestic_water_supply,off turn_on_pressure:slider,2,0.2,3.0,1 resetValveErrors:noArg' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); + foreach my $valve ( + split( ',', ReadingsVal( $name, 'ic24-valves_connected', '1' ) ) ) + { + $list .= ' manualDurationValve' . $valve . ':slider,1,1,90 ' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + } + + foreach my $valve ( + split( ',', ReadingsVal( $name, 'ic24-valves_connected', '1' ) ) ) + { + $list .= ' cancelOverrideValve' . $valve . ':noArg ' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + } $list .= 'refresh:temperature,humidity' if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ); @@ -585,7 +617,9 @@ sub Set { # all devices has abilitie to fall a sleep $list .= ' winter_mode:awake,hibernate'; - return "Unknown argument $cmd, choose one of $list"; + return SetExtensions( $hash, $list, $name, $cmd, @$aArg ); + + # return "Unknown argument $cmd, choose one of $list"; } $hash->{helper}{deviceAction} = $payload; @@ -647,9 +681,10 @@ sub WriteReadings { my $hash = shift; my $decode_json = shift; - my $name = $hash->{NAME}; - my $abilities = scalar( @{ $decode_json->{abilities} } ); - my $settings = scalar( @{ $decode_json->{settings} } ); + my $name = $hash->{NAME}; + my $abilities = scalar( @{ $decode_json->{abilities} } ); + my $settings = scalar( @{ $decode_json->{settings} } ); + my $scheduled_events = scalar( @{ $decode_json->{scheduled_events} } ); readingsBeginUpdate($hash); @@ -669,6 +704,7 @@ sub WriteReadings { 'watering' ) ) { + if ( $propertie->{name} eq 'button_config_time' ) { if ( $hash->{helper}{ $propertie->{name} . '_id' } ne $decode_json->{abilities}[$abilities]{id} ) @@ -693,9 +729,13 @@ sub WriteReadings { $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, - RigReadingsValue( $hash, $propertie->{value} ) + ( defined( $propertie->{value} ) eq '' ) + ? RigReadingsValue( $hash, 'n/a' ) + : "" + . RigReadingsValue( $hash, + $propertie->{value} ) # cast all data to string with "" ) - if ( defined( $propertie->{value} ) + if ( exists( $propertie->{value} ) && $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'radio-quality' && $decode_json->{abilities}[$abilities]{name} . '-' @@ -710,13 +750,19 @@ sub WriteReadings { . $propertie->{name} ne 'humidity-humidity' && $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'light-light' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'ic24-valves_connected' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'ic24-valves_master_config' && ref( $propertie->{value} ) ne "HASH" ); readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, - RigReadingsValue( $hash, $propertie->{value} ) + "" + . RigReadingsValue( $hash, + $propertie->{value} ) # cast all data to string with "" ) if ( defined( $propertie->{value} ) @@ -743,7 +789,8 @@ sub WriteReadings { $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_timestamp', - Time::Piece->strptime( + "" + . Time::Piece->strptime( RigReadingsValue( $hash, $propertie->{timestamp} ), "%Y-%m-%d %H:%M:%S" )->strftime('%s') @@ -775,35 +822,178 @@ sub WriteReadings { . $propertie->{name} eq 'ic24-valves_master_config' ); if ( ref( $propertie->{value} ) eq "HASH" ) { + my $sub_state = 0; + my $sub_value = 0; while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { - if ( ref( $v ) ne "HASH" ) { - readingsBulkUpdate( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} . '_' - . $r, + if ( ref($v) ne "HASH" ) { + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} + . '-' + . $propertie->{name} . '_' + . $r, RigReadingsValue( $hash, $v ) ); - } else { - while ( my ( $i_r, $i_v ) = each %{ $v } ) { - readingsBulkUpdate( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} . '_' - . $r . '_' . $i_r, - RigReadingsValue( $hash, $i_v ) - ); - } + } + else { + while ( my ( $i_r, $i_v ) = each %{$v} ) { + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} + . '-' + . $propertie->{name} . '_' + . $r . '_' + . $i_r, + RigReadingsValue( $hash, $i_v ) + ); + } } } } + + # ic24 and other watering devices calc irrigation left in sec + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} + . '_irrigation_left', + ( $propertie->{value}{duration} > 0 ) + ? ( + Time::Piece::localtime->strptime( + RigReadingsValue( $hash, $propertie->{timestamp} ), + "%Y-%m-%d %H:%M:%S" + ) + + ( $propertie->{value}{duration} + 3 ) - + Time::Piece::localtime->new + ) + : 0 + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} eq + 'watering' ); } } $abilities--; } while ( $abilities >= 0 ); - my $winter_mode; + if ( + exists( $decode_json->{scheduled_events} ) + + # && scalar ($decode_json->{scheduled_events} ) > 0 + && ref( $decode_json->{scheduled_events} ) eq 'ARRAY' + && AttrVal( $name, 'model', 'unknown' ) !~ /sensor.?/ + ) + { + readingsBulkUpdateIfChanged( + $hash, + 'scheduling-schedules_events_count', + scalar( @{ $decode_json->{scheduled_events} } ) + ); + my $valve_id = 1; + my $event_id = 0; # ic24 [1..6] | wc, pump [1] + + ## + # validiere schedules + my @soll = (); + my @ist = (); + my @tmp_ist = (); + for my $cloud_schedules ( @{ $decode_json->{scheduled_events} } ) { + while ( my ( $r, $v ) = each %{$cloud_schedules} ) { + push @soll, $v if $r eq 'id'; # cloud hat SOLL + } + } + + foreach my $dev_schedules ( sort keys %{ $hash->{READINGS} } ) { + my $dev_reading = ReadingsVal( $name, $dev_schedules, "error" ); + push @ist, $dev_reading + if $dev_schedules =~ /schedule.*\d_id/; # push reading _id + push @ist, $1 + if $dev_schedules =~ + /schedule.*_(\d)_id/; # push readigs d from x_id + + Log3 $name, 5, + "[DEBUG] $name - Schedule - Key ist : $dev_schedules "; + Log3 $name, 5, "[DEBUG] $name - Schedule - ID FOUND $dev_reading" + if $dev_schedules =~ /schedule.*_\d_id/; # cloud hat SOLL + } + + #Log3 $name, 5, "[DEBUG] Cloud:".Dumper(@soll) . "- Internal:". Dumper(@ist); + + ## delete only if cloud != (ist/2) + if ( + ( + scalar(@soll) != scalar( @ist / 2 ) + && scalar(@soll) > 0 + && scalar(@ist) > 0 + ) + || ( scalar(@ist) eq 2 && scalar(@soll) eq 1 ) + ) + { + @tmp_ist = @ist; + while ( my $element = shift(@soll) ) { + my $schedule_step_int = 0; + + foreach my $sist (@tmp_ist) { + my $step = scalar(@tmp_ist) > 1 ? 2 : 1; + if ( $element eq $sist ) { + splice( @ist, $schedule_step_int, $step ) + ; # more than 2 items del them, otherwise 1 + } + $schedule_step_int += $step; + } + } + } + + #Log3 $name, 5, "[DEBUG] $name - Schedule - Rest ". Dumper(@ist); + # delete only if count soll != count ist. cos the will be overwritten + if ( scalar(@ist) > 0 + && scalar(@soll) != scalar( @ist / 2 ) ) + { + while ( my $old_schedule_id = shift(@ist) ) { + if ( length($old_schedule_id) == 1 ) { + foreach ( keys %{ $hash->{READINGS} } ) { + delete $hash->{READINGS}->{$_} + if ( $_ =~ + /scheduling-schedules_event_$old_schedule_id.*/ ); + } + } # fi + Log3 $name, 5, +"[DEBUG] - $name : deletereading scheduling-schedules_event_$old_schedule_id.*" + if length($old_schedule_id) == 1; + } + } + #### /validiere schedules + + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { + $valve_id = $event_schedules->{valve_id} + if ( exists( $event_schedules->{valve_id} ) ); #ic24 + $event_id++; # event id + + while ( my ( $r, $v ) = each %{$event_schedules} ) { + readingsBulkUpdateIfChanged( + $hash, 'scheduling-schedules_event_' . $event_id + +#. ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') + . '_' + . $r, + $v + ) if ( ref($v) ne 'HASH' ); + readingsBulkUpdateIfChanged( + $hash, 'scheduling-schedules_event_' . $event_id + +#. ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') + . '_' + . $v->{type}, + join( ',', @{ $v->{weekdays} } ) + ) if ( ref($v) eq 'HASH' ); + } + } + + } + ; # fi scheduled_events + + my $winter_mode = 'awake'; do { #Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name}; @@ -815,10 +1005,12 @@ sub WriteReadings { && ( $decode_json->{settings}[$settings]{name} =~ /schedules_paused_until_?\d?$/ || $decode_json->{settings}[$settings]{name} eq 'eco_mode' - || $decode_json->{settings}[$settings]{name} eq 'winter_mode' - || $decode_json->{settings}[$settings]{name} eq 'operating_mode' - || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' - || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) + || $decode_json->{settings}[$settings]{name} eq 'winter_mode' + || $decode_json->{settings}[$settings]{name} eq 'operating_mode' + || $decode_json->{settings}[$settings]{name} eq + 'leakage_detection' + || $decode_json->{settings}[$settings]{name} eq + 'turn_on_pressure' ) ) { if ( $hash->{helper} @@ -829,22 +1021,50 @@ sub WriteReadings { { $decode_json->{settings}[$settings]{name} . '_id' } = $decode_json->{settings}[$settings]{id}; } + # check watering controler single schedules pause until - if ( $decode_json->{settings}[$settings]{name} eq 'schedules_paused_until' ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_paused_until', - $decode_json->{settings}[$settings]{value} ); + if ( $decode_json->{settings}[$settings]{name} eq + 'schedules_paused_until' ) + { + readingsBulkUpdateIfChanged( + $hash, + 'scheduling-schedules_paused_until', + $decode_json->{settings}[$settings]{value} + ); + } + ##### + #ic24 schedules pause until + if ( $decode_json->{settings}[$settings]{name} =~ + /schedules_paused_until_?(\d)?$/ ) + { + #my $ventil = substr($decode_json->{settings}[$settings]{name}, -1); # => 1 - 6 + # check if empty, clear scheduling-scheduled_watering_next_start_x + readingsBulkUpdateIfChanged( + $hash, + 'scheduling-' . $decode_json->{settings}[$settings]{name}, + $decode_json->{settings}[$settings]{value} + ); + +# CommandAttr( undef, $name . " scheduling-scheduled_watering_next_start_") if ($decode_json->{settings}[$settings]{value} eq '' ) } + #TODO: Readings und Setter ?! # save electronid pressure pump settings as readings - if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' - || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' - || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) { - readingsBulkUpdateIfChanged( $hash, $decode_json->{settings}[$settings]{name}, - $decode_json->{settings}[$settings]{value} ); + if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' + || $decode_json->{settings}[$settings]{name} eq + 'leakage_detection' + || $decode_json->{settings}[$settings]{name} eq + 'turn_on_pressure' ) + { + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{settings}[$settings]{name}, + $decode_json->{settings}[$settings]{value} + ); } - # save winter mode as reading + # save winter mode as reading if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) { readingsBulkUpdateIfChanged( $hash, 'winter_mode', $decode_json->{settings}[$settings]{value} ); @@ -853,6 +1073,20 @@ sub WriteReadings { } } + if ( defined( $decode_json->{settings}[$settings]{name} ) + && $decode_json->{settings}[$settings]{name} eq 'valve_names' + && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) + { # or HASH ? + my @valves = @{ $decode_json->{settings}[$settings]{value} }; + foreach my $valve (@valves) { + + #Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; + readingsBulkUpdateIfChanged( $hash, + 'valve-valve_name_' . $valve->{"id"}, + $valve->{"name"} ); + } + } + if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" && $decode_json->{settings}[$settings]{name} eq 'starting_points' ) { @@ -913,54 +1147,226 @@ sub setState { : 'offline' ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - #online state water control - # zeitplan -> dauert pausiert wenn 2038-01-18T00:00:00.000Z + # ic24 / wc / electronic pump - # watering-watering_timer_1_state idle | scheduled | manual - # watering-watering_timer_1_duration 0 in sec - # scheduling-scheduled_watering_next_start XXX - # scheduling-scheduled_watering_end | end < NOW && duration = 0 => abbruch manuell - # scheduling-schedules_paused_until + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' + || AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ) + { + my @opened_valves; + my $state_string = ''; + my $nearst_irrigation = '2999-12-12 12:00'; + my $has_schedule = 0; + my $longest_duration = 0; + my $processed_item = ''; + my $error_type = 'ok'; + my @valves_connected = + AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + ? split( ',', ReadingsVal( $name, 'ic24-valves_connected', '' ) ) + : '1'; - - # 1. Ventil geschlossen, Zeitplan pausiert. - # App zeigt: nichts (wenn vorher ein Zeitplan abgebrochen wurde, steht da "Unterbrochen xx:yy - zz:aa") - # 2. Ventil geschlossen, Zeitplan aktiv. - # App zeigt: "Nächste Bewässerung heute um xx:yy Uhr" (wenn vorher ein Zeitplan abgebrochen wurde, steht da vorher auch "Unterbrochen xx:yy - zz:aa") - # 3. Ventil manuell geoeffnet, späterer Zeitplan aktiv. - # Wird bewässert xx Minuten verbleibend" und "Nächste Bewässerung heute um xx:yy Uhr" - # 4. Ventil manuell geoeffnet, Zeitpläne deaktiviert. - # App zeigt: "Wird bewässert xx Minuten verbleibend" - if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ){ - my $state_string = ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 ) =~ - m{\A[1-9]([0-9]+)?\z}xms - # offen - ? - ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # leer ( zeitplan aktiv ... ) - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash, 'next watering: %s')), (ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )/60), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '')) ) - # zeitplan pausiert - : - ( ReadingsVal($name, 'scheduling-schedules_paused_until', '') eq '2038-01-18T00:00:00.000Z') - # pause bis dauerhaft - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash , 'schedule permanently paused')), (ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )/60) ) - # naechter termin - : sprintf( RigReadingsValue($hash , 'paused until %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')) ) - # zu - : - ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # zeitplan aktiv - ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') ) ) - # zeitplan pausiert - : RigReadingsValue($hash, 'closed') - ; - # state offline | override - $state_string = 'offline' if ($online_state eq 'offline'); - - readingsBulkUpdate( - $hash, 'state', RigReadingsValue( $hash, $state_string ) ); + $has_schedule = 1 + if ( ReadingsVal( $name, 'scheduling-schedules_events_count', '' ) ne + '' ); + for (@valves_connected) { # valves 1 or 1..6 + ## add to opened ventils, if watering active + push @opened_valves, + $_ + if ( + ( + ( + ReadingsVal( $name, + "watering-watering_timer_" . $_ . "_duration", 0 ) + =~ m{\A[1-9]([0-9]+)?\z}xms + ) ? $_ : 0 + ) > 0 + ); + ## set error type (pumpe required) + $error_type = + ReadingsVal( $name, 'error-valve_error_' . $_ . '_type', 'error' ) + if ( + ReadingsVal( $name, 'error-valve_error_' . $_ . '_type', + 'error' ) ne 'ok' + ); + ## find longest irrigation duration + $longest_duration = + ReadingsVal( $name, + "watering-watering_timer_" . $_ . "_irrigation_left", 0 ) + if ( + ( + ReadingsVal( $name, + "watering-watering_timer_" . $_ . "_duration", 0 ) =~ + m{\A[1-9]([0-9]+)?\z}xms + && ReadingsVal( $name, + "watering-watering_timer_" . $_ . "_duration", 0 ) > 0 + && ReadingsVal( $name, + "watering-watering_timer_" . $_ . "_duration", 0 ) > + $longest_duration + ) + ); + + # y-m-d h:m + $processed_item = + AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + ? RigReadingsValue( + $hash, + ReadingsVal( + $name, 'scheduling-schedules_paused_until_' . $_, '' + ) + ) + : RigReadingsValue( $hash, + ReadingsVal( $name, 'scheduling-schedules_paused_until', '' ) ); + + Log3 $name, 5, "[DEBUG] - process: $processed_item"; + Log3 $name, 5, + "[DEBUG] - next_start: " + . ReadingsVal( $name, 'scheduling-scheduled_watering_next_start', + '' ); # n/a RigReadingsValue( $hash, 'n/a') + # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) + if ( + ReadingsVal( $name, 'scheduling-scheduled_watering_next_start', + '' ) eq RigReadingsValue( $hash, 'n/a' ) + ) + { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until + Log3 $name, 5, "[DEBUG] - next_start: empty "; + Log3 $name, 5, + "[DEBUG] - empty pro item " + . Time::Piece->strptime( $processed_item, + "%Y-%m-%d %H:%M:%S" ); + Log3 $name, 5, + "[DEBUG] - empty nearst " + . Time::Piece->strptime( $nearst_irrigation, + "%Y-%m-%d %H:%M:%S" ); + $nearst_irrigation = $processed_item + if ( + Time::Piece->strptime( $processed_item, + "%Y-%m-%d %H:%M:%S" ) < + Time::Piece->strptime( $nearst_irrigation, + "%Y-%m-%d %H:%M:%S" ) + && $has_schedule + && Time::Piece->strptime( $processed_item, + "%Y-%m-%d %H:%M:%S" ) > Time::Piece->new + ); + } + else { + $nearst_irrigation = ReadingsVal( $name, + 'scheduling-scheduled_watering_next_start', '' ); + } + Log3 $name, 5, "[DEBUG] - choosed nearst: $nearst_irrigation"; + + } # for + # override state 4 extendedstates + if ( AttrVal( $name, "extendedState", 0 ) == 1 ) { + if ( scalar(@opened_valves) > 0 ) { + ## valve 1 will be ir.. 23 minutes remaining + for (@valves_connected) { + $state_string .= sprintf( + RigReadingsValue( $hash, 'valve' ) . ' ' + . $_ . ' ' + . ( + RigReadingsValue( $hash, + 'watering. %.f minutes left' ) + . '
' + ), + ( + ReadingsVal( $name, + 'watering-watering_timer_' . $_ . '_duration', + 0 ) / 60 + ) + ); + } # /for + } + else { + $state_string .= RigReadingsValue( $hash, 'closed' ); + } + $state_string .= + ($has_schedule) + ? sprintf( + RigReadingsValue( $hash, 'next watering: %s' ), + RigReadingsValue( + $hash, + ReadingsVal( + $name, 'scheduling-scheduled_watering_next_start', '' + ) + ) + ) + : sprintf( + RigReadingsValue( $hash, 'paused until %s' ), + $nearst_irrigation + ); + + #TODO: Write state format for ventil 1-@valces_connected -> map ? + CommandAttr( + undef, $name . ' stateFormat + { + + } + ' + ) if ( AttrVal( $name, 'stateFormat', 'none' ) eq 'none' ); + } + else { + Log3 $name, 5, + "[DEBUG] - Offene Ventile :" + . scalar(@opened_valves) + . " laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; + $state_string = scalar(@opened_valves) > 0 + + # offen + ? sprintf( + ( RigReadingsValue( $hash, 'watering. %.f minutes left' ) ), + $longest_duration / 60 + ) + + # zu + : ( $has_schedule + && $nearst_irrigation ne '2999-12-12 12:00' ) + +# zeitplan aktiv +# ? ( $nearst_irrigation eq '2038-01-18 00:00') sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) + ? ( $nearst_irrigation eq RigReadingsValue( $hash, 'n/a' ) + || $nearst_irrigation =~ '2038-01-18.*' ) + + # dauerhaft pausiert + ? sprintf( + ( + RigReadingsValue( $hash, 'closed' ) . '. ' + . RigReadingsValue( + $hash, 'schedule permanently paused' + ) + ) + ) + + # naechster zeutplan + : ( + ReadingsVal( $name, + 'scheduling-scheduled_watering_next_start', '' ) eq + RigReadingsValue( $hash, 'n/a' ) + ) ? sprintf( + RigReadingsValue( $hash, 'paused until %s' ), + $nearst_irrigation + ) + : sprintf( + ( + RigReadingsValue( $hash, 'closed' ) . '. ' + . RigReadingsValue( $hash, 'next watering: %s' ) + ), + $nearst_irrigation + ) + + # zeitplan pausiert + : RigReadingsValue( $hash, 'closed' ); + + # state offline | override + $state_string = 'offline' if ( $online_state eq 'offline' ); + $state_string = + ( $error_type ne 'ok' ) ? $error_type : $state_string; + + } + readingsBulkUpdate( $hash, 'state', + RigReadingsValue( $hash, $state_string ) ); } + # Sensor / Sensor 2 if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ) { my $state_string = ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq @@ -980,64 +1386,17 @@ sub setState { if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq 'sensor' ); -# if ( $online_state eq 'offline') { -# readingsBulkUpdate( $hash, 'humidity-humidity', '-1' ); -# readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# } #online state sensor I II readingsBulkUpdate( $hash, 'state', - $online_state eq 'online' ? RigReadingsValue( $hash, $state_string) : RigReadingsValue( $hash, 'offline') ); + $online_state eq 'online' + ? RigReadingsValue( $hash, $state_string ) + : RigReadingsValue( $hash, 'offline' ) ); } - readingsBulkUpdate( - $hash, 'state', - 'scheduled watering next start: ' - . ( - ReadingsVal( - $name, 'scheduling-scheduled_watering_next_start', - 'no timer' - ) - ) - ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - readingsBulkUpdate( $hash, 'state', ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - #electronic water pump - if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ) { # | ok | pump_not_filled (Pumpe nicht gefüllt) - my $state_string = ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 ) =~ - m{\A[1-9]([0-9]+)?\z}xms - # offen - ? - ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # leer ( zeitplan aktiv ... ) - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash, 'next watering: %s')), (ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )/60), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '')) ) - # zeitplan pausiert - : - ( ReadingsVal($name, 'scheduling-schedules_paused_until', '') eq '2038-01-18T00:00:00.000Z') - # pause bis dauerhaft - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash , 'schedule permanently paused')), (ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )/60) ) - # naechter termin - : sprintf( RigReadingsValue($hash , 'paused until %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')) ) - # zu - : - ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # zeitplan aktiv - ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') ) ) - # zeitplan pausiert - : RigReadingsValue($hash, 'closed') - ; - # state offline | override - $state_string = 'offline' if ($online_state eq 'offline'); - # check valv error, override state - my $error_type = ReadingsVal( $name, 'error-valve_error_1_type', 'ok' ); - $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; - - readingsBulkUpdate( - $hash, 'state', RigReadingsValue( $hash, $state_string ) ); - } return; } @@ -1051,21 +1410,22 @@ sub ReadingLangGerman { my $name = $hash->{NAME}; my %langGermanMapp = ( - 'ok_cutting' => 'mähen', - 'paused' => 'pausiert', - 'ok_searching' => 'suche Ladestation', - 'ok_charging' => 'lädt', - 'ok_leaving' => 'unterwegs zum Startpunkt', - 'wait_updating' => 'wird aktualisiert ...', - 'wait_power_up' => 'wird eingeschaltet ...', - 'parked_timer' => 'geparkt nach Zeitplan', - 'parked_park_selected' => 'geparkt', - 'off_disabled' => 'der Mäher ist ausgeschaltet', - 'off_hatch_open' => 'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich', - 'unknown' => 'unbekannter Status', - 'error' => 'Fehler', - 'error_at_power_up' => 'Neustart ...', - 'off_hatch_closed' => 'Deaktiviert. Manueller Start erforderlich', + 'ok_cutting' => 'mähen', + 'paused' => 'pausiert', + 'ok_searching' => 'suche Ladestation', + 'ok_charging' => 'lädt', + 'ok_leaving' => 'unterwegs zum Startpunkt', + 'wait_updating' => 'wird aktualisiert ...', + 'wait_power_up' => 'wird eingeschaltet ...', + 'parked_timer' => 'geparkt nach Zeitplan', + 'parked_park_selected' => 'geparkt', + 'off_disabled' => 'der Mäher ist ausgeschaltet', + 'off_hatch_open' => + 'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich', + 'unknown' => 'unbekannter Status', + 'error' => 'Fehler', + 'error_at_power_up' => 'Neustart ...', + 'off_hatch_closed' => 'Deaktiviert. Manueller Start erforderlich', 'ok_cutting_timer_overridden' => 'manuelles mähen', 'parked_autotimer' => 'geparkt durch SensorControl', 'parked_daily_limit_reached' => 'abgeschlossen', @@ -1103,55 +1463,64 @@ sub ReadingLangGerman { 'guide_2_not_found' => 'SK 2 nicht gefunden', 'guide_3_not_found' => 'SK 3 nicht gefunden', 'difficult_finding_home' => 'Problem die Ladestation zu finden', - 'guide_calibration_accomplished' => 'Kalibrierung des Suchkabels beendet', - 'guide_calibration_failed' => 'Kalibrierung des Suchkabels fehlgeschlagen', - 'temporary_battery_problem' => 'kurzzeitiges Batterieproblem', - 'battery_problem' => 'Batterieproblem', - 'alarm_mower_switched_off' => 'Alarm! Mäher ausgeschalten', - 'alarm_mower_stopped' => 'Alarm! Mäher gestoppt', - 'alarm_mower_lifted' => 'Alarm! Mäher angehoben', - 'alarm_mower_tilted' => 'Alarm! Mäher gekippt', - 'connection_changed' => 'Verbindung geändert', - 'connection_not_changed' => 'Verbindung nicht geändert', - 'com_board_not_available' => 'COM Board nicht verfügbar', - 'slipped' => 'rutscht', - 'out_of_operation' => 'ausser Betrieb', - 'replace_now' => 'kritischer Batteriestand, wechseln Sie jetzt', - 'low' => 'niedrig', - 'ok' => 'ok', - 'no_source' => 'ok', - 'mower_charging' => 'Mäher wurde geladen', - 'completed_cutting_autotimer' => 'Sensor Control erreicht', - 'week_timer' => 'Wochentimer erreicht', - 'countdown_timer' => 'Stoppuhr Timer', - 'undefined' => 'unklar', - 'unknown' => 'unklar', - 'status_device_unreachable' => 'Gerät ist nicht in Reichweite', - 'status_device_alive' => 'Gerät ist in Reichweite', - 'bad' => 'schlecht', - 'poor' => 'schwach', - 'good' => 'gut', - 'undefined' => 'unklar', - 'idle' => 'nichts zu tun', - 'firmware_cancel' => 'Firmwareupload unterbrochen', - 'firmware_upload' => 'Firmwareupload', - 'unsupported' => 'nicht unterstützt', - 'up_to_date' => 'auf dem neusten Stand', - 'mower' => 'Mäher', - 'watering_computer' => 'Bewässerungscomputer', - 'no_frost' => 'kein Frost', - 'open' => 'offen', - 'closed' => 'geschlossen', - 'included' => 'inbegriffen', - 'active' => 'aktiv', - 'inactive' => 'nicht aktiv', - 'hibernate' => 'Winterschlaf', - 'awake' => 'Aufgewacht', - 'schedule permanently paused' => 'Zeitplan dauerhaft pausiert', - 'paused until %s' => 'pausiert bis %s', - 'will be irrigated %.f minutes remaining.'=> 'Wird bewässert. %.f Minuten verbleibend.', - 'next watering: %s' => 'Nächste Bewässerung: %s', - 'pump_not_filled' => 'Pumpe nicht gefüllt', + 'guide_calibration_accomplished' => + 'Kalibrierung des Suchkabels beendet', + 'guide_calibration_failed' => + 'Kalibrierung des Suchkabels fehlgeschlagen', + 'temporary_battery_problem' => 'kurzzeitiges Batterieproblem', + 'battery_problem' => 'Batterieproblem', + 'alarm_mower_switched_off' => 'Alarm! Mäher ausgeschalten', + 'alarm_mower_stopped' => 'Alarm! Mäher gestoppt', + 'alarm_mower_lifted' => 'Alarm! Mäher angehoben', + 'alarm_mower_tilted' => 'Alarm! Mäher gekippt', + 'connection_changed' => 'Verbindung geändert', + 'connection_not_changed' => 'Verbindung nicht geändert', + 'com_board_not_available' => 'COM Board nicht verfügbar', + 'slipped' => 'rutscht', + 'out_of_operation' => 'ausser Betrieb', + 'replace_now' => 'kritischer Batteriestand, wechseln Sie jetzt', + 'low' => 'niedrig', + 'ok' => 'ok', + 'no_source' => 'ok', + 'mower_charging' => 'Mäher wurde geladen', + 'completed_cutting_autotimer' => 'Sensor Control erreicht', + 'week_timer' => 'Wochentimer erreicht', + 'countdown_timer' => 'Stoppuhr Timer', + 'undefined' => 'unklar', + 'unknown' => 'unklar', + 'status_device_unreachable' => 'Gerät ist nicht in Reichweite', + 'status_device_alive' => 'Gerät ist in Reichweite', + 'bad' => 'schlecht', + 'poor' => 'schwach', + 'good' => 'gut', + 'undefined' => 'unklar', + 'idle' => 'nichts zu tun', + 'firmware_cancel' => 'Firmwareupload unterbrochen', + 'firmware_upload' => 'Firmwareupload', + 'unsupported' => 'nicht unterstützt', + 'up_to_date' => 'auf dem neusten Stand', + 'mower' => 'Mäher', + 'watering_computer' => 'Bewässerungscomputer', + 'no_frost' => 'kein Frost', + 'open' => 'offen', + 'closed' => 'geschlossen', + 'included' => 'inbegriffen', + 'active' => 'aktiv', + 'inactive' => 'nicht aktiv', + 'hibernate' => 'Winterschlaf', + 'awake' => 'Aufgewacht', + 'schedule permanently paused' => 'Zeitplan dauerhaft pausiert', + 'paused until %s' => 'pausiert bis %s', + 'watering. %.f minutes left' => + 'Wird bewässert. %.f Minuten verbleibend.', + 'next watering: %s' => 'Nächste Bewässerung: %s', + 'n/a' => 'nicht verfügbar', + 'pump_not_filled' => 'Pumpe nicht gefüllt', + 'clean_fine_filter' => 'Filter reinigen', + 'concurrent_limit_reached' => + 'Grenze gleichzeitig geöffneter Ventile erreicht', + 'low_battery_prevents_starting' => + 'Niedrieger Batteriestand verhindert Bewässerung', ); if ( @@ -1302,320 +1671,1002 @@ sub SetPredefinedStartPoints { =item device =item summary Modul to control GardenaSmart Devices -=item summary_DE Modul zur Steuerung von GardenaSmartgeräten - +=item summary_DE Modul zur Steuerung von GardenaSmartgeräten =begin html - +

GardenaSmartDevice

- +
+ +
  • parkUntilFurtherNotice - Parken des Mähers und Aussetzen des Zeitplans
  • +
  • parkUntilNextTimer - Parken bis zum nächsten Start nach Zeitplan
  • +
  • startOverrideTimer n - Manuelles Mähen für n Minuten (z.B. 60 = 1h, 1440 = 24h, 4320 = 72h)
  • +
  • startResumeSchedule - Zeitplan wieder aktivieren
  • +
  • startpoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
      - Readings +
    • set NAME startpoint enable 1
    • +
    • set NAME startpoint disable 3 enable 1
    • +
    +
  • + +
  • cancelOverride - (Manuelle) Bewässerung stoppen
  • +
  • manualButtonTime n - Bewässerungsdauer für manuellen Knopf auf n Minuten setzen (0 schaltet den Knopf aus)
  • +
  • manualOverride n - Manuelle Bewässerung für n Minuten
  • +
  • resetValveErrors - Ventilfehler zurücksetzen
  • +
  • resumeSchedule - Zeitplan wieder aktivieren
  • +
  • stopSchedule n - Zeitplan anhalten für n Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als "dauerhaft" interpretiert)
  • + +
  • operating_mode -Steuert den Operation Mode. Zeitgesteuert wird in Kombination mit dem Wochenzeitplan oder mit "manualOverride" genutzt, automatisch bedeutet, dass die Pumpe immer aktiv ist und die Bewässerung abhängig vom Wert "Einschaltdruck" startet. automatic|scheduled
  • +
  • leakage_detection - Steuert die Lekage-Erkennung.
    Hierdurch wird eine Pumpenabschaltung erreicht, sollte die Pumpe unkontrollierten Wasserverlust feststellen. watering|washing_machine|domestic_water_supply|off
  • +
  • turn_on_pressure - Einschaltdruck 2.0 - 3.0 Steuert den Einschaltdruck in Scheduled und Automatic Mode. Fällt der Druck bei der Bewässerung unter diese wert, startet die Pumpe, ist der Wert dauerhaft über diesem Wert und es finden kein Durchfluss statt, geht die Pumpe in Standby
  • + +
  • cancelOverrideValve1 - (Manuelle) Bewässerung an Ventil 1 stoppen
  • +
  • cancelOverrideValve2 - (Manuelle) Bewässerung an Ventil 2 stoppen
  • +
  • cancelOverrideValve3 - (Manuelle) Bewässerung an Ventil 3 stoppen
  • +
  • cancelOverrideValve4 - (Manuelle) Bewässerung an Ventil 4 stoppen
  • +
  • cancelOverrideValve5 - (Manuelle) Bewässerung an Ventil 5 stoppen
  • +
  • cancelOverrideValve6 - (Manuelle) Bewässerung an Ventil 6 stoppen
  • +
  • closeAllValves - Alle Ventile schliessen
  • +
  • manualDurationValve1 n - Ventil 1 für n Minuten öffnen
  • +
  • manualDurationValve2 n - Ventil 2 für n Minuten öffnen
  • +
  • manualDurationValve3 n - Ventil 3 für n Minuten öffnen
  • +
  • manualDurationValve4 n - Ventil 4 für n Minuten öffnen
  • +
  • manualDurationValve5 n - Ventil 5 für n Minuten öffnen
  • +
  • manualDurationValve6 n - Ventil 6 für n Minuten öffnen
  • +
  • resumeScheduleValve n - Zeitplan für Ventil n wieder aktivieren
  • +
  • stopScheduleValve n m - Zeitplan für Ventil n anhalten für m Stunden (Default: 2038-01-18T00:00:00.000Z durch Gardena-App als "dauerhaft" interpretiert)
  • + +
  • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
  • + +
  • refresh temperature|humidity|light* +
    + Wert für Temperatur, Feuchtigkeit oder Helligkeit aktualisieren +
    *nur bei Sensor type 1 verfügbar +
  • + + + +
    +
    + + +

    + Readings (model = power) + +

    + Readings (model = electronic_pressure_pump) + +


    + + Attribute (alle Modelle) + +


    + set (model = mower) + +

    + set (model = watering_computer) + +

    + set (model = ic24) + +

    + set (model = sensor) + +

    + set (model = sensor2) + +

    + set (model = power) + +

    + set (model = electronic_pressure_pump) + + =end html_DE + =for :application/json;q=META.json 74_GardenaSmartDevice.pm { "abstract": "Modul to control GardenaSmart Devices", @@ -1633,7 +2684,7 @@ sub SetPredefinedStartPoints { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.5.2", + "version": "v2.6.1", "author": [ "Marko Oldenburg " ],