lightwaverf 0.12.1 → 0.13.1
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/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"
|