lightwaverf 0.12.1 → 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/lightwaverf +2 -0
- data/lib/lightwaverf.rb +124 -22
- metadata +6 -6
data/bin/lightwaverf
CHANGED
@@ -20,6 +20,8 @@ case ARGV[0]
|
|
20
20
|
puts obj.learnmood ARGV[1], ARGV[2], ARGV[3]
|
21
21
|
when 'energy'
|
22
22
|
puts obj.energy ARGV[1], ARGV[2], ARGV[3]
|
23
|
+
when 'schedule'
|
24
|
+
puts obj.schedule ARGV[1]
|
23
25
|
when 'update_timers'
|
24
26
|
puts obj.update_timers ARGV[1], ARGV[2], ARGV[3]
|
25
27
|
when 'timer'
|
data/lib/lightwaverf.rb
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
# Cope with events that start and end in the same run?
|
6
6
|
# Add info about states to timer log
|
7
7
|
|
8
|
+
# require 'tzinfo'
|
8
9
|
require 'yaml'
|
9
10
|
require 'socket'
|
10
11
|
require 'net/http'
|
@@ -143,14 +144,8 @@ class LightWaveRF
|
|
143
144
|
end
|
144
145
|
|
145
146
|
if config['calendar']
|
146
|
-
crontab << '# ' + executable + '
|
147
|
-
crontab << '56
|
148
|
-
crontab << '# ' + executable + ' update_timers on reboot (works for me on raspbian)'
|
149
|
-
crontab << '@reboot ' + executable + ' update_timers 120 360 > /tmp/lightwaverf_update_timers.out 2>&1'
|
150
|
-
crontab << '# ' + executable + ' timer every 10 mins off peak'
|
151
|
-
crontab << '*/10 0-6,9-16,23 * * * ' + executable + ' timer 10 > /tmp/lightwaverf_timer.out 2>&1'
|
152
|
-
crontab << '# ' + executable + ' timer every 2 minutes peak'
|
153
|
-
crontab << '*/2 7,8,17-22 * * * ' + executable + ' timer 2 > /tmp/lightwaverf_timer.out 2>&1'
|
147
|
+
crontab << '# ' + executable + ' update schedule ONLY ONCE A DAY'
|
148
|
+
crontab << '56 0 * * * ' + executable + ' schedule true > /tmp/lightwaverf_schedule.out 2>&1'
|
154
149
|
end
|
155
150
|
|
156
151
|
config['room'].each do | room |
|
@@ -169,6 +164,99 @@ class LightWaveRF
|
|
169
164
|
'Saved config file ' + file
|
170
165
|
end
|
171
166
|
|
167
|
+
def schedule debug = false
|
168
|
+
id = 'lwrf_cron'
|
169
|
+
executable = `which lightwaverf`.chomp
|
170
|
+
if (executable == "")
|
171
|
+
puts 'did not get executable from `which lightwaverf` - do we have ' + File.expand_path(__FILE__) + '../bin/lightwaverf ???'
|
172
|
+
# executable = File.expand_path(__FILE__) + '/../bin/lightwaverf'
|
173
|
+
executable = '/usr/local/bin/lightwaverf'
|
174
|
+
end
|
175
|
+
if (!executable)
|
176
|
+
puts 'still no, bah, aborting'
|
177
|
+
return
|
178
|
+
end
|
179
|
+
crontab = `crontab -l`.split( /\n/ ) || [ ]
|
180
|
+
crontab = crontab.reject do | line |
|
181
|
+
line =~ Regexp.new( id )
|
182
|
+
end
|
183
|
+
crontab << '# ' + id + ' new crontab added by `' + executable + ' cron`'
|
184
|
+
|
185
|
+
body = self.calendar_body(debug)
|
186
|
+
|
187
|
+
cals = RiCal.parse_string(body)
|
188
|
+
|
189
|
+
cals.first.events.each do | e |
|
190
|
+
event = self.tokenise_event e, debug
|
191
|
+
event = self.get_modifiers event, debug
|
192
|
+
event.delete 'command'
|
193
|
+
event.delete 'modifier_start'
|
194
|
+
event.delete 'time_modifier'
|
195
|
+
|
196
|
+
endDate = nil
|
197
|
+
|
198
|
+
match = /UNTIL=(\d+)/.match(event['rrule'].to_s)
|
199
|
+
if match
|
200
|
+
endDate = DateTime.parse(match[1].to_s)
|
201
|
+
end
|
202
|
+
|
203
|
+
match = /FREQ=(\w+);COUNT=(\d+)/.match(event['rrule'])
|
204
|
+
# FREQ=DAILY;COUNT=8 - need to check for weekly, monthly etc
|
205
|
+
if match
|
206
|
+
endDate = event['date'] + match[2].to_i
|
207
|
+
end
|
208
|
+
|
209
|
+
if !event['rrule']
|
210
|
+
endDate = event['date']
|
211
|
+
end
|
212
|
+
|
213
|
+
if endDate
|
214
|
+
if endDate < Date.today
|
215
|
+
next
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
if event['type'] == 'device' and event['state'] != 'on' and event['state'] != 'off'
|
220
|
+
event['room'] = 'sequence' if event['room'].nil?
|
221
|
+
crontab << self.cron_entry(event, executable)
|
222
|
+
end_event = event.dup # duplicate event for start and end
|
223
|
+
end_event['date'] = event['end']
|
224
|
+
end_event['state'] = 'off'
|
225
|
+
crontab << self.cron_entry(end_event, executable)
|
226
|
+
else
|
227
|
+
event['room'] = 'sequence' if event['room'].nil?
|
228
|
+
crontab << self.cron_entry(event, executable, true)
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
end
|
233
|
+
File.open( '/tmp/cron.tab', 'w' ) do | handle |
|
234
|
+
handle.write crontab.join( "\n" ) + "\n"
|
235
|
+
end
|
236
|
+
puts `crontab /tmp/cron.tab`
|
237
|
+
end
|
238
|
+
|
239
|
+
def cron_entry event, executable, extra_debug = false
|
240
|
+
id = 'lwrf_cron ' + event['rrule'].to_s + (extra_debug ? ' ' + event.inspect : '')
|
241
|
+
event['state'] = 'on' if event['state'].nil?
|
242
|
+
cmd = event['room'].to_s + ' ' + event['device'].to_s + ' ' + event['state'].to_s
|
243
|
+
out_file = '/tmp/' + cmd + '.out'
|
244
|
+
out_file.gsub! /\s/, '-'
|
245
|
+
return self.cron_entry_times(event) + ' ' + executable + ' ' + cmd + ' > ' + out_file + ' 2>&1 # ' + id
|
246
|
+
end
|
247
|
+
|
248
|
+
def cron_entry_times event
|
249
|
+
return event['date'].strftime('%M %H * * *') if event['rrule'] == 'FREQ=DAILY'
|
250
|
+
match = /BYDAY=([\w,]+)/.match(event['rrule'])
|
251
|
+
return event['date'].strftime('%M %H * * ') + self.rrule_days_of_week(match[1]) if match
|
252
|
+
return event['date'].strftime('%M %H %d %m *') if event['date']
|
253
|
+
return '# 0 12 * * *';
|
254
|
+
end
|
255
|
+
|
256
|
+
def rrule_days_of_week days
|
257
|
+
return days.gsub('SU', '0').gsub('MO', '1').gsub('TU', '2').gsub('WE', '3').gsub('TH', '4').gsub('FR', '5').gsub('SA', '6')
|
258
|
+
end
|
259
|
+
|
172
260
|
def get_config_file
|
173
261
|
@config_file || File.expand_path('~') + '/lightwaverf-config.yml'
|
174
262
|
end
|
@@ -798,7 +886,6 @@ class LightWaveRF
|
|
798
886
|
# handle optional state
|
799
887
|
if event['command'].length > 2
|
800
888
|
first_char = event['command'][2].to_s[0,1]
|
801
|
-
debug and ( p 'First char is: ' + first_char )
|
802
889
|
# if the third word does not start with a modifier flag, assume it's a state
|
803
890
|
if /\w/.match first_char
|
804
891
|
event['state'] = event['command'][2].to_s
|
@@ -829,19 +916,20 @@ class LightWaveRF
|
|
829
916
|
debug and ( p 'Found unless modifier: ' + modifier[1..-1] )
|
830
917
|
event['unless_modifiers'].push modifier[1..-1]
|
831
918
|
elsif modifier[0,1] == '+'
|
832
|
-
debug and ( p 'Found positive time modifier: ' + modifier[1..-1] )
|
833
919
|
event['time_modifier'] = modifier[1..-1].to_i
|
834
920
|
elsif modifier[0,1] == '-'
|
835
|
-
debug and ( p 'Found negative time modifier: ' + modifier[1..-1] )
|
836
921
|
event['time_modifier'] = modifier[1..-1].to_i * -1
|
837
922
|
end
|
838
923
|
end
|
839
924
|
end
|
840
925
|
event['time_modifier'] += self.class.variance( event['summary'] ).to_i
|
841
926
|
if event['time_modifier'] != 0
|
842
|
-
debug and (
|
927
|
+
debug and (p 'Adjusting timings by: ' + event['time_modifier'].to_s + ' ' + event.inspect)
|
843
928
|
event['date'] = (( event['date'].to_time ) + event['time_modifier'] * 60 ).to_datetime
|
844
|
-
|
929
|
+
if event['end']
|
930
|
+
event['end'] = (( event['end'].to_time ) + event['time_modifier'] * 60 ).to_datetime
|
931
|
+
end
|
932
|
+
debug and (p 'dates now ' + event['date'].to_s + ' ' + event['end'].to_s)
|
845
933
|
end
|
846
934
|
event
|
847
935
|
end
|
@@ -853,29 +941,43 @@ class LightWaveRF
|
|
853
941
|
event['annotate'] = !( /do not annotate/.match event['summary'] )
|
854
942
|
event['date'] = e.dtstart
|
855
943
|
event['end'] = e.dtend
|
944
|
+
if e.rrule.length > 0
|
945
|
+
event['rrule'] = e.rrule.first
|
946
|
+
# event['rrules'] = event['rrule'].split(';')
|
947
|
+
end
|
856
948
|
event = set_event_type event, debug
|
857
949
|
end
|
858
950
|
|
859
|
-
def
|
860
|
-
p '-- Updating timers...'
|
861
|
-
|
862
|
-
query_start = Time.new - self.class.to_seconds( past )
|
863
|
-
query_end = Time.new + self.class.to_seconds( future )
|
864
|
-
|
951
|
+
def calendar_body debug = false
|
865
952
|
url = self.get_calendar_url debug
|
866
953
|
debug and ( p url )
|
867
954
|
response = self.request url, debug
|
868
955
|
if response.code != '200'
|
869
956
|
debug and ( p "Response code is: " + response.code)
|
870
|
-
return self.log_timer_event 'update', nil, nil, nil, false
|
871
957
|
end
|
958
|
+
return response.body
|
959
|
+
end
|
960
|
+
|
961
|
+
def update_timers past = 60, future = 1440, debug = false
|
962
|
+
p '-- Updating timers...'
|
963
|
+
|
964
|
+
query_start = Time.new - self.class.to_seconds( past )
|
965
|
+
query_end = Time.new + self.class.to_seconds( future )
|
872
966
|
|
873
|
-
|
967
|
+
body = self.calendar_body(debug)
|
968
|
+
|
969
|
+
cals = RiCal.parse_string(body)
|
874
970
|
|
875
971
|
timers = { 'events' => [ ], 'states' => [ ] }
|
876
972
|
|
877
973
|
cals.first.events.each do | e |
|
878
|
-
|
974
|
+
begin
|
975
|
+
occurs = e.occurrences(:overlapping => [query_start, query_end])
|
976
|
+
rescue StandardError => err
|
977
|
+
p err.to_s
|
978
|
+
p e.to_s
|
979
|
+
occurs = []
|
980
|
+
end
|
879
981
|
next if occurs.length == 0
|
880
982
|
occurs.each do | occurrence |
|
881
983
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lightwaverf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2016-
|
14
|
+
date: 2016-08-08 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: htmlentities
|
@@ -50,17 +50,17 @@ dependencies:
|
|
50
50
|
requirement: !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ~>
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '1'
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
59
59
|
none: false
|
60
60
|
requirements:
|
61
|
-
- -
|
61
|
+
- - ~>
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '
|
63
|
+
version: '1'
|
64
64
|
description: ! " Interact with lightwaverf wifi-link from code or the command line.\n
|
65
65
|
\ Control your lights, heating, sockets, sprinkler etc.\n Also use ical calendar,
|
66
66
|
for timers, log energy usage, and build a website.\n"
|