testing #83

Merged
marko merged 7 commits from testing into main 2023-01-10 10:01:11 +01:00
6 changed files with 4602 additions and 352 deletions

3972
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -437,11 +437,13 @@ sub Set {
DeletePassword($hash);
}
elsif ( lc $cmd eq 'debughelper') {
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");
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} ) )
@ -1574,7 +1575,7 @@ sub DeletePassword {
],
"release_status": "stable",
"license": "GPL_2",
"version": "v2.5.2",
"version": "v2.6.0",
"author": [
"Marko Oldenburg <fhemdevelopment@cooltux.net>"
],

View File

@ -197,12 +197,12 @@ 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} = '';
$hash->{helper}{_id} = '';
# IrrigationControl valve control max 6
@ -288,8 +288,10 @@ sub Set {
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;
@ -485,36 +487,41 @@ sub Set {
. $hash->{DEVICEID} . '"}';
}
### Watering_pressure_pump
elsif ( lc $cmd eq 'operating_mode') {
elsif ( lc $cmd eq 'operating_mode' ) {
my $op_mode = $aArg->[0];
$payload = '"settings":{"name":"operating_mode",'
.'"value":"'.$op_mode.'",'
.'"device":"'
. $hash->{DEVICEID}.'"}';
$payload =
'"settings":{"name":"operating_mode",'
. '"value":"'
. $op_mode . '",'
. '"device":"'
. $hash->{DEVICEID} . '"}';
$abilities = 'watering_pressure_pump_settings';
$service_id = $hash->{helper}->{ 'operating_mode_id' };
$service_id = $hash->{helper}->{'operating_mode_id'};
}
elsif ( lc $cmd eq 'leakage_detection') {
elsif ( lc $cmd eq 'leakage_detection' ) {
my $leakdetection_mode = $aArg->[0];
$payload = '"settings":{"name":"leakage_detection",'
.'"value":"'.$leakdetection_mode.'",'
.'"device":"'
. $hash->{DEVICEID}.'"}';
$payload =
'"settings":{"name":"leakage_detection",'
. '"value":"'
. $leakdetection_mode . '",'
. '"device":"'
. $hash->{DEVICEID} . '"}';
$abilities = 'watering_pressure_pump_settings';
$service_id = $hash->{helper}->{ 'leakage_detection_id' };
$service_id = $hash->{helper}->{'leakage_detection_id'};
}
elsif ( lc $cmd eq 'turn_on_pressure') {
elsif ( lc $cmd eq 'turn_on_pressure' ) {
my $turnonpressure = $aArg->[0];
$payload = '"settings":{"name":"turn_on_pressure",'
.'"value":"'.$turnonpressure.'",'
.'"device":"'
. $hash->{DEVICEID}.'"}';
$payload =
'"settings":{"name":"turn_on_pressure",'
. '"value":"'
. $turnonpressure . '",'
. '"device":"'
. $hash->{DEVICEID} . '"}';
$abilities = 'watering_pressure_pump_settings';
$service_id = $hash->{helper}->{ 'turn_on_pressure_id' };
$service_id = $hash->{helper}->{'turn_on_pressure_id'};
}
elsif ( lc $cmd eq 'resetvalveerrors') {
$payload = '"name":"reset_valve_errors",'
.' "parameters": {}';
elsif ( lc $cmd eq 'resetvalveerrors' ) {
$payload = '"name":"reset_valve_errors",' . ' "parameters": {}';
$abilities = 'error';
}
@ -566,21 +573,29 @@ sub Set {
'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 .= '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 .=
'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' )
'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 '
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 '
foreach my $valve (
split( ',', ReadingsVal( $name, 'ic24-valves_connected', '1' ) ) )
{
$list .= ' cancelOverrideValve' . $valve . ':noArg '
if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' );
}
@ -708,7 +723,11 @@ sub WriteReadings {
$hash,
$decode_json->{abilities}[$abilities]{name} . '-'
. $propertie->{name},
(defined ($propertie->{value} ) eq '') ? RigReadingsValue( $hash, 'n/a') : "".RigReadingsValue( $hash, $propertie->{value} ) # cast all data to string with ""
( defined( $propertie->{value} ) eq '' )
? RigReadingsValue( $hash, 'n/a' )
: ""
. RigReadingsValue( $hash,
$propertie->{value} ) # cast all data to string with ""
)
if ( exists( $propertie->{value} )
&& $decode_json->{abilities}[$abilities]{name} . '-'
@ -735,7 +754,9 @@ sub WriteReadings {
$hash,
$decode_json->{abilities}[$abilities]{name} . '-'
. $propertie->{name},
"".RigReadingsValue( $hash, $propertie->{value} ) # cast all data to string with ""
""
. RigReadingsValue( $hash,
$propertie->{value} ) # cast all data to string with ""
)
if (
defined( $propertie->{value} )
@ -762,7 +783,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')
@ -794,131 +816,176 @@ sub WriteReadings {
. $propertie->{name} eq 'ic24-valves_master_config' );
if ( ref( $propertie->{value} ) eq "HASH" ) {
my $sub_state = 0; my $sub_value = 0;
my $sub_state = 0;
my $sub_value = 0;
while ( my ( $r, $v ) = each %{ $propertie->{value} } ) {
if ( ref( $v ) ne "HASH" ) {
if ( ref($v) ne "HASH" ) {
readingsBulkUpdateIfChanged(
$hash,
$decode_json->{abilities}[$abilities]{name} . '-'
$decode_json->{abilities}[$abilities]{name}
. '-'
. $propertie->{name} . '_'
. $r,
RigReadingsValue( $hash, $v )
);
} else {
while ( my ( $i_r, $i_v ) = each %{ $v } ) {
}
else {
while ( my ( $i_r, $i_v ) = each %{$v} ) {
readingsBulkUpdateIfChanged(
$hash,
$decode_json->{abilities}[$abilities]{name} . '-'
$decode_json->{abilities}[$abilities]{name}
. '-'
. $propertie->{name} . '_'
. $r . '_' . $i_r,
. $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
( $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'
);
&& $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]
&& 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=();
my @soll = ();
my @ist = ();
my @tmp_ist = ();
for my $cloud_schedules ( @{ $decode_json->{scheduled_events} } ) {
while ( my ( $r, $v ) = each %{ $cloud_schedules } ) {
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
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] $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)
if (
(
scalar(@soll) != scalar( @ist / 2 )
&& scalar(@soll) > 0
&& scalar(@ist) > 0)
|| (scalar(@ist) eq 2 && scalar(@soll) eq 1 )){
&& scalar(@ist) > 0
)
|| ( scalar(@ist) eq 2 && scalar(@soll) eq 1 )
)
{
@tmp_ist = @ist;
while(my $element = shift(@soll)) {
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
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.*/);
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;
} # 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
$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" : '')
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
) 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' );
};
};
join( ',', @{ $v->{weekdays} } )
) if ( ref($v) eq 'HASH' );
}
}
}; # fi scheduled_events
}
; # fi scheduled_events
my $winter_mode;
@ -934,8 +1001,10 @@ sub WriteReadings {
|| $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
'leakage_detection'
|| $decode_json->{settings}[$settings]{name} eq
'turn_on_pressure' )
)
{
if ( $hash->{helper}
@ -946,29 +1015,49 @@ 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)?$/) {
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 '' )
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 ?!
#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} );
|| $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
if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) {
readingsBulkUpdateIfChanged( $hash, 'winter_mode',
@ -980,11 +1069,14 @@ 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 ) {
&& 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"},
readingsBulkUpdateIfChanged( $hash,
'valve-valve_name_' . $valve->{"id"},
$valve->{"name"} );
}
}
@ -1053,96 +1145,219 @@ sub setState {
if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24'
|| AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer'
|| AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ){
|| 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 $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';
my @valves_connected =
AttrVal( $name, 'model', 'unknown' ) eq 'ic24'
? split( ',', ReadingsVal( $name, 'ic24-valves_connected', '' ) )
: '1';
$has_schedule = 1 if ( ReadingsVal($name, 'scheduling-schedules_events_count', '') ne '' );
for (@valves_connected){ # valves 1 or 1..6
$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 );
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');
$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 ) );
$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', ''));
$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')
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
if (
ReadingsVal( $name, 'scheduling-scheduled_watering_next_start',
'' ) eq RigReadingsValue( $hash, 'n/a' )
)
} else {
$nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '');
{ # 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){
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') .'</br>'), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60));
for (@valves_connected) {
$state_string .= sprintf(
RigReadingsValue( $hash, 'valve' ) . ' '
. $_ . ' '
. (
RigReadingsValue( $hash,
'watering. %.f minutes left' )
. '</br>'
),
(
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);
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
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";
'
) 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)
? 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.*')
: ( $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')) )
? 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 )
: (
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')
;
: RigReadingsValue( $hash, 'closed' );
# state offline | override
$state_string = 'offline' if ($online_state eq 'offline');
$state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string;
$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 ) );
readingsBulkUpdate( $hash, 'state',
RigReadingsValue( $hash, $state_string ) );
}
# Sensor / Sensor 2
@ -1167,7 +1382,9 @@ sub setState {
#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',
@ -1197,7 +1414,8 @@ sub ReadingLangGerman {
'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',
'off_hatch_open' =>
'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich',
'unknown' => 'unbekannter Status',
'error' => 'Fehler',
'error_at_power_up' => 'Neustart ...',
@ -1239,8 +1457,10 @@ 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',
'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',
@ -1285,13 +1505,16 @@ sub ReadingLangGerman {
'awake' => 'Aufgewacht',
'schedule permanently paused' => 'Zeitplan dauerhaft pausiert',
'paused until %s' => 'pausiert bis %s',
'watering. %.f minutes left' => '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',
'concurrent_limit_reached' =>
'Grenze gleichzeitig geöffneter Ventile erreicht',
'low_battery_prevents_starting' =>
'Niedrieger Batteriestand verhindert Bewässerung',
);
if (
@ -2455,7 +2678,7 @@ sub SetPredefinedStartPoints {
],
"release_status": "stable",
"license": "GPL_2",
"version": "v2.5.7",
"version": "v2.6.0",
"author": [
"Marko Oldenburg <fhemdevelopment@cooltux.net>"
],

View File

@ -1,2 +1,2 @@
UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm
UPD 2022-09-18_08:52:23 122934 FHEM/74_GardenaSmartDevice.pm
UPD 2023-01-10_09:49:28 49646 FHEM/73_GardenaSmartBridge.pm
UPD 2023-01-10_09:49:45 126305 FHEM/74_GardenaSmartDevice.pm

36
hooks/commit-msg Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
commit_msg=$(cat "${1:?Missing commit message file}")
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}
if ! echo "$commit_msg" | grep -Eq "^(build|chore|ci|docs|feat|feat!|fix|perf|refactor|revert|style|test)(\(.+\))?: .*$" ; then
echo "Invalid commit message"
exit 1
fi
echo "Commit message is valid!"

18
hooks/post-commit Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
set -eu
# destination of the final changelog file
OUTPUT_FILE=CHANGELOG.md
# generate the changelog
git --no-pager log --no-merges --format="### %s%d%n>%aD%n%n>Author: %aN (%aE)%n%n>Commiter: %cN (%cE)%n%n%b%n%N%n" > $OUTPUT_FILE
# prevent recursion!
# since a 'commit --amend' will trigger the post-commit script again
# we have to check if the changelog file has changed or not
res=$(git status --porcelain | grep -c ".\$OUTPUT_FILE$")
if [ "$res" -gt 0 ]; then
git add $OUTPUT_FILE
git commit --amend
echo "Populated Changelog in $OUTPUT_FILE"
fi