Added handling of groups of aliases.

Fixed internal bug when using multiple tellsticks.
This commit is contained in:
Rickard Andersson 2008-12-14 11:04:44 +00:00
parent 4971fb472f
commit ccdb488cfe
6 changed files with 261 additions and 82 deletions

View file

@ -1,3 +1,4 @@
NAME
tellstickController
@ -14,17 +15,18 @@
A small database is used for keeping track of device states
between every execution of tellstickController.
-a, --aliases List of aliases for devices.
-c, --check Check content of configuration file.
-h, --help Show this help text.
-v, --verbose Show extra information.
-d, --daemon Starts in daemon mode.
-f, --file F Set configfile to file F.
-g, --get D Get state for device D.
-h, --help Print this help text.
-l, --list List states for all devices.
-s, --set D S Set device D to state S.
-c, --check Check content of configuration file.
-t, --test Test mode, no real devices will used.
-v, --verbose Print extra information.
-x, --swap D Swap state for device D.
-a, --aliases List of aliases for devices/groups.
-l, --list List states for all devices/groups.
-s, --set D S Set device D to state S.
-g, --get D Get state for device/group D.
-w, --swapfirst G Swap states for group G based on first device state.
-x, --swap D Swap state for device/group D.
EXAMPLES
tellstickController -l
@ -52,6 +54,8 @@
The aliases configures device name, channel, code, etc.
The groups configures a list of devices and a delay time.
The rules can be written as a string containing two parts.
The first part is optional and ends with an '/'. It can contain
one or more of these keywords 'Weekend', 'Workweek', 'Monday',
@ -71,11 +75,10 @@
AUTHOR
Original version written by Rickard Andersson
Improvments added by ...
LICENSE
Copyright (C) 2008 Rickard Andersson
Version 1.4.2
Version 1.5.0
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; See license file for details.

View file

@ -7,7 +7,9 @@ tellstickController --set bedroom_mythtv_leds off
tellstickController --set bedroom_window off
tellstickController --set kitchen_cabinets off
tellstickController --set livingroom_cabinets off
tellstickController --set livingroom_uplight off
tellstickController --set livingroom_walls off
tellstickController --set livingroom_mythtv_leds off
tellstickController --set livingroom_uplight off
tellstickController --set livingroom_wall_north off
tellstickController --set livingroom_wall_east off
tellstickController --set livingroom_window off

View file

@ -1,13 +1,15 @@
#!/bin/sh
#
# Power off every device that control light sources.
# Power on every device that control light sources.
#
tellstickController --set bedroom_mythtv_leds on
tellstickController --set bedroom_window on
tellstickController --set kitchen_cabinets on
tellstickController --set livingroom_cabinets on
tellstickController --set livingroom_uplight on
tellstickController --set livingroom_walls on
tellstickController --set livingroom_mythtv_leds on
tellstickController --set livingroom_uplight on
tellstickController --set livingroom_wall_north on
tellstickController --set livingroom_wall_east on
tellstickController --set Livingroom_window on

View file

@ -3,7 +3,7 @@
# Configuration file for tellstickController
#
# Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com)
# Version: 1.4.0
# Version: 1.4
#
################################################################################
#
@ -49,14 +49,31 @@ Set logfile /var/log/tellstickController.log
# Alias MythTv_Backlight /dev/ttyUSB0 No Sartano 000000001
#
#
Alias kitchen_cabinets /dev/tellstick0 No Nexa G 2
Alias Bedroom_window /dev/tellstick0 No Nexa G 1
Alias Bedroom_window /dev/tellstick0 No Nexa G 10
Alias Bedroom_mythtv_power /dev/tellstick0 No Nexa G 6
Alias Bedroom_mythtv_leds /dev/tellstick0 No Nexa G 7
Alias Kitchen_cabinets /dev/tellstick0 No Nexa G 2
Alias Kitchen_window /dev/tellstick0 No Nexa G 11
Alias Livingroom_cabinets /dev/tellstick0 No Nexa G 3
Alias Livingroom_walls /dev/tellstick0 No Nexa G 4
Alias Livingroom_wall_north /dev/tellstick0 No Nexa G 4
Alias Livingroom_wall_east /dev/tellstick0 No Nexa G 9
Alias Livingroom_uplight /dev/tellstick0 Yes Nexa G 5
Alias Livingroom_mythtv_leds /dev/tellstick0 No Nexa G 8
Alias Livingroom_window /dev/tellstick0 No Nexa G 1
Alias Study_window /dev/tellstick0 No Nexa G 12
# Group aliases uses for handling a group of aliases
#
# Usage examples:
# Group Name Delay List of Aliases
# Group Livingroom_walls 60 Livingroom_wall_north Livingroom_wall_east
# Group Kitchen 5 Kitchen_cabinets Kitchen_window
#
#
Group Christmas_lights 20 Bedroom_window Kitchen_window Study_window
Group Background_lights 60 Kitchen_cabinets Livingroom_window Livingroom_wall_east Livingroom_wall_north
Group All_lights 10 Bedroom_mythtv_leds Bedroom_window Kitchen_cabinets Kitchen_window Livingroom_cabinets Livingroom_mythtv_leds Livingroom_uplight Livingroom_wall_north Livingroom_wall_east Livingroom_window Study_window
# Timer rules for reciever devices.
@ -68,18 +85,12 @@ Alias Livingroom_mythtv_leds /dev/tellstick0 No Nexa G 8
# Rule MythTv_Backlight Weekend/20:00 Weekend/Sunset
#
#
Rule Bedroom_window Workweek/sunrise+02:00 Workweek/Sunrise+03:00
Rule Bedroom_window Sunset-Random(00:30) 00:00+Random(00:30)
Rule Bedroom_window No 02:00
Rule Bedroom_mythtv_leds No 02:00
Rule Kitchen_cabinets Sunrise+01:00 Sunrise+03:00
Rule Kitchen_cabinets Workweek/Sunset-01:00 Workweek/00:00+Random(00:30)
Rule Kitchen_cabinets Weekend/Sunset-01:00 Weekend/00:30+Random(00:30)
Rule Kitchen_cabinets No 02:00
Rule Livingroom_cabinets Sunset-Random(00:30) 00:15+Random(00:30)
Rule Livingroom_cabinets No 02:00
Rule Livingroom_walls Sunset-Random(00:30) 00:15+Random(00:30)
Rule Livingroom_walls No 02:00
Rule Livingroom_uplight No 02:00
Rule Livingroom_mythtv_leds No 02:00
Rule Background_lights Workweek/Sunset+Random(01:00) Workweek/00:00+Random(00:30)
Rule Background_lights Weekend/Sunset-Random(00:30) Weekend/00:45+Random(00:30)
Rule Christmas_lights 07:00+Random(00:30) 09:00+Random(00:30)
Rule Christmas_lights 14:30+Random(00:30) 00:30+Random(00:30)
Rule Kitchen_cabinets Sunrise-01:30 Sunrise+01:00
Rule All_lights No 02:00

View file

@ -4,7 +4,7 @@
# tellstickController program
#
# Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com)
# Version 1.4.2
# Version 1.5.0
#
######################################################################
#
@ -52,6 +52,7 @@ my %cfg_set = (
"longitude" => "15.31",
"timezone" => "Europe/Stockholm",
);
my %cfg_group = ();
my %cfg_alias = ();
my %cfg_dimmer = ();
my @cfg_rule = ();
@ -64,6 +65,7 @@ my %option = (
"list" => 0,
"device" => "",
"state" => "",
"swapfirst" => 0,
"swap" => 0,
"test" => 0,
"verbose" => 0,
@ -121,6 +123,12 @@ sub check_args(@) {
$option{"state"} = lc($args[0]);
shift(@args);
next;
} elsif ($args[0] =~ /^-(w|-swapfirst)$/) {
shift(@args);
$option{"swapfirst"} = 1;
$option{"device"} = lc($args[0]);
shift(@args);
next;
} elsif ($args[0] =~ /^-(x|-swap)$/) {
shift(@args);
$option{"swap"} = 1;
@ -316,6 +324,7 @@ sub read_config($) {
= split(/\s+/, $line);
if (defined($suffix)) {
println "Wrong argument '$suffix' in line '$line'!";
println $addr;
} else {
$name = lc($name);
$sender = $sender;
@ -355,6 +364,30 @@ sub read_config($) {
next;
}
if ($line =~ /^Group\s+/i) {
println $line if ($option{"verbose"});
my (undef, $name, $delay, $aliases) = split(/\s+/, $line, 4);
$name = lc($name);
$delay = lc($delay);
if ($delay =~ /^\d+$/) {
my $error = 0;
$aliases = lc($aliases);
my @aliaslist = split(/\s+/, $aliases);
foreach my $alias (@aliaslist) {
if (! exists($cfg_alias{$alias})) {
println "Wrong alias '$alias' in line '$line'!";
$error += 1;
}
}
if ($error == 0) {
$cfg_group{$name} = "$delay $aliases";
}
} else {
println "Wrong delay time '$delay' in line '$line'!";
}
next;
}
if ($line =~ /^Rule\s+/i) {
#println $line if ($option{"verbose"});
my (undef, $alias, $on, $off, $suffix) = split(/\s+/, $line);
@ -364,7 +397,6 @@ sub read_config($) {
$alias = lc($alias);
$on = lc($on);
$off = lc($off);
if (exists($cfg_alias{$alias})) {
if ($on eq "") {
println "Wrong on time '$on' in line '$line'!";
} elsif ($off eq "") {
@ -374,10 +406,12 @@ sub read_config($) {
println "Wrong on time '$on' in line '$line'!";
} elsif ($off !~ /[\w\/\+\-\:\$\(\)]+/) {
println "Wrong off time '$off' in line '$line'!";
} else {
}
}
if (exists($cfg_alias{$alias})) {
push @cfg_rule, [$alias, $on, $off];
} elsif (exists($cfg_group{$alias})) {
push @cfg_rule, [$alias, $on, $off];
}
}
} else {
println "Wrong alias '$alias' in line '$line'!";
}
@ -414,6 +448,18 @@ sub read_config($) {
println $text if ($option{"check"});
printlogger $text;
}
$text = "=== Group ===";
println $text if ($option{"check"});
printlogger $text;
foreach my $key (sort keys %cfg_group) {
my $val = $cfg_group{$key};
my ($delay, $aliases) = split(/\s+/, $val, 2);
$text = "$key =";
$text .= " delay time $delay seconds";
$text .= " between aliases ($aliases)";
println $text if ($option{"check"});
printlogger $text;
}
$text = "=== Rule ===";
println $text if ($option{"check"});
printlogger $text;
@ -480,10 +526,31 @@ sub load_device_rules () {
foreach my $rule (@cfg_rule) {
my ($alias, $on, $off) = @$rule;
if (exists($cfg_alias{$alias})) {
my $time = get_rule_datetime($on, $today, $sunrise, $sunset);
push @device_on, [$time, $alias] if (defined($time) && ($now <= $time));
$time = get_rule_datetime($off, $today, $sunrise, $sunset);
push @device_off, [$time, $alias] if (defined($time) && ($now <= $time));
} else {
foreach my $val ($cfg_group{$alias}) {
my ($delay, $aliases) = split(/\s+/, $val, 2);
my $timedelay = 0;
my $ontime = get_rule_datetime($on, $today, $sunrise, $sunset);
my $offtime = get_rule_datetime($off, $today, $sunrise, $sunset);
my (@aliaslist) = split(/\s+/, $aliases);
foreach my $device (@aliaslist) {
if (defined($ontime)) {
my $time = $ontime->clone->add(seconds => $timedelay);
push @device_on, [$time, $device] if (defined($time) && ($now <= $time));
}
if (defined($offtime)) {
my $time = $offtime->clone->add(seconds => $timedelay);
push @device_off, [$time, $device] if (defined($time) && ($now <= $time));
}
$timedelay += $delay;
}
}
}
}
@device_on = sort { $a->[0] cmp $b->[0] } @device_on;
@ -646,7 +713,7 @@ sub get_rule_datetime($$$$) {
# UTC ?
$time = get_datetime_now();
$time->set(hour => 0, minute => 0, second => 0);
$time->add(hours => $hours+24*$days, minutes => $minutes);
$time->add(hours => $hours+24*$days, minutes => $minutes, seconds => 0);
#println "days='$days', hours='$hours', minutes='$minutes'";
#println "time='$time'";
} else {
@ -713,8 +780,17 @@ sub get_device_state() {
my $state = $device_state{$device};
println "$state" if (not $option{"verbose"});
println "Device $device = $state" if ($option{"verbose"});
} elsif (exists($cfg_group{$device})) {
my $val = $cfg_group{$device};
my ($delay, $aliases) = split(/\s+/, $val, 2);
my $states = "";
my (@aliaslist) = split(/\s+/, $aliases);
foreach my $alias (@aliaslist) {
$states .= " $device_state{$alias}";
}
println "Group $device =$states";
} else {
println "No device found with alias '$device'!";
println "No alias or group found with name '$device'!";
}
}
}
@ -723,16 +799,58 @@ sub get_device_state() {
sub set_device_state() {
if ($option{"device"}) {
if ($option{"state"}) {
my $device = $option{"device"};
if ($device_state{$device}) {
my $state = $option{"state"};
if ($state =~ /^(on|off)$/i) {
change_device_state($device, $state);
} else {
if ($state !~ /^(on|off)$/i) {
println "No state found with name '$state'!";
}
my $device = $option{"device"};
if ($device_state{$device}) {
change_device_state($device, $state);
} elsif (exists($cfg_group{$device})) {
my $val = $cfg_group{$device};
my ($delay, $aliases) = split(/\s+/, $val, 2);
my (@aliaslist) = split(/\s+/, $aliases);
foreach my $alias (@aliaslist) {
change_device_state($alias, $state);
sleep(1);
}
} else {
println "No device found with alias '$device'!";
println "No alias or group found with name '$device'!";
}
}
}
}
sub swap_first_device_state() {
if ($option{"device"}) {
if ($option{"swapfirst"}) {
my $device = $option{"device"};
if ($device_state{$device}) {
my $state = $device_state{$device};
if ($state =~ /^off$/i) {
$state = 'on';
} else {
$state = 'off';
}
change_device_state($device, $state);
} elsif (exists($cfg_group{$device})) {
my $val = $cfg_group{$device};
my ($delay, $aliases) = split(/\s+/, $val, 2);
my ($alias) = split(/\s+/, $aliases);
my $state = $device_state{$alias};
if ($state =~ /^off$/i) {
$state = 'on';
} else {
$state = 'off';
}
my (@aliaslist) = split(/\s+/, $aliases);
foreach my $alias (@aliaslist) {
change_device_state($alias, $state);
sleep(1);
}
} else {
println "No alias or group found with name '$device'!";
}
}
}
@ -746,12 +864,27 @@ sub swap_device_state() {
if ($device_state{$device}) {
my $state = $device_state{$device};
if ($state =~ /^off$/i) {
change_device_state($device, 'on');
$state = 'on';
} else {
change_device_state($device, 'off');
$state = 'off';
}
change_device_state($device, $state);
} elsif (exists($cfg_group{$device})) {
my $val = $cfg_group{$device};
my ($delay, $aliases) = split(/\s+/, $val, 2);
my (@aliaslist) = split(/\s+/, $aliases);
foreach my $alias (@aliaslist) {
my $state = $device_state{$alias};
if ($state =~ /^off$/i) {
$state = 'on';
} else {
$state = 'off';
}
change_device_state($alias, $state);
sleep(1);
}
} else {
println "No device found with alias '$device'!";
println "No alias or group found with name '$device'!";
}
}
}
@ -762,6 +895,16 @@ sub list_all_devices() {
foreach my $key (sort keys %device_state) {
println "Device $key = $device_state{$key}";
}
foreach my $key (sort keys %cfg_group) {
my $val = $cfg_group{$key};
my ($delay, $aliases) = split(/\s+/, $val, 2);
my $states = "";
my (@aliaslist) = split(/\s+/, $aliases);
foreach my $device (@aliaslist) {
$states .= " $device_state{$device}";
}
println "Group $key =$states";
}
}
@ -769,7 +912,12 @@ sub list_all_aliases {
foreach my $key (sort keys %cfg_alias) {
my $dimmer = "";
$dimmer = " dimmer" if $cfg_dimmer{$key} eq "yes";
println "Device $key is an alias for$dimmer receiver $cfg_alias{$key}";
println "Alias $key = receiver ($cfg_alias{$key}$dimmer)";
}
foreach my $key (sort keys %cfg_group) {
my $val = $cfg_group{$key};
my ($delay, $aliases) = split(/\s+/, $val, 2);
println "Group $key = delay $delay seconds, aliases ($aliases)";
}
}
@ -784,7 +932,7 @@ sub daemon_loop() {
$next_day->set( hour => 0, minute => 0, second => 0 );
println "Next reload of device rules = $next_day" if ($option{"verbose"});
my $wait_time = 60;
my $wait_time = 5;
my $loop = 1;
check_device_rules($now);
@ -811,6 +959,8 @@ sub perform_action() {
get_device_state();
} elsif ($option{"set"}) {
set_device_state();
} elsif ($option{"swapfirst"}) {
swap_first_device_state();
} elsif ($option{"swap"}) {
swap_device_state();
} elsif ($option{"list"}) {
@ -869,17 +1019,18 @@ __DATA__
#- A small database is used for keeping track of device states
#- between every execution of tellstickController.
#-
#- -a, --aliases List of aliases for devices.
#- -c, --check Check content of configuration file.
#- -h, --help Show this help text.
#- -v, --verbose Show extra information.
#- -d, --daemon Starts in daemon mode.
#- -f, --file F Set configfile to file F.
#- -g, --get D Get state for device D.
#- -h, --help Print this help text.
#- -l, --list List states for all devices.
#- -s, --set D S Set device D to state S.
#- -c, --check Check content of configuration file.
#- -t, --test Test mode, no real devices will used.
#- -v, --verbose Print extra information.
#- -x, --swap D Swap state for device D.
#- -a, --aliases List of aliases for devices/groups.
#- -l, --list List states for all devices/groups.
#- -s, --set D S Set device D to state S.
#- -g, --get D Get state for device/group D.
#- -w, --swapfirst G Swap states for group G based on first device state.
#- -x, --swap D Swap state for device/group D.
#-
#- EXAMPLES
#- tellstickController -l
@ -907,6 +1058,8 @@ __DATA__
#-
#- The aliases configures device name, channel, code, etc.
#-
#- The groups configures a list of devices and a delay time.
#-
#- The rules can be written as a string containing two parts.
#- The first part is optional and ends with an '/'. It can contain
#- one or more of these keywords 'Weekend', 'Workweek', 'Monday',
@ -926,11 +1079,10 @@ __DATA__
#-
#- AUTHOR
#- Original version written by Rickard Andersson
#- Improvments added by ...
#-
#- LICENSE
#- Copyright (C) 2008 Rickard Andersson
#- Version 1.4.2
#- Version 1.5.0
#- This program comes with ABSOLUTELY NO WARRANTY.
#- This is free software, and you are welcome to redistribute it
#- under certain conditions; See license file for details.

View file

@ -3,7 +3,7 @@
# Configuration file for tellstickController
#
# Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com)
# Version: 1.4.2
# Version: 1.5.0
#
################################################################################
#
@ -29,7 +29,6 @@
#
# Set Timezone Europe/Stockholm
#
#
Set Timezone Europe/Stockholm
Set Latitude 58.24
Set Longitude 15.31
@ -53,8 +52,18 @@ Set logfile /var/log/tellstickController.log
#
# Alias MythTv_Backlight /dev/ttyUSB0 No Sartano 000000001
#
#
Alias device1 /dev/tellstick No Nexa A 1
Alias device2 /dev/tellstick No Nexa A 2
# Groups used for handling a list of aliases.
#
# Usage examples:
# Group Name Delay Aliases
# Group Livingroom_walls 60 Livingroom_wall_north Livingroom_wall_east
# Group Kitchen 5 Kitchen_cabinets Kitchen_window
#
Group allDevices 10 Device1 Device2
# Timer rules for reciever devices.
@ -68,7 +77,7 @@ Alias device1 /dev/tellstick No Nexa A 1
# Rule device42 2008-03-##/18:45 2008-03-##/22:11
# Rule device42 No 02:00
#
#
Rule device1 weekend/sunrise weekend/08:45
Rule device1 sunset+00:15 23:30+Random(00:20)
Rule allDevices 16:45 23:45