12 Commits

Author SHA1 Message Date
2111939863 docs: add changelog file 2023-01-10 09:51:23 +01:00
c9a3cc9e1d docs: change verson numbers
change modul versions
2023-01-10 09:50:36 +01:00
b399fcd524 test: add hooks
hooks for commit test and create changelog
2023-01-10 09:48:39 +01:00
89bbb4bb10 Merge branch 'main' of git.cooltux.net:/FHEM/mod-GardenaSmart 2023-01-10 09:29:11 +01:00
801a1a468f Merge pull request 'testing' (#80) from testing into main
Reviewed-on: #80
2022-12-22 08:04:47 +01:00
eddcb708ba Merge pull request 'dev' (#79) from dev into testing
Reviewed-on: #79
Reviewed-by: Marko Oldenburg <marko@noreply@cooltux.net>
2022-11-14 20:34:36 +01:00
c7073b24b4 Merge pull request 'patch-fix_commandref_spell' (#78) from patch-fix_commandref_spell into dev
Reviewed-on: #78
Reviewed-by: Marko Oldenburg <marko@noreply@cooltux.net>
2022-10-14 09:01:55 +02:00
fe97f0b203 [translaten] - add commandref translation 2022-09-18 08:52:43 +02:00
eebe13bb7b spellcheck + corrections 2022-09-06 14:34:38 +02:00
a6174d9982 Merge pull request 'dev' (#77) from dev into testing
Reviewed-on: #77
Reviewed-by: Marko Oldenburg <marko@noreply@cooltux.net>
2022-09-06 14:26:24 +02:00
4cb9f2e50b Merge pull request 'dev' (#74) from dev into testing
Reviewed-on: #74
Reviewed-by: Marko Oldenburg <marko@noreply@cooltux.net>
2022-09-06 13:31:53 +02:00
ebb342d83f Merge branch 'dev' of git.cooltux.net:/FHEM/mod-GardenaSmart 2022-07-13 07:20:49 +02:00
7 changed files with 4623 additions and 373 deletions

View File

@ -1 +1 @@
[enhancement] - commandref
spellcheck + corrections

3972
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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>"
],

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;
@ -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 (
@ -1476,14 +1699,14 @@ sub SetPredefinedStartPoints {
<li><a id="GardenaSmartDevice-set-cancelOverride">cancelOverride</a> - stop (manual) watering</li>
<li><a id="GardenaSmartDevice-set-manualButtonTime">manualButtonTime</a> n - set watering time for manual button (0 disables button)</li>
<li><a id="GardenaSmartDevice-set-manualOverride">manualOverride</a> n - manual watering for n minutes</li>
<li><a id="GardenaSmartDevice-set-resetValveErrors">resetValveErrors</a> - Vreset valve errormessage</li>
<li><a id="GardenaSmartDevice-set-resetValveErrors">resetValveErrors</a> - reset valve errormessage</li>
<li><a id="GardenaSmartDevice-set-resumeSchedule">resumeSchedule</a> - enable schedule</li>
<li><a id="GardenaSmartDevice-set-stopSchedule">stopSchedule</a> n - disable schedule for n hours (Default: 2038-01-18T00:00:00.000Z, Gardena App reads it as
"permanently")</li>
<li><a id="GardenaSmartDevice-set-operating_mode">operating_mode</a> -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 </li>
<li><a id="GardenaSmartDevice-set-leakage_detection">leakage_detection</a> - Steuert die Lekage-Erkennung.</br> Hierdurch wird eine Pumpenabschaltung erreicht, sollte die Pumpe unkontrollierten Wasserverlust feststellen. watering|washing_machine|domestic_water_supply|off</li>
<li><a id="GardenaSmartDevice-set-turn_on_pressure">turn_on_pressure</a> - 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</li>
<li><a id="GardenaSmartDevice-set-operating_mode">operating_mode</a> - Managing operation mode. Timed operation is used in combination with schedules or "manualOverride". Automatic operation leaves pump active and activates irrigation depending on start-up pressure. automatic|scheduled </li>
<li><a id="GardenaSmartDevice-set-leakage_detection">leakage_detection</a> - Manages leakage detection.</br> Pump will be deactivated if it detects irregular loss of water. watering|washing_machine|domestic_water_supply|off</li>
<li><a id="GardenaSmartDevice-set-turn_on_pressure">turn_on_pressure</a> - Start-up pressure 2.0 - 3.0 Manages start-up pressure in scheduled and automatic mode. If pressure falls below this setting, pump will start. If pressure stays above this setting and there isn't any water flow, pump will activate standby.</li>
<li><a id="GardenaSmartDevice-set-cancelOverrideValve1">cancelOverrideValve1</a> - stop (manual) watering for valve 1</li>
<li><a id="GardenaSmartDevice-set-cancelOverrideValve2">cancelOverrideValve2</a> - stop (manual) watering for valve 2</li>
@ -1502,7 +1725,7 @@ sub SetPredefinedStartPoints {
<li><a id="GardenaSmartDevice-set-stopScheduleValve">stopScheduleValve</a> n m - stop irrigation schedule for valve n (Default: 2038-01-18T00:00:00.000Z, Gardena
App reads it as "permanently")</li>
<!-- ALL -->
<li><a id="GardenaSmartDevice-set-winter_mode">winter_mode</a> awake|hibernate - disable or enable winter mode</li>
<li><a id="GardenaSmartDevice-set-winter_mode">winter_mode</a> awake|hibernate - enable or disable winter mode</li>
<!-- SENSOR -->
<li><a id="GardenaSmartDevice-set-refresh">refresh</a> temperature|humidity|light*
<br>
@ -1642,7 +1865,7 @@ sub SetPredefinedStartPoints {
<li>ok_cutting_timer_overridden</li>
<li>parked_autotimer</li>
<li>parked_daily_limit_reached</li>
<li>hibernate - winter mode)</li>
<li>hibernate - winter mode</li>
</ul>
</li>
<li>winter_mode - status of winter mode (awake/hibernate)</li>
@ -1846,7 +2069,7 @@ sub SetPredefinedStartPoints {
<li>set NAME startpoint enable 1</li>
<li>set NAME startpoint disable 3 enable 1</li>
</ul>
<li>winter_mode awake|hibernate - Disable or enable winter mode</li>
<li>winter_mode hibernate|awake - enable or disable winter mode</li>
</ul>
<br><br>
<b>set (model = watering_computer)</b>
@ -1858,7 +2081,7 @@ sub SetPredefinedStartPoints {
<li>resumeSchedule - enable schedule</li>
<li>stopSchedule n - disable schedule for n hours (Default: 2038-01-18T00:00:00.000Z, Gardena App reads it as
"permanently")</li>
<li>winter_mode awake|hibernate - disable or enable winter mode</li>
<li>winter_mode hibernate|awake - enable or disable winter mode</li>
</ul>
<br><br>
<b>set (model = ic24)</b>
@ -1880,19 +2103,19 @@ sub SetPredefinedStartPoints {
<li>resumeScheduleValve n - (re)start irrigation schedule for valve n</li>
<li>stopScheduleValve n m - stop irrigation schedule for valve n (Default: 2038-01-18T00:00:00.000Z, Gardena
App reads it as "permanently")</li>
<li>winter_mode awake|hibernate - Disable or enable winter mode</li>
<li>winter_mode hibernate|awake - enable or disable winter mode</li>
</ul>
<br><br>
<b>set (model = sensor)</b>
<ul>
<li>refresh temperature|humidity|light - refresh sensor reading for temperature, humidity or daylight</li>
<li>winter_mode awake|hibernate - Disable or enable winter mode</li>
<li>winter_mode hibernate|awake - enable or disable winter mode</li>
</ul>
<br><br>
<b>set (model = sensor2)</b>
<ul>
<li>refresh temperature|humidity - refresh sensor reading for temperature or humidity</li>
<li>winter_mode awake|hibernate - Disable or enable winter mode</li>
<li>winter_mode hibernate|awake - enable or disable winter mode</li>
</ul>
<br><br>
<b>set (model = power)</b>
@ -2371,7 +2594,7 @@ sub SetPredefinedStartPoints {
<li>set NAME startpoint enable 1</li>
<li>set NAME startpoint disable 3 enable 1</li>
</ul>
<li>winter_mode awake|hibernate - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
<li>winter_mode hibernate|awake - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
</ul>
<br><br>
<b>set (model = watering_computer)</b>
@ -2382,7 +2605,7 @@ sub SetPredefinedStartPoints {
<li>resetValveErrors - Ventilfehler zur&uuml;cksetzen</li>
<li>resumeSchedule - Zeitplan wieder aktivieren</li>
<li>stopSchedule n - Zeitplan anhalten f&uuml;r n Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als "dauerhaft" interpretiert)</li>
<li>winter_mode awake|hibernate - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
<li>winter_mode hibernate|awake - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
</ul>
<br><br>
<b>set (model = ic24)</b>
@ -2403,19 +2626,19 @@ sub SetPredefinedStartPoints {
<li>resetValveErrors - Ventilfehler zur&uuml;cksetzen</li>
<li>resumeScheduleValve n - Zeitplan f&uuml;r Ventil n wieder aktivieren</li>
<li>stopScheduleValve n m - Zeitplan f&uuml;r Ventil n anhalten f&uuml;r m Stunden (Default: 2038-01-18T00:00:00.000Z durch Gardena-App als "dauerhaft" interpretiert)</li>
<li>winter_mode awake|hibernate - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
<li>winter_mode hibernate|awake - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
</ul>
<br><br>
<b>set (model = sensor)</b>
<ul>
<li>refresh temperature|humidity|light - Sensorwert f&uuml;r Temperatur, Feuchtigkeit oder Helligkeit aktualisieren</li>
<li>winter_mode awake|hibernate - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
<li>winter_mode hibernate|awake - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
</ul>
<br><br>
<b>set (model = sensor2)</b>
<ul>
<li>refresh temperature|humidity - Sensorwert f&uuml;r Temperatur oder Feuchtigkeit aktualisieren</li>
<li>winter_mode awake|hibernate - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
<li>winter_mode hibernate|awake - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
</ul>
<br><br>
<b>set (model = power)</b>
@ -2431,7 +2654,7 @@ sub SetPredefinedStartPoints {
<li>leakage_detection - Steuert die Lekage-Erkennung.</br> Hierdurch wird eine Pumpenabschaltung erreicht, sollte die Pumpe unkontrollierten Wasserverlust feststellen. watering|washing_machine|domestic_water_supply|off</li>
<li>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</li>
<li>resetValveErrors - Ventilfehler zur&uuml;cksetzen</li>
<li>winter_mode awake|hibernate - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
<li>winter_mode hibernate|awake - Winterschlaf aktivieren oder Ger&auml;t aufwecken</li>
</ul>
@ -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-06_12:31:38 123049 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