commit
fb3a690993
3972
CHANGELOG.md
Normal file
3972
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -441,7 +441,9 @@ sub Set {
|
||||
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 {
|
||||
@ -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>"
|
||||
],
|
||||
|
@ -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;
|
||||
|
||||
@ -487,8 +489,10 @@ sub Set {
|
||||
### Watering_pressure_pump
|
||||
elsif ( lc $cmd eq 'operating_mode' ) {
|
||||
my $op_mode = $aArg->[0];
|
||||
$payload = '"settings":{"name":"operating_mode",'
|
||||
.'"value":"'.$op_mode.'",'
|
||||
$payload =
|
||||
'"settings":{"name":"operating_mode",'
|
||||
. '"value":"'
|
||||
. $op_mode . '",'
|
||||
. '"device":"'
|
||||
. $hash->{DEVICEID} . '"}';
|
||||
$abilities = 'watering_pressure_pump_settings';
|
||||
@ -496,8 +500,10 @@ sub Set {
|
||||
}
|
||||
elsif ( lc $cmd eq 'leakage_detection' ) {
|
||||
my $leakdetection_mode = $aArg->[0];
|
||||
$payload = '"settings":{"name":"leakage_detection",'
|
||||
.'"value":"'.$leakdetection_mode.'",'
|
||||
$payload =
|
||||
'"settings":{"name":"leakage_detection",'
|
||||
. '"value":"'
|
||||
. $leakdetection_mode . '",'
|
||||
. '"device":"'
|
||||
. $hash->{DEVICEID} . '"}';
|
||||
$abilities = 'watering_pressure_pump_settings';
|
||||
@ -505,16 +511,17 @@ sub Set {
|
||||
}
|
||||
elsif ( lc $cmd eq 'turn_on_pressure' ) {
|
||||
my $turnonpressure = $aArg->[0];
|
||||
$payload = '"settings":{"name":"turn_on_pressure",'
|
||||
.'"value":"'.$turnonpressure.'",'
|
||||
$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": {}';
|
||||
$payload = '"name":"reset_valve_errors",' . ' "parameters": {}';
|
||||
$abilities = 'error';
|
||||
}
|
||||
|
||||
@ -566,20 +573,28 @@ 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'))) {
|
||||
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'))) {
|
||||
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,61 +816,82 @@ 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" ) {
|
||||
readingsBulkUpdateIfChanged(
|
||||
$hash,
|
||||
$decode_json->{abilities}[$abilities]{name} . '-'
|
||||
$decode_json->{abilities}[$abilities]{name}
|
||||
. '-'
|
||||
. $propertie->{name} . '_'
|
||||
. $r,
|
||||
RigReadingsValue( $hash, $v )
|
||||
);
|
||||
} else {
|
||||
}
|
||||
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]
|
||||
&& 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} ) {
|
||||
push @soll, $v if $r eq 'id'; # cloud hat SOLL
|
||||
@ -857,19 +900,30 @@ sub WriteReadings {
|
||||
|
||||
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) ) {
|
||||
my $schedule_step_int = 0;
|
||||
@ -877,48 +931,61 @@ sub WriteReadings {
|
||||
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
|
||||
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) ){
|
||||
&& 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.*/);
|
||||
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;
|
||||
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
|
||||
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
|
||||
$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} );
|
||||
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} );
|
||||
|| $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 ?
|
||||
&& 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,46 +1145,106 @@ 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 '' );
|
||||
$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";
|
||||
|
||||
@ -1102,47 +1254,110 @@ sub setState {
|
||||
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));
|
||||
$state_string .= sprintf(
|
||||
RigReadingsValue( $hash, 'valve' ) . ' '
|
||||
. $_ . ' '
|
||||
. (
|
||||
RigReadingsValue( $hash,
|
||||
'watering. %.f minutes left' )
|
||||
. '</br>'
|
||||
),
|
||||
(
|
||||
ReadingsVal( $name,
|
||||
'watering-watering_timer_' . $_ . '_duration',
|
||||
0 ) / 60
|
||||
)
|
||||
);
|
||||
} # /for
|
||||
} else {
|
||||
}
|
||||
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);
|
||||
$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
|
||||
: ( $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.*')
|
||||
? ( $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 =
|
||||
( $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>"
|
||||
],
|
||||
|
@ -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
36
hooks/commit-msg
Executable 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
18
hooks/post-commit
Executable 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
|
Loading…
Reference in New Issue
Block a user