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.
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"