diff --git a/CHANGED b/CHANGED index 37eb437..2161d26 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - Reviewed-by: Marko Oldenburg + spellcheck + corrections diff --git a/FHEM/73_GardenaSmartBridge.pm b/FHEM/73_GardenaSmartBridge.pm index d3bec09..934335c 100644 --- a/FHEM/73_GardenaSmartBridge.pm +++ b/FHEM/73_GardenaSmartBridge.pm @@ -737,7 +737,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 +753,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; diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index ad92993..20da94d 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/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 @@ -166,6 +167,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; @@ -204,12 +206,12 @@ sub Define { $hash->{helper}{_id} = ''; # IrrigationControl valve control max 6 - $hash->{helper}{schedules_paused_until_1_id} = ''; - $hash->{helper}{schedules_paused_until_2_id} = ''; - $hash->{helper}{schedules_paused_until_3_id} = ''; - $hash->{helper}{schedules_paused_until_4_id} = ''; - $hash->{helper}{schedules_paused_until_5_id} = ''; - $hash->{helper}{schedules_paused_until_6_id} = ''; + $hash->{helper}{schedules_paused_until_1_id} = ''; + $hash->{helper}{schedules_paused_until_2_id} = ''; + $hash->{helper}{schedules_paused_until_3_id} = ''; + $hash->{helper}{schedules_paused_until_4_id} = ''; + $hash->{helper}{schedules_paused_until_5_id} = ''; + $hash->{helper}{schedules_paused_until_6_id} = ''; CommandAttr( undef, "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" ) @@ -561,16 +563,27 @@ 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' - 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' ); + $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' ); + + 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.?/ ); @@ -650,6 +663,7 @@ sub WriteReadings { 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 +683,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 +708,9 @@ 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 +725,17 @@ 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 +762,7 @@ 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,9 +794,10 @@ 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( + readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_' @@ -786,7 +806,7 @@ sub WriteReadings { ); } else { while ( my ( $i_r, $i_v ) = each %{ $v } ) { - readingsBulkUpdate( + readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_' @@ -797,12 +817,109 @@ sub WriteReadings { } } } + # 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 ); + + 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; do { @@ -834,7 +951,16 @@ sub WriteReadings { 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' @@ -844,7 +970,6 @@ sub WriteReadings { } # save winter mode as reading - if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) { readingsBulkUpdateIfChanged( $hash, 'winter_mode', $decode_json->{settings}[$settings]{value} ); @@ -852,6 +977,17 @@ sub WriteReadings { $winter_mode = $decode_json->{settings}[$settings]{value}; } } + + 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 +1049,103 @@ 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 + $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 +1165,15 @@ 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') ); } - 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; } @@ -1149,9 +1285,13 @@ sub ReadingLangGerman { '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.', + '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 +1442,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 +2455,7 @@ sub SetPredefinedStartPoints { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.5.2", + "version": "v2.5.7", "author": [ "Marko Oldenburg " ], diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index ff4f11a..249f831 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ -UPD 2022-06-29_20:30:48 49913 FHEM/73_GardenaSmartBridge.pm -UPD 2022-06-29_20:31:47 66815 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm +UPD 2022-09-18_08:52:23 122934 FHEM/74_GardenaSmartDevice.pm