diff --git a/tellstickd/README b/tellstickd/README index 446a9753..b1e3aa26 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Feel free to improve the program. Revision history ================= +2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. 2008-02-10 0.1.3 Modified switch logic. When dawn is before on-time, lights are not switched on. If dusk time is after off time, lights are not switched on. 2008-01-30 0.1.2 Corrected a bug regarding datetimelocal. 2008-01-15 0.1.1 Fixed some bugs. Added logfile capability. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 69285bb7..aa0d3c71 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -16,7 +16,7 @@ $LOG_FILE = "/var/log/tellstickd"; # After this point you really shouldn't need to go $AUTHOR = "Magnus Juntti, juntti\@mail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.1.3"; +$VERSION = "0.1.4"; # Structure of the configurations to be read; @@ -25,11 +25,12 @@ $VERSION = "0.1.3"; # $device_cfg[$i][2]; # Channel 1-3 # $device_cfg[$i][3]; # On time # $device_cfg[$i][4]; # Off time -# $device_cfg[$i][5]; # Off when bright +# $device_cfg[$i][5]; # Off when bright, 0 = no, 1 = yes # $device_cfg[$i][6]; # Off when bright delay # $device_cfg[$i][7]; # Time in advance when getting dark # $device_cfg[$i][20]; # Sunrise off time, calculated in this program and stored here # $device_cfg[$i][21]; # Sunset on time, calculated in this program and stored here +# $device_cfg[$i][22]; # Switch state, 0 = off, 1 = on sub daemonize { chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!"; @@ -76,30 +77,67 @@ sub get_sunset_time return $sunset_time; } -sub is_sun_up +# Checks if $current_time is inbetween argument 1 ($time1) and argument 2 ($time2) +sub is_inbetween_times { - $sunrise_time = get_sunrise_time(); - $sunset_time = get_sunset_time(); + my $time1 = $_[0]; + my $time2 = $_[1]; -# printf("sunrise: $sunrise_time\nsunset: $sunset_time\n"); - - my $curr_time = sprintf("%0d%02d", $Hour, $Minute); - $sunrise_time =~ s/://g; - $sunset_time =~ s/://g; - - #Remove leading zeroes. + my $curr_time = $current_time; + $curr_time =~ s/://g; + $time1 =~ s/://g; + $time2 =~ s/://g; $curr_time =~ s/^0*//; $sunrise_time =~ s/^0*//; $sunset_time =~ s/^0*//; -# printf("curr_time = $curr_time, sunrise_time = $sunrise_time, sunset_time = $sunset_time\n"); + # If we pass midnight, the following has to be checked + if ($time2 <= $time1) { + $time2 += 2400; + } - if ($curr_time > $sunrise_time && $curr_time < $sunset_time) { + if ($curr_time >= $time1 && $curr_time <= $time2) { return $YES; } - else { - return $NO; + + return $NO; +} + + + +sub rfcmd_exec { + my $device_id = $_[0]; + my $action = $_[1]; + + + # Action = 1 means turn lamp on + if ($action == 1) { + # Only turn the device on if it is not already turned on to avoid flashing dimmers. + if ($device_cfg[$device_id][22] == 0) { + printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2] 1`; + $device_cfg[$device_id][22] = 1; + + return; + } + else { + return; + } } + elsif ($action == 0) { + if ($device_cfg[$device_id][22] == 1) { + printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2] 0`; + $device_cfg[$device_id][22] = 0; + + return; + } + else { + return; + } + } + + return; } sub add_time @@ -185,7 +223,7 @@ sub read_config { my $input_file = $_[0]; - printf("$PROGRAM_NAME: Reading configuration file $conf_file...\n"); + printf("$PROGRAM_NAME: Reading configuration file $conf_file\n"); open(CFG_FILE, "<$input_file") or die "$PROGRAM_NAME: Could not access config file: $conf_file\n"; @@ -202,6 +240,7 @@ sub read_config $device_cfg[$i][5] = $inrad[5]; # Off when bright $device_cfg[$i][6] = $inrad[6]; # Off when bright delay $device_cfg[$i][7] = $inrad[7]; # Time in advance when getting dark + $device_cfg[$i][22] = 1; # Initial state set to so that they will be switched of at startup # Some sanity checks @@ -335,7 +374,7 @@ if (length($conf_file) < 1) { $conf_file = $CONFIG_FILE; } -printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION...\n"); +printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); # Read the configuration file $number_of_devices = read_config($conf_file); @@ -360,7 +399,7 @@ while (1) { ################################################################################################### - # First, lets set the sunrise and sunset times for the devices that applies to, once a day, at 00:00. + # First, lets set the sunrise and sunset times for the devices that it applies to, once a day, at 00:00. if ($first_loop == $YES || $current_time eq "00:00") { my $sunrise_time = get_sunrise_time(); printf("$PROGRAM_NAME: Sunrise today is expected at $sunrise_time\n"); @@ -368,111 +407,57 @@ while (1) { my $sunset_time = get_sunset_time(); printf("$PROGRAM_NAME: Sunset today is expected at $sunset_time\n"); - my $i = 0; - while($i < $number_of_devices) { + for (my $i = 0; $i < $number_of_devices; $i++) { + # Initially all devices are switched off to get a known state + if ($first_loop == $YES) { + rfcmd_exec($i, 0); + } + + # If the device is supposed to be off daytime, the following applies # Sunrise time + requested offset if ($device_cfg[$i][5] == $YES) { $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); - } - # Sunset time - requested offset - if ($device_cfg[$i][5] == $YES) { + # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); } - - $i++; } } ################################################################################################### # Below the required actions are performed for each device - my $i = 0; - while($i < $number_of_devices) { + for ($i = 0; $i < $number_of_devices; $i++) { - - # ON - # This is where we turn devices on depending on the state of the sun and the settings in daytime savings field $device_cfg[$i][5] - if ($device_cfg[$i][3] eq $current_time) { - # In case daytime turn off is activated, check if sun is up before turning on lamp - if ($device_cfg[$i][5] == $YES) { - if (is_sun_up() == $NO) { - printf("$PROGRAM_NAME: Time is $current_time and the sun is not yet up. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; - } - # This is where we end up when daytime saving is on and the sun is already up - else { - printf("$PROGRAM_NAME: Time is $current_time and the sun is up. $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] not turned on.\n"); - } - } - # If daytime turn off is not activated, always turn on the lamps on. - else { - printf("$PROGRAM_NAME: Time is $current_time. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; - } - } - - - - - - - - # DAWN / DUSK ACTIONS - # If on when bright feature is 1 (yes) then do the following (i.e. if lights are supposed to be turned off daytime) + # First if we consider daytime off if ($device_cfg[$i][5] == $YES) { - # Sunrise turn off - if ($device_cfg[$i][20] eq $current_time) { - printf("$PROGRAM_NAME: Time is $current_time. Turning off $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 0`; + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21]) == $NO) { + rfcmd_exec($i, 1); } - - # Sunset turn on if the sunset turn on time is before the desired turn off time - if ($device_cfg[$i][21] eq $current_time) { - my $t_off = $device_cfg[$i][4]; - my $ss_on = $device_cfg[$i][21]; - $t_off =~ s/://g; - $ss_on =~ s/://g; - $t_off =~ s/^0*//; - $ss_on =~ s/^0*//; - - # If sunset on time is before the desired off time then turn the device on. - if ($ss_on < $t_off) { - printf("$PROGRAM_NAME: Time is $current_time. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; - } - # If the sunset on time is after the desired off time then do nothing - else { - printf("$PROGRAM_NAME: Time is $current_time. Not turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] since the desired turn off time is already passed.\n"); - } + else { + rfcmd_exec($i, 0); } } - - - - - # OFF - # This is where we turn devices off, we do this regardless of any other settings. - if ($device_cfg[$i][4] eq $current_time) { - printf("$PROGRAM_NAME: Time is $current_time. Turning off $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 0`; + # Then if daytime off is not considered + else { + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES) { + rfcmd_exec($i, 1); + } + else { + rfcmd_exec($i, 0); + } } - - - - # Move on to next device - $i++; } $first_loop = $NO; - sleep(60); # Wait a while until next round should be less than or equal to a minute, [seconds] + sleep(60); # Wait a while until next round should be less than or equal to a minute [seconds]. } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 33736948..4bc079fa 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -1,16 +1,17 @@ # Configuration file for control of remote switches # -# +# # (no = 0, yes = 1) # Multiple definitions are possible for each device -# +# +# Setting and to the same means that the device will always be switched on +# # Time format xx:yy where xx is hour and yy is minute # If no turn on time or turn off time should be used. Note this with -1. See the example line below. Only to be used on turn on or turn off times. # NEXA A 1 -1 22:45 1 00:30 00:30 - -# Sample to control NEXA device A 1 -NEXA A 1 05:30 22:45 1 00:30 00:30 +# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. +NEXA A 1 05:30 22:45 1 00:30 00:15