lightwaverf 0.12.1 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/lightwaverf +2 -0
  2. data/lib/lightwaverf.rb +124 -22
  3. 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 + ' cache timed events 2 hours back 6 hours ahead'
147
- crontab << '56 * * * * ' + executable + ' update_timers 120 360 > /tmp/lightwaverf_update_timers.out 2>&1'
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 ( p 'Adjusting timings by: ' + event['time_modifier'].to_s )
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
- event['end'] = (( event['end'].to_time ) + event['time_modifier'] * 60 ).to_datetime
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 update_timers past = 60, future = 1440, debug = false
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
- cals = RiCal.parse_string( response.body )
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
- occurs = e.occurrences( :overlapping => [ query_start, query_end ] )
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.12.1
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-02-04 00:00:00.000000000 Z
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: '0'
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: '0'
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"