Version 0.3.0. New feature: possibility to randomize switch on and switch off time.
This commit is contained in:
parent
809659ea17
commit
80ce55dc8c
3 changed files with 108 additions and 35 deletions
|
@ -31,10 +31,11 @@ Licensing
|
||||||
=================
|
=================
|
||||||
This software is freely distributable under the GNU General Public License,
|
This software is freely distributable under the GNU General Public License,
|
||||||
the full content of the license is included in the file LICENSE.
|
the full content of the license is included in the file LICENSE.
|
||||||
Feel free to improve the program.
|
Bug reports are welcome, but even more appreciated are patches with the solution to the problem.
|
||||||
|
|
||||||
Revision history
|
Revision history
|
||||||
=================
|
=================
|
||||||
|
2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval.
|
||||||
2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information.
|
2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information.
|
||||||
2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups.
|
2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups.
|
||||||
2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs.
|
2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTime::Event::Sunrise;
|
use DateTime::Event::Sunrise;
|
||||||
use Time::Local;
|
use Time::Local;
|
||||||
|
@ -16,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd";
|
||||||
# You should not need to go beyond this point (unless you have found a bug or need to improve the functionality).
|
# You should not need to go beyond this point (unless you have found a bug or need to improve the functionality).
|
||||||
$AUTHOR = "Magnus Juntti, mjuntti\@gmail.com";
|
$AUTHOR = "Magnus Juntti, mjuntti\@gmail.com";
|
||||||
$PROGRAM_NAME = "tellstickd";
|
$PROGRAM_NAME = "tellstickd";
|
||||||
$VERSION = "0.2.1";
|
$VERSION = "0.3.0";
|
||||||
|
|
||||||
|
|
||||||
# Structure of the configurations to be read;
|
# Structure of the configurations to be read;
|
||||||
|
@ -28,9 +29,13 @@ $VERSION = "0.2.1";
|
||||||
# $device_cfg[$i][5]; # Off when bright, 0 = no, 1 = yes
|
# $device_cfg[$i][5]; # Off when bright, 0 = no, 1 = yes
|
||||||
# $device_cfg[$i][6]; # Off when bright delay
|
# $device_cfg[$i][6]; # Off when bright delay
|
||||||
# $device_cfg[$i][7]; # Time in advance when getting dark
|
# $device_cfg[$i][7]; # Time in advance when getting dark
|
||||||
|
# $device_cfg[$i][8]; # On time random interval
|
||||||
|
# $device_cfg[$i][9]; # Off time random interval
|
||||||
# $device_cfg[$i][20]; # Sunrise off time, calculated in this program and stored here
|
# $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][21]; # Sunset on time, calculated in this program and stored here
|
||||||
# $device_cfg[$i][22]; # Switch state, 0 = off, 1 = on
|
# $device_cfg[$i][22]; # Switch state, 0 = off, 1 = on
|
||||||
|
# $device_cfg[$i][23]; # Original on time
|
||||||
|
# $device_cfg[$i][24]; # Original off time
|
||||||
|
|
||||||
sub daemonize {
|
sub daemonize {
|
||||||
chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!";
|
chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!";
|
||||||
|
@ -82,8 +87,8 @@ sub is_inbetween_times
|
||||||
{
|
{
|
||||||
my $time1 = $_[0];
|
my $time1 = $_[0];
|
||||||
my $time2 = $_[1];
|
my $time2 = $_[1];
|
||||||
|
my $curr_time = $_[2];
|
||||||
|
|
||||||
my $curr_time = $current_time;
|
|
||||||
$curr_time =~ s/://g;
|
$curr_time =~ s/://g;
|
||||||
$time1 =~ s/://g;
|
$time1 =~ s/://g;
|
||||||
$time2 =~ s/://g;
|
$time2 =~ s/://g;
|
||||||
|
@ -150,6 +155,8 @@ sub rfcmd_exec {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Time format xx:yy for input parameters
|
||||||
sub add_time
|
sub add_time
|
||||||
{
|
{
|
||||||
my $time1 = $_[0];
|
my $time1 = $_[0];
|
||||||
|
@ -159,7 +166,8 @@ sub add_time
|
||||||
$Year += 1900;
|
$Year += 1900;
|
||||||
|
|
||||||
($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/;
|
($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/;
|
||||||
($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/;
|
($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/;$device_cfg[$i][8] = $inrad[8]; # On time random interval
|
||||||
|
$device_cfg[$i][9] = $inrad[9]; # Off time random interval
|
||||||
|
|
||||||
$time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year);
|
$time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year);
|
||||||
$time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute;
|
$time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute;
|
||||||
|
@ -172,6 +180,7 @@ sub add_time
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Time format xx:yy for input parameters
|
||||||
sub subtract_time
|
sub subtract_time
|
||||||
{
|
{
|
||||||
my $time1 = $_[0];
|
my $time1 = $_[0];
|
||||||
|
@ -194,6 +203,53 @@ sub subtract_time
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub randomize_on
|
||||||
|
{
|
||||||
|
my $device_id = $_[0];
|
||||||
|
|
||||||
|
(my $random_hour, my $random_minute) = $device_cfg[$device_id][8] =~ /(.*)\:(.*)/;
|
||||||
|
|
||||||
|
my $rand_res = int(rand(60 * $random_hour + $random_minute));
|
||||||
|
|
||||||
|
my $rand_res_hour = floor($rand_res / 60);
|
||||||
|
my $rand_res_minute = $rand_res - 60*$rand_res_hour;
|
||||||
|
|
||||||
|
# Here we have the random offset in format xx:yy
|
||||||
|
my $random_time = sprintf("%02d:%02d", $rand_res_hour, $rand_res_minute);
|
||||||
|
|
||||||
|
$device_cfg[$device_id][3] = add_time($device_cfg[$device_id][23], $random_time);
|
||||||
|
|
||||||
|
if (is_inbetween_times($device_cfg[$device_id][23], $device_cfg[$device_id][24], $device_cfg[$device_id][3]) == $NO) {
|
||||||
|
randomize_on($device_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub randomize_off
|
||||||
|
{
|
||||||
|
my $device_id = $_[0];
|
||||||
|
|
||||||
|
(my $random_hour, my $random_minute) = $device_cfg[$device_id][9] =~ /(.*)\:(.*)/;
|
||||||
|
|
||||||
|
my $rand_res = int(rand(60 * $random_hour + $random_minute));
|
||||||
|
|
||||||
|
my $rand_res_hour = floor($rand_res / 60);
|
||||||
|
my $rand_res_minute = $rand_res - 60*$rand_res_hour;
|
||||||
|
|
||||||
|
# Here we have the random offset in format xx:yy
|
||||||
|
my $random_time = sprintf("%02d:%02d", $rand_res_hour, $rand_res_minute);
|
||||||
|
|
||||||
|
$device_cfg[$device_id][4] = add_time($device_cfg[$device_id][24], $random_time);
|
||||||
|
|
||||||
|
if (is_inbetween_times($device_cfg[$device_id][23], $device_cfg[$device_id][24], $device_cfg[$device_id][4]) == $YES) {
|
||||||
|
randomize_off($device_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Time format sanity check routine
|
# Time format sanity check routine
|
||||||
sub is_time_format_correct
|
sub is_time_format_correct
|
||||||
{
|
{
|
||||||
|
@ -250,10 +306,14 @@ sub read_config
|
||||||
$device_cfg[$i][5] = $inrad[5]; # Off when bright
|
$device_cfg[$i][5] = $inrad[5]; # Off when bright
|
||||||
$device_cfg[$i][6] = $inrad[6]; # Off when bright delay
|
$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][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
|
$device_cfg[$i][8] = $inrad[8]; # On time random interval
|
||||||
|
$device_cfg[$i][9] = $inrad[9]; # Off time random interval
|
||||||
|
$device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched of at startup
|
||||||
|
$device_cfg[$i][23] = $device_cfg[$i][3]; # Original on time is stored here pos 3 will be used for random on times
|
||||||
|
$device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random on times
|
||||||
|
|
||||||
|
|
||||||
if ($device_cfg[$device_id][0] eq "SARTANO") {
|
if ($device_cfg[$i][0] eq "SARTANO") {
|
||||||
$device_cfg[$i][2] = "";
|
$device_cfg[$i][2] = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +363,9 @@ sub read_config
|
||||||
printf(" Off time: $device_cfg[$i][4]\n");
|
printf(" Off time: $device_cfg[$i][4]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf(" On time random interval: $device_cfg[$i][8]\n");
|
||||||
|
printf(" Off time random interval: $device_cfg[$i][9]\n");
|
||||||
|
|
||||||
if ($device_cfg[$i][5] == $YES) {
|
if ($device_cfg[$i][5] == $YES) {
|
||||||
printf(" Turned off daytime: yes\n");
|
printf(" Turned off daytime: yes\n");
|
||||||
printf(" Off post sunrise: $device_cfg[$i][6]\n");
|
printf(" Off post sunrise: $device_cfg[$i][6]\n");
|
||||||
|
@ -419,10 +482,10 @@ while (1) {
|
||||||
# First, lets set the sunrise and sunset times for the devices that it 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") {
|
if ($first_loop == $YES || $current_time eq "00:00") {
|
||||||
my $sunrise_time = get_sunrise_time();
|
my $sunrise_time = get_sunrise_time();
|
||||||
printf("$PROGRAM_NAME: Sunrise today is expected at $sunrise_time\n");
|
printf("$PROGRAM_NAME: Time is $current_time. Sunrise today is expected at $sunrise_time\n");
|
||||||
|
|
||||||
my $sunset_time = get_sunset_time();
|
my $sunset_time = get_sunset_time();
|
||||||
printf("$PROGRAM_NAME: Sunset today is expected at $sunset_time\n");
|
printf("$PROGRAM_NAME: Time is $current_time. Sunset today is expected at $sunset_time\n");
|
||||||
|
|
||||||
for (my $i = 0; $i < $number_of_devices; $i++) {
|
for (my $i = 0; $i < $number_of_devices; $i++) {
|
||||||
# Initially all devices are switched off to get a known state
|
# Initially all devices are switched off to get a known state
|
||||||
|
@ -430,9 +493,15 @@ while (1) {
|
||||||
rfcmd_exec($i, 0);
|
rfcmd_exec($i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Lets set the actual on- and offtimes depending on random interval settings.
|
||||||
|
randomize_on($i);
|
||||||
|
printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned on $device_cfg[$i][3]\n");
|
||||||
|
|
||||||
|
randomize_off($i);
|
||||||
|
printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned off $device_cfg[$i][4]\n");
|
||||||
|
|
||||||
|
|
||||||
# If the device is supposed to be off daytime, the following applies
|
# If the device is supposed to be off daytime, the following applies
|
||||||
|
|
||||||
# Sunrise time + requested offset
|
# Sunrise time + requested offset
|
||||||
if ($device_cfg[$i][5] == $YES) {
|
if ($device_cfg[$i][5] == $YES) {
|
||||||
$device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]);
|
$device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]);
|
||||||
|
@ -453,7 +522,7 @@ while (1) {
|
||||||
|
|
||||||
# First if we consider daytime off
|
# First if we consider daytime off
|
||||||
if ($device_cfg[$i][5] == $YES) {
|
if ($device_cfg[$i][5] == $YES) {
|
||||||
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) {
|
if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21]) == $NO) {
|
||||||
rfcmd_exec($i, 1);
|
rfcmd_exec($i, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -464,7 +533,7 @@ while (1) {
|
||||||
|
|
||||||
# Then if daytime off is not considered
|
# Then if daytime off is not considered
|
||||||
else {
|
else {
|
||||||
if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES) {
|
if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES) {
|
||||||
rfcmd_exec($i, 1);
|
rfcmd_exec($i, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -476,5 +545,5 @@ while (1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$first_loop = $NO;
|
$first_loop = $NO;
|
||||||
sleep(60); # Wait a while until next round should be less than or equal to a minute [seconds].
|
sleep(50); # Wait a while until next round [seconds].
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
# Configuration file for control of remote switches
|
# Tellstickd file for control of remote switches with rfcmd.
|
||||||
#
|
#
|
||||||
#<protocol> <housecode> <channel> <on time> <off time> <daytime off yes/no> <off when bright delay in morning> <prelight in afternoon>
|
#<protocol> <housecode> <channel> <on time> <off time> <daytime off yes/no> <off when bright delay in morning> <prelight in afternoon> <on time random interval> <off time random interval>
|
||||||
# (no = 0, yes = 1)
|
# (no = 0, yes = 1)
|
||||||
# Multiple definitions are possible for each device
|
# Multiple definitions are possible for each device
|
||||||
#
|
#
|
||||||
# Setting <on time> and <off time> to the same means that the device will always be switched on
|
# Setting <on time> and <off time> to the same means that the device will always be switched on.
|
||||||
|
# The random interval times defines the allowed interval within the switch may take place
|
||||||
|
# <off time>=22:15 and <on time random interval>=00:30 means that the actual switch will take
|
||||||
|
# place sometime between 22:15 and 22:44, with new randomized times set every night at 00:00.
|
||||||
#
|
#
|
||||||
# Time format xx:yy where xx is hour and yy is minute
|
# 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.
|
# 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
|
# NEXA A 1 -1 22:45 1 00:30 00:30
|
||||||
#
|
#
|
||||||
# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning.
|
# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. On time will always be 05:30, off time will always be 22:45.
|
||||||
SARTANO 0000000000 0 05:30 22:45 1 00:30 00:15
|
SARTANO 0000000000 0 05:30 22:45 1 00:30 00:15 00:00 00:00
|
||||||
|
|
||||||
# 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.
|
# 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. On time will be between 06:30 and 06:39, off time will be between 22:05 and 22:24.
|
||||||
NEXA A 1 05:30 22:45 1 00:30 00:15
|
NEXA A 1 06:30 22:05 1 00:30 00:15 00:10 00:20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue