trigger_switch_d 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING.txt +674 -0
- data/LICENSE.txt +54 -0
- data/README.rdoc +106 -0
- data/bin/teach +44 -0
- data/bin/tsd +68 -0
- data/bin/turn_off +42 -0
- data/bin/turn_on +39 -0
- data/doc/classes/Tellstick/Tellstick.html +117 -0
- data/doc/classes/Tellstick/TellstickIO.html +265 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000020.html +18 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000021.html +20 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000022.html +26 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000023.html +19 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000024.html +26 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000025.html +16 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000026.html +16 -0
- data/doc/classes/Tellstick/TellstickIO.src/M000027.html +24 -0
- data/doc/classes/Tellstick.html +204 -0
- data/doc/classes/Tellstick.src/M000019.html +25 -0
- data/doc/classes/TriggerSwitchD/Action.html +165 -0
- data/doc/classes/TriggerSwitchD/Action.src/M000015.html +28 -0
- data/doc/classes/TriggerSwitchD/Action.src/M000016.html +18 -0
- data/doc/classes/TriggerSwitchD/Application.html +203 -0
- data/doc/classes/TriggerSwitchD/Application.src/M000017.html +21 -0
- data/doc/classes/TriggerSwitchD/Application.src/M000018.html +40 -0
- data/doc/classes/TriggerSwitchD/ConfigFactory/Config.html +127 -0
- data/doc/classes/TriggerSwitchD/ConfigFactory/Config.src/M000014.html +23 -0
- data/doc/classes/TriggerSwitchD/ConfigFactory.html +141 -0
- data/doc/classes/TriggerSwitchD/ConfigFactory.src/M000013.html +24 -0
- data/doc/classes/TriggerSwitchD/IPC.html +134 -0
- data/doc/classes/TriggerSwitchD/IPC.src/M000012.html +32 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.html +242 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000005.html +19 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000006.html +18 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000007.html +23 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000008.html +19 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000009.html +19 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000010.html +18 -0
- data/doc/classes/TriggerSwitchD/Schedule/InstanceMethods.src/M000011.html +18 -0
- data/doc/classes/TriggerSwitchD/Schedule.html +147 -0
- data/doc/classes/TriggerSwitchD/Schedule.src/M000004.html +19 -0
- data/doc/classes/TriggerSwitchD/SwitchFactory.html +135 -0
- data/doc/classes/TriggerSwitchD/SwitchFactory.src/M000003.html +20 -0
- data/doc/classes/TriggerSwitchD.html +212 -0
- data/doc/classes/TriggerSwitchD.src/M000001.html +22 -0
- data/doc/classes/TriggerSwitchD.src/M000002.html +27 -0
- data/doc/created.rid +1 -0
- data/doc/files/lib/tellstick/protocol/nexa_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/not_connected_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/null_protocol_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/plain_text_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/proove_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/protocol_loader_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/rising_sun_rb.html +126 -0
- data/doc/files/lib/tellstick/protocol/waveman_rb.html +126 -0
- data/doc/files/lib/tellstick/tellstick_io_rb.html +135 -0
- data/doc/files/lib/tellstick/tellstick_rb.html +135 -0
- data/doc/files/lib/tellstick_rb.html +134 -0
- data/doc/files/lib/trigger_switch_d/action_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d/application_rb.html +136 -0
- data/doc/files/lib/trigger_switch_d/config_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d/daylight_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d/ipc_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d/schedule_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d/switch_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d/trigger_switch_d_helper_rb.html +126 -0
- data/doc/files/lib/trigger_switch_d_rb.html +140 -0
- data/doc/fr_class_index.html +38 -0
- data/doc/fr_file_index.html +46 -0
- data/doc/fr_method_index.html +53 -0
- data/doc/index.html +24 -0
- data/features/execute_schedule.feature +20 -0
- data/features/group_aliases.feature +31 -0
- data/features/handle_switches.feature +36 -0
- data/features/listen_for_client_call.feature +23 -0
- data/features/persistent_schedule.feature +70 -0
- data/features/proove_protocol.feature +20 -0
- data/features/schedule.feature +25 -0
- data/features/simple_string_protocol.feature +35 -0
- data/features/step_definitions/execute_schedule_steps.rb +16 -0
- data/features/step_definitions/group_aliases_steps.rb +24 -0
- data/features/step_definitions/handle_switches_steps.rb +21 -0
- data/features/step_definitions/listen_for_client_call_steps.rb +34 -0
- data/features/step_definitions/persistent_schedule_steps.rb +18 -0
- data/features/step_definitions/proove_protocol_steps.rb +3 -0
- data/features/step_definitions/schedule_steps.rb +9 -0
- data/features/step_definitions/shared_steps.rb +75 -0
- data/features/step_definitions/simple_string_protocol_steps.rb +3 -0
- data/features/step_definitions/sunrise_steps.rb +22 -0
- data/features/step_definitions/tellstick_connected_steps.rb +21 -0
- data/features/sunrise.feature +22 -0
- data/features/sunset.feature +22 -0
- data/features/support/action_helpers.rb +10 -0
- data/features/support/env.rb +7 -0
- data/features/support/listen_for_client_call_helper.rb +71 -0
- data/features/support/proove_helpers.rb +6 -0
- data/features/support/sunrise_helper.rb +8 -0
- data/features/tellstick_connected.feature +14 -0
- data/lib/tellstick/protocol/nexa.rb +48 -0
- data/lib/tellstick/protocol/not_connected.rb +42 -0
- data/lib/tellstick/protocol/null_protocol.rb +41 -0
- data/lib/tellstick/protocol/plain_text.rb +35 -0
- data/lib/tellstick/protocol/proove.rb +83 -0
- data/lib/tellstick/protocol/protocol_loader.rb +26 -0
- data/lib/tellstick/protocol/rising_sun.rb +42 -0
- data/lib/tellstick/protocol/waveman.rb +29 -0
- data/lib/tellstick/tellstick.rb +73 -0
- data/lib/tellstick/tellstick_io.rb +80 -0
- data/lib/tellstick.rb +20 -0
- data/lib/trigger_switch_d/action.rb +83 -0
- data/lib/trigger_switch_d/application.rb +89 -0
- data/lib/trigger_switch_d/config.rb +83 -0
- data/lib/trigger_switch_d/daylight.rb +114 -0
- data/lib/trigger_switch_d/ipc.rb +39 -0
- data/lib/trigger_switch_d/schedule.rb +95 -0
- data/lib/trigger_switch_d/switch.rb +37 -0
- data/lib/trigger_switch_d/trigger_switch_d_helper.rb +44 -0
- data/lib/trigger_switch_d.rb +26 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/tellstick/protocol/nexa_spec.rb +57 -0
- data/spec/tellstick/protocol/proove_spec.rb +61 -0
- data/spec/tellstick/protocol/rising_sun_spec.rb +56 -0
- data/spec/tellstick/protocol/waveman_spec.rb +57 -0
- data/spec/tellstick/tellstick_io_spec.rb +31 -0
- data/spec/tellstick/tellstick_spec.rb +86 -0
- data/spec/trigger_switch_d/application_spec.rb +144 -0
- data/spec/trigger_switch_d/config_spec.rb +94 -0
- data/spec/trigger_switch_d/daylight_spec.rb +39 -0
- data/spec/trigger_switch_d/ipc_spec.rb +119 -0
- data/spec/trigger_switch_d/schedule_spec.rb +103 -0
- data/spec/trigger_switch_d/trigger_switch_d_spec_helpers.rb +24 -0
- data/trigger_switch_d.gemspec +43 -0
- metadata +206 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "ftd2xx"
|
20
|
+
require "pp"
|
21
|
+
|
22
|
+
module Tellstick
|
23
|
+
|
24
|
+
#IO stream associated with the tellstick
|
25
|
+
class TellstickIO
|
26
|
+
def initialize
|
27
|
+
open
|
28
|
+
end
|
29
|
+
|
30
|
+
#writes input string to tellstick
|
31
|
+
def puts(input)
|
32
|
+
input.scan(/.{1,8}/).each do |str|
|
33
|
+
Ftd2xx.write(@handle,str)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
#reads string from tellstick
|
38
|
+
def gets
|
39
|
+
reply = ""
|
40
|
+
bytes_read = 1
|
41
|
+
c = " "
|
42
|
+
while (bytes_read != 0) and (c != "\n")
|
43
|
+
c = " "
|
44
|
+
bytes_read = Ftd2xx.read(@handle,c)
|
45
|
+
reply << c
|
46
|
+
end
|
47
|
+
reply
|
48
|
+
end
|
49
|
+
|
50
|
+
#close tellstick stream
|
51
|
+
def close
|
52
|
+
Ftd2xx.ft_close(@handle)
|
53
|
+
@handle = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
#opens tellstick stream
|
57
|
+
def open
|
58
|
+
Ftd2xx.ft_set_vidpid(0x1781,0x0c30)
|
59
|
+
device_index = Ftd2xx.create_device_info_list - 1
|
60
|
+
@handle = Ftd2xx.open(device_index)
|
61
|
+
Ftd2xx.ft_set_baud_rate(@handle,4800)
|
62
|
+
Ftd2xx.ft_set_timeouts(@handle,5000,0)
|
63
|
+
if @handle == nil
|
64
|
+
def puts(input);end
|
65
|
+
def gets;end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#true if connected
|
70
|
+
def connected?
|
71
|
+
close
|
72
|
+
open
|
73
|
+
puts("S+")
|
74
|
+
answer = gets
|
75
|
+
close
|
76
|
+
open
|
77
|
+
answer == "+S\r\n"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/tellstick.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
require "tellstick/tellstick"
|
19
|
+
require "tellstick/tellstick_io"
|
20
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__),"trigger_switch_d_helper")
|
19
|
+
|
20
|
+
module TriggerSwitchD
|
21
|
+
#Uses the ruby engine to transform code_line into method execute on an instance of Action
|
22
|
+
class Action
|
23
|
+
|
24
|
+
#Takes a code_line to be scheduled or executed together with the devices, environment
|
25
|
+
#and date to validate it.
|
26
|
+
def initialize(code_line,devices,environment=Config.default_environment,date=Date.today)
|
27
|
+
@name = code_line.strip
|
28
|
+
@date = date
|
29
|
+
@at_location = environment[:at_location]
|
30
|
+
@lookup = environment[:lookup]
|
31
|
+
tokens = code_line.scan(/(\w+) (\w+) (\w+) ([\w\d:]+)/u).flatten
|
32
|
+
(class << self;self;end).methodize_device(tokens[1],devices[tokens[1]],@lookup) if devices.include? tokens[1]
|
33
|
+
code = tokens.map do |token|
|
34
|
+
(@lookup.include? token) ? @lookup[token] : token
|
35
|
+
end.reverse
|
36
|
+
@at, executable = send(code[3], send(code[2], send(code[1], code[0])))
|
37
|
+
(class << self;self;end).methodize_executable(executable)
|
38
|
+
end
|
39
|
+
|
40
|
+
def activate(*args) #:nodoc:
|
41
|
+
action(args[0][0],args[0][1],:turn_on)
|
42
|
+
end
|
43
|
+
|
44
|
+
def deactivate(*args) #:nodoc:
|
45
|
+
action(args[0][0],args[0][1],:turn_off)
|
46
|
+
end
|
47
|
+
|
48
|
+
def at(*args) #:nodoc:
|
49
|
+
return @at if args[0] == nil
|
50
|
+
if (args[0] =~ /(?:2[0-3]|[01]\d):[0-5]\d/) == 0
|
51
|
+
return args[0]
|
52
|
+
end
|
53
|
+
return @date.extend(Daylight).send(args[0],@at_location).localtime.strftime("%H:%M")
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
@name
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def action(*args)
|
63
|
+
switches, at_time, event = args
|
64
|
+
code = Proc.new do |output|
|
65
|
+
switches.each do |switch|
|
66
|
+
Tellstick::create(output,switch.model_name).send(event,switch.house_code, switch.unit_code)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
[at_time,code]
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.methodize_executable(executable)
|
73
|
+
define_method(:execute,&executable)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.methodize_device(name,switches,lookup)
|
77
|
+
lookup[name] = :remote_device.to_s
|
78
|
+
define_method(:remote_device) do |*args|
|
79
|
+
[switches,args[0]]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'socket'
|
18
|
+
require 'yaml'
|
19
|
+
require 'logger'
|
20
|
+
require 'ipc'
|
21
|
+
|
22
|
+
|
23
|
+
module TriggerSwitchD
|
24
|
+
|
25
|
+
#starts an instance of the daemon.
|
26
|
+
class Application
|
27
|
+
attr_reader :devices, :schedule, :logger
|
28
|
+
alias_method :list_devices, :devices
|
29
|
+
|
30
|
+
#Prepares the run by loading up the environment
|
31
|
+
#located in config/config.rb
|
32
|
+
def initialize(config_file)
|
33
|
+
@current_date = Date.new
|
34
|
+
ConfigFactory.new(config_file)
|
35
|
+
@logger = Logger.new(Config.log_object)
|
36
|
+
logger.info("Environment prepared")
|
37
|
+
end
|
38
|
+
|
39
|
+
#Runs the daemon untill process killed or it receives
|
40
|
+
#stop from client connected via unix socket
|
41
|
+
def start
|
42
|
+
com_thread = IPC.create(Config.unix_socket_path)
|
43
|
+
logger.info("IPC started")
|
44
|
+
com_thread["received"] = "anything"
|
45
|
+
while ((command = com_thread["received"].to_sym) != :stop)
|
46
|
+
now_time = Time.new
|
47
|
+
load_db(now_time.strftime("%Y-%m-%d %H:%M:%S"))
|
48
|
+
hhmm_now_time = now_time.strftime("%H:%M")
|
49
|
+
if methods.include? command.to_s
|
50
|
+
com_thread["response"] = send(command).to_yaml
|
51
|
+
logger.info("Received #{command} via IPC")
|
52
|
+
Config.log_object.flush
|
53
|
+
com_thread["received"] = "anything"
|
54
|
+
com_thread.run
|
55
|
+
end
|
56
|
+
if (schedule.cronological.keys.include? hhmm_now_time)
|
57
|
+
logger.info("Executed #{schedule.cronological[hhmm_now_time].length} action(s) at #{hhmm_now_time}")
|
58
|
+
Config.log_object.flush
|
59
|
+
schedule.execute(hhmm_now_time,Config.output)
|
60
|
+
end
|
61
|
+
Kernel.sleep(1)
|
62
|
+
com_thread["received"] = "anything" if com_thread["received"] == ""
|
63
|
+
end
|
64
|
+
logger.info("Received #{command} via IPC")
|
65
|
+
end
|
66
|
+
|
67
|
+
def list_schedule #:nodoc:
|
68
|
+
schedule.by_name.keys
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def load_db(time)
|
74
|
+
date = Date.parse(time)
|
75
|
+
return unless @current_date < date
|
76
|
+
file = File.open(Config.db_path[0],"r")
|
77
|
+
@devices = TriggerSwitchD::load_devices(file)
|
78
|
+
file.close
|
79
|
+
@schedule = Schedule.create
|
80
|
+
file = File.open(Config.db_path[1],"r")
|
81
|
+
TriggerSwitchD::load_scheduled_actions(file,@schedule,devices,Config.environment)
|
82
|
+
file.close
|
83
|
+
logger.info("Loaded #{devices.length} devices and #{schedule.by_name.length} actions")
|
84
|
+
Config.log_object.flush
|
85
|
+
@current_date = date
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
module TriggerSwitchD
|
19
|
+
module ConfigFactory
|
20
|
+
|
21
|
+
#Creates the Config class from the config/config.rb file
|
22
|
+
#See samples/config.rb for more documentation
|
23
|
+
def self.new(file=StringIO.new)
|
24
|
+
env = file.readlines
|
25
|
+
attributes = env.map do |attribute|
|
26
|
+
attribute.scan(/Config.([\w_]+) =/).flatten[0]
|
27
|
+
end
|
28
|
+
cls = <<-EOS
|
29
|
+
class Config
|
30
|
+
#{attributes.map {|name| "def self.#{name}=(value); #{append_filenames(name)}; end"}.join("\n")}
|
31
|
+
|
32
|
+
#{attributes.map {|name| "def self.#{name}; @#{name}; end"}.join("\n")}
|
33
|
+
|
34
|
+
def self.default_environment
|
35
|
+
{:lookup => {"tänd" => "activate",
|
36
|
+
"släck" => "deactivate",
|
37
|
+
"soluppgång" => "sunrise",
|
38
|
+
"solnedgång" => "sunset",
|
39
|
+
"klockan" => "at",
|
40
|
+
"vid" => "at"},
|
41
|
+
:at_location => {:north => 0.0, :west => 0.0}}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
EOS
|
45
|
+
::TriggerSwitchD.module_eval(cls)
|
46
|
+
setup_environment(env)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def self.setup_environment(env)
|
51
|
+
env.map do |attribute|
|
52
|
+
::TriggerSwitchD.module_eval(attribute)
|
53
|
+
end
|
54
|
+
def Config.environment
|
55
|
+
result = default_environment
|
56
|
+
file = File.open(Config.dsl_path,"r")
|
57
|
+
result[:lookup] = YAML::load(file)
|
58
|
+
file.close
|
59
|
+
result[:at_location] = Config.geo_position
|
60
|
+
result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.set_type(name)
|
65
|
+
types = {"log_object" => "{:spec => StringIO.new, :development => STDOUT, :file => File.open(\"#log_path}\",\"a+\")}",
|
66
|
+
"output" => "{:spec => StringIO.new, :development => STDOUT, :tellstick => Tellstick::TellstickIO.new}"}
|
67
|
+
return "@#{name}=value" unless types.keys.include? name
|
68
|
+
"@#{name}=#{types[name]}[value]".gsub("log_path","{log_path")
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.append_filenames(name)
|
72
|
+
filenames = {"log_path" => ["tsd.log"], "db_path" => ["devices","scheduled_actions"],
|
73
|
+
"dsl_path" => ["lookup.dsl"], "unix_socket_path" => ["com.adhocskill.trigger_switch_d"]}
|
74
|
+
return set_type(name) unless filenames.keys.include? name
|
75
|
+
result = filenames[name].map do |fname|
|
76
|
+
"#value}/#{fname}"
|
77
|
+
end.inspect.gsub("value","{value")
|
78
|
+
result = result.gsub("[","").gsub("]","") if filenames[name].length == 1
|
79
|
+
"@#{name}=#{result}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
# External referenses used:
|
19
|
+
# http://www.stjarnhimlen.se (accessed 2010-03-02)
|
20
|
+
# http://users.electromagnetic.net/bu/astro/sunrise-set.php (accessed 2010-03-02)
|
21
|
+
# http://www.astro.uu.nl/~strous/AA/en/reken/zonpositie.html (accessed 2010-03-02)
|
22
|
+
|
23
|
+
module Daylight #:nodoc:all
|
24
|
+
|
25
|
+
JULIAN_DAYS_UNTIL_YEAR_2000 = 2451545.0
|
26
|
+
UNIT_CIRCLE = 360.0
|
27
|
+
C1 = 0.0009
|
28
|
+
C2 = 357.5291
|
29
|
+
C3 = 0.98560028
|
30
|
+
C4 = 1.9148
|
31
|
+
C5 = 0.0200
|
32
|
+
C6 = 0.0003
|
33
|
+
C7 = 102.9372
|
34
|
+
C8 = 0.0053
|
35
|
+
C9 = 0.0069
|
36
|
+
C10 = 23.45
|
37
|
+
C11 = -0.83
|
38
|
+
FOR = {:sunrise => -1, :sunset => 1}
|
39
|
+
|
40
|
+
def self.extended(receiver)
|
41
|
+
days = receiver.jd
|
42
|
+
raise "method jd on #{receiver} does not return Fixnum" unless days.kind_of? Fixnum
|
43
|
+
end
|
44
|
+
|
45
|
+
def sunrise(at_location)
|
46
|
+
time_for(:sunrise,at_location)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sunset(at_location)
|
50
|
+
time_for(:sunset,at_location)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def time_for(what_time,at_location)
|
56
|
+
__prepare_float__
|
57
|
+
n = ((days_since_2000 - C1) - per_unit_circle(at_location[:west])).round
|
58
|
+
j = JULIAN_DAYS_UNTIL_YEAR_2000 + C1 + (per_unit_circle(at_location[:west])) + n
|
59
|
+
|
60
|
+
transit_approx = stable_transit_approximation(j)
|
61
|
+
|
62
|
+
declination = Math.asin(Math.sin(transit_approx[:lamda].to_rad) * Math.sin(C10.to_rad)).to_degrees
|
63
|
+
h = (Math.acos((Math.sin(C11.to_rad) - Math.sin(at_location[:north].to_rad)*Math.sin(declination.to_rad))/(Math.cos(at_location[:north].to_rad) * Math.cos(declination.to_rad)))).to_degrees
|
64
|
+
j2 = JULIAN_DAYS_UNTIL_YEAR_2000 + C1 + per_unit_circle(FOR[what_time]*h + at_location[:west]) + n
|
65
|
+
raw = j2 + (C8 * Math.sin(transit_approx[:m].to_rad)) - (C9 * Math.sin(2*transit_approx[:lamda].to_rad))
|
66
|
+
dt = DateTime.jd(raw).new_offset(0.5)
|
67
|
+
Time.utc(dt.year,dt.month,dt.day,dt.hour,dt.min,dt.sec,0)
|
68
|
+
end
|
69
|
+
|
70
|
+
def stable_transit_approximation(j)
|
71
|
+
transit_approx = transit_approximation(j,j)
|
72
|
+
count = 5
|
73
|
+
until((transit_approx == (transit_approx = transit_approximation(j,transit_approx[:transit]))) || count <= 0)
|
74
|
+
count -= 1
|
75
|
+
end
|
76
|
+
transit_approx
|
77
|
+
end
|
78
|
+
|
79
|
+
def transit_approximation(j,transit)
|
80
|
+
m = mod_unit_circle(C2 + C3 * (transit - JULIAN_DAYS_UNTIL_YEAR_2000))
|
81
|
+
c = (C4 * Math.sin(m.to_rad)) + (C5 * Math.sin(2 * m.to_rad)) + (C6 * Math.sin(3 * m.to_rad))
|
82
|
+
lamda = mod_unit_circle(m + C7 + c + UNIT_CIRCLE/2)
|
83
|
+
transit = j + (C8 * Math.sin(m.to_rad)) - (C9 * Math.sin(2 * lamda.to_rad))
|
84
|
+
{:m => m, :lamda => lamda, :transit => transit}
|
85
|
+
end
|
86
|
+
|
87
|
+
def days_since_2000
|
88
|
+
self.jd - JULIAN_DAYS_UNTIL_YEAR_2000
|
89
|
+
end
|
90
|
+
|
91
|
+
def per_unit_circle(value)
|
92
|
+
value / UNIT_CIRCLE
|
93
|
+
end
|
94
|
+
|
95
|
+
def mod_unit_circle(value)
|
96
|
+
value % UNIT_CIRCLE
|
97
|
+
end
|
98
|
+
|
99
|
+
def __prepare_float__
|
100
|
+
Float.class_eval {include DayFloat}
|
101
|
+
def __prepare_float__
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
module DayFloat
|
106
|
+
def to_rad
|
107
|
+
self * Math::PI/180.0
|
108
|
+
end
|
109
|
+
def to_degrees
|
110
|
+
self * 180.0/Math::PI
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module TriggerSwitchD
|
18
|
+
module IPC
|
19
|
+
|
20
|
+
#unix socket thread, see README.rdoc for usage
|
21
|
+
def self.create(socket_path)
|
22
|
+
File.delete(socket_path) if File.exist? socket_path
|
23
|
+
sock = UNIXServer.open(socket_path)
|
24
|
+
Thread.start(sock) do |sock|
|
25
|
+
while(!["stop"].include?(Thread.current["received"]))
|
26
|
+
Thread.current["received"] = ""
|
27
|
+
s1 = sock.accept
|
28
|
+
while(!["stop","bye"].include?(Thread.current["received"]))
|
29
|
+
Thread.current["received"] = s1.recvfrom(200)[0]
|
30
|
+
Thread.current["response"] = Thread.current["received"] if Thread.current["received"] == "bye"
|
31
|
+
Thread.stop if !["bye",""].include?(Thread.current["received"])
|
32
|
+
s1.send(Thread.current["response"],0) unless Thread.current["received"] == ""
|
33
|
+
Thread.current["received"] = "bye" if Thread.current["received"] == ""
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__),"trigger_switch_d_helper")
|
19
|
+
require File.join(File.dirname(__FILE__),"action")
|
20
|
+
|
21
|
+
module TriggerSwitchD
|
22
|
+
#Holds actions organized by name and cronological
|
23
|
+
#Use create to instasiate
|
24
|
+
module Schedule
|
25
|
+
module InstanceMethods
|
26
|
+
def schedule_action(action)
|
27
|
+
self._insert_action_(action) if find(action.to_s) == nil
|
28
|
+
find(action.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
#find by name
|
32
|
+
def find(name)
|
33
|
+
by_name[name]
|
34
|
+
end
|
35
|
+
|
36
|
+
#Returns when the next action is scheduled to occur
|
37
|
+
#based on the hour_minute. The format is "HH:MM" for both
|
38
|
+
#hour_minute as well as the result, with the exception
|
39
|
+
#that if no next action is found it will return
|
40
|
+
#"23:59:59"
|
41
|
+
def next_action_at(hour_minute)
|
42
|
+
end_of_day = "23:59:59"
|
43
|
+
return end_of_day unless hour_minute =~ /\d{2}:\d{2}/
|
44
|
+
time = Time.parse(hour_minute)
|
45
|
+
cronological.keys.sort {|x,y| Time.parse(x) <=> Time.parse(y)}.find(Proc.new {end_of_day}) do |at|
|
46
|
+
time < Time.parse(at)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#deletes action from schedule, returning the action on exit
|
51
|
+
def delete(name)
|
52
|
+
action = by_name.delete(name)
|
53
|
+
cronological[action.at].delete(name)
|
54
|
+
end
|
55
|
+
|
56
|
+
#Executes action and removes it from the schedule
|
57
|
+
def execute(at,output)
|
58
|
+
cronological[at].values.each { |action| action.execute(output) } unless cronological[at] == nil
|
59
|
+
self._remove_executed_actions_from_schedule_(at)
|
60
|
+
end
|
61
|
+
|
62
|
+
#Hash of actions accessible by "HH:MM" format
|
63
|
+
def cronological
|
64
|
+
self[:cronological]
|
65
|
+
end
|
66
|
+
|
67
|
+
#Hash of actions accessible by name
|
68
|
+
def by_name
|
69
|
+
self[:all]
|
70
|
+
end
|
71
|
+
|
72
|
+
def _remove_executed_actions_from_schedule_(at) #:nodoc:
|
73
|
+
cronological[at].values.clone.each do |element|
|
74
|
+
by_name.delete(element.to_s)
|
75
|
+
end unless cronological[at] == nil
|
76
|
+
cronological.delete(at)
|
77
|
+
end
|
78
|
+
|
79
|
+
def _insert_action_(action) #:nodoc:
|
80
|
+
name = action.to_s
|
81
|
+
by_name[name] = action
|
82
|
+
cronological[action.at] ||= {}
|
83
|
+
cronological[action.at][name] = by_name[name]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#Creates an instance of a schedule
|
88
|
+
def create
|
89
|
+
schedule = {:all => {}, :cronological => {}}
|
90
|
+
schedule.extend InstanceMethods
|
91
|
+
end
|
92
|
+
|
93
|
+
module_function :create
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
module TriggerSwitchD
|
19
|
+
module SwitchFactory
|
20
|
+
#Creates the Switch class dynamically from values, which is
|
21
|
+
#assumed to be an Array of attributes/keys
|
22
|
+
def self.new(values)
|
23
|
+
definition = <<-EOS
|
24
|
+
class Switch
|
25
|
+
attr_reader #{values.map {|name| ":#{name}"}.join(",")}
|
26
|
+
def initialize(value)
|
27
|
+
value.each_pair do |key,value|
|
28
|
+
instance_variable_set("@"+key.to_s,value) if respond_to?(key)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
EOS
|
33
|
+
::TriggerSwitchD.module_eval(definition)
|
34
|
+
::TriggerSwitchD.const_get("Switch")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# TriggerSwitchD, executes commands to activate/deactive remote switches.
|
2
|
+
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
module TriggerSwitchD
|
19
|
+
|
20
|
+
#Loads up schedule with the actions in file
|
21
|
+
def load_scheduled_actions(file,schedule,devices,environment,date=Date.today)
|
22
|
+
rows = file.readlines
|
23
|
+
rows.each do |code_line|
|
24
|
+
action = Action.new(code_line,devices,environment,date)
|
25
|
+
schedule.schedule_action(action) #unless Time.parse(action.at) < Time.now
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#Returns devices loaded from file
|
30
|
+
def load_devices(file)
|
31
|
+
devices = YAML::load(file)
|
32
|
+
SwitchFactory.new(devices[0]["switches"][0].keys)
|
33
|
+
result = {}
|
34
|
+
devices.each do |device|
|
35
|
+
switches = device["switches"].map do |switch|
|
36
|
+
TriggerSwitchD::Switch.new(switch)
|
37
|
+
end
|
38
|
+
result[device["name"]] = switches
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
module_function :load_scheduled_actions, :load_devices
|
44
|
+
end
|