lightwaverf 0.6.0 → 0.6.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/app/views/_graphs.ejs +5 -2
  2. data/lib/lightwaverf.rb +114 -88
  3. metadata +2 -2
@@ -42,8 +42,6 @@
42
42
  energy_data.addRows( raw_data.map( function ( e ) {
43
43
  if ( e[0] !== start_date ) e[0] += start_date;
44
44
  e[0] = new Date( 1000 * e[0] ); // as it is now a timestamp
45
- // var d = '' + e[0];
46
- // e[0] = new Date( '20' + d[0] + d[1] + '-' + d[2] + d[3] + '-' + d[4] + d[5] + ' ' + d[6] + d[7] + ':' + d[8] + d[9] );
47
45
  e[1] = e[1] * 10;
48
46
  e[2] = e[2] || '';
49
47
  e[3] = e[3] || '';
@@ -66,6 +64,7 @@
66
64
  gauge.draw( gauge_data, gauge_options );
67
65
  } );
68
66
  $( function ( ) {
67
+ var key = 'foo';
69
68
  $('dt a').click( function ( ) {
70
69
  $(this).parent( ).next('dd').slideDown( );
71
70
  return false;
@@ -75,6 +74,10 @@
75
74
  var status = $a.data( 'status' ) == 'on' ? 'off' : 'on';
76
75
  $.ajax( {
77
76
  url: $a.attr('href') + '?status=' + status,
77
+ data: {
78
+ status: status,
79
+ key: key,
80
+ },
78
81
  type: 'PUT',
79
82
  success: function( js ) {
80
83
  $a.data( 'status', status );
data/lib/lightwaverf.rb CHANGED
@@ -538,19 +538,33 @@ class LightWaveRF
538
538
  match = /W=(\d+),(\d+),(\d+),(\d+)/.match data
539
539
  debug and ( p match )
540
540
  if match
541
- data = { 'message' => { 'usage' => match[1].to_i, 'max' => match[2].to_i, 'today' => match[3].to_i }}
541
+ data = {
542
+ 'message' => {
543
+ 'usage' => match[1].to_i,
544
+ 'max' => match[2].to_i,
545
+ 'today' => match[3].to_i
546
+ }
547
+ }
542
548
  data['timestamp'] = Time.now.to_s
543
549
  if note
544
550
  data['message']['annotation'] = { 'title' => title.to_s, 'text' => note.to_s }
545
551
  end
546
552
  debug and ( p data )
547
553
  begin
548
- File.open( self.get_log_file, 'a' ) do | f |
554
+ File.open( self.get_log_file, 'a' ) do | f |
549
555
  f.write( data.to_json + "\n" )
550
- end
551
- data['message']
556
+ end
557
+ file = self.get_summary_file.gsub 'summary', 'daily'
558
+ json = self.class.get_contents file
559
+ begin
560
+ data['message']['history'] = JSON.parse json
561
+ rescue => e
562
+ data['message']['error'] = 'error parsing ' + file + '; ' + e.to_s
563
+ data['message']['history_json'] = json
564
+ end
565
+ data['message']
552
566
  rescue
553
- puts 'error writing to log'
567
+ puts 'error writing to log'
554
568
  end
555
569
  end
556
570
  end
@@ -592,9 +606,15 @@ class LightWaveRF
592
606
  query_start = now - self.class.to_seconds( past )
593
607
  query_end = now + self.class.to_seconds( future )
594
608
 
595
- url = LightWaveRF.new.get_config['calendar']
596
- # url += '?ctz=' + Time.new.zone
597
- url += '?ctz=UTC'
609
+ # url = LightWaveRF.new.get_config['calendar']
610
+ url = self.get_config['calendar']
611
+
612
+ url += '?ctz=' + Time.new.zone
613
+ # url += '?ctz=UTC'
614
+ if Time.new.zone != 'UTC'
615
+ p 'time zone is ' + Time.new.zone + ' so look out...'
616
+ end
617
+
598
618
  url += '&singleevents=true'
599
619
  url += '&start-min=' + query_start.strftime( '%FT%T%:z' ).sub('+', '%2B')
600
620
  url += '&start-max=' + query_end.strftime( '%FT%T%:z' ).sub('+', '%2B')
@@ -625,20 +645,20 @@ class LightWaveRF
625
645
 
626
646
  # refresh the list of entries for the caching period
627
647
  doc.elements.each 'feed/entry' do | e |
628
- debug and ( p "-------------------")
629
- debug and ( p "Processing entry...")
648
+ debug and ( p '-------------------' )
649
+ debug and ( p 'Processing entry...' )
630
650
  event = Hash.new
631
651
 
632
652
  # tokenise the title
633
- debug and ( p "Event title is: " + e.elements['title'].text )
653
+ debug and ( p 'Event title is: ' + e.elements['title'].text )
634
654
  command = e.elements['title'].text.split
635
655
  command_length = command.length
636
- debug and ( p "Number of words is: " + command_length.to_s )
656
+ debug and ( p 'Number of words is: ' + command_length.to_s )
637
657
  if command and command.length >= 1
638
658
  first_word = command[0].to_s
639
659
  # determine the type of the entry
640
660
  if first_word[0,1] == '#'
641
- debug and ( p "Type is: state" )
661
+ debug and ( p 'Type is: state' )
642
662
  event['type'] = 'state' # temporary type, will be overridden later
643
663
  event['room'] = nil
644
664
  event['device'] = nil
@@ -647,21 +667,21 @@ class LightWaveRF
647
667
  else
648
668
  case first_word
649
669
  when 'mood'
650
- debug and ( p "Type is: mood" )
670
+ debug and ( p 'Type is: mood' )
651
671
  event['type'] = 'mood'
652
672
  event['room'] = command[1].to_s
653
673
  event['device'] = nil
654
674
  event['state'] = command[2].to_s
655
675
  modifier_start = 3
656
676
  when 'sequence'
657
- debug and ( p "Type is: sequence" )
677
+ debug and ( p 'Type is: sequence' )
658
678
  event['type'] = 'sequence'
659
679
  event['room'] = nil
660
680
  event['device'] = nil
661
681
  event['state'] = command[1].to_s
662
682
  modifier_start = 2
663
683
  else
664
- debug and ( p "Type is: device" )
684
+ debug and ( p 'Type is: device' )
665
685
  event['type'] = 'device'
666
686
  event['room'] = command[0].to_s
667
687
  event['device'] = command[1].to_s
@@ -669,18 +689,19 @@ class LightWaveRF
669
689
  if command_length > 2
670
690
  third_word = command[2].to_s
671
691
  first_char = third_word[0,1]
672
- debug and ( p "First char is: " + first_char )
692
+ debug and ( p 'First char is: ' + first_char )
673
693
  # if the third word does not start with a modifier flag, assume it's a state
674
- if first_char != '@' and first_char != '!' and first_char != '+' and first_char != '-'
675
- debug and ( p "State has been given.")
694
+ # if first_char != '@' and first_char != '!' and first_char != '+' and first_char != '-'
695
+ if /\w/.match first_char
696
+ debug and ( p 'State has been given.')
676
697
  event['state'] = command[2].to_s
677
698
  modifier_start = 3
678
699
  else
679
- debug and ( p "State has not been given." )
700
+ debug and ( p 'State has not been given.' )
680
701
  modifier_start = 2
681
702
  end
682
703
  else
683
- debug and ( p "State has not been given." )
704
+ debug and ( p 'State has not been given.' )
684
705
  event['state'] = nil
685
706
  modifier_start = 2
686
707
  end
@@ -690,24 +711,24 @@ class LightWaveRF
690
711
  # get modifiers if they exist
691
712
  time_modifier = 0
692
713
  if command_length > modifier_start
693
- debug and ( p "May have modifiers..." )
714
+ debug and ( p 'May have modifiers...' )
694
715
  when_modifiers = [ ]
695
716
  unless_modifiers = [ ]
696
717
  modifier_count = command_length - modifier_start
697
- debug and ( p "Count of modifiers is " + modifier_count.to_s )
718
+ debug and ( p 'Count of modifiers is ' + modifier_count.to_s )
698
719
  for i in modifier_start..(command_length-1)
699
720
  modifier = command[i]
700
721
  if modifier[0,1] == '@'
701
- debug and ( p "Found when modifier: " + modifier[1..-1] )
722
+ debug and ( p 'Found when modifier: ' + modifier[1..-1] )
702
723
  when_modifiers.push modifier[1..-1]
703
724
  elsif modifier[0,1] == '!'
704
- debug and ( p "Found unless modifier: " + modifier[1..-1] )
725
+ debug and ( p 'Found unless modifier: ' + modifier[1..-1] )
705
726
  unless_modifiers.push modifier[1..-1]
706
727
  elsif modifier[0,1] == '+'
707
- debug and ( p "Found positive time modifier: " + modifier[1..-1] )
728
+ debug and ( p 'Found positive time modifier: ' + modifier[1..-1] )
708
729
  time_modifier = modifier[1..-1].to_i
709
730
  elsif modifier[0,1] == '-'
710
- debug and ( p "Found negative time modifier: " + modifier[1..-1] )
731
+ debug and ( p 'Found negative time modifier: ' + modifier[1..-1] )
711
732
  time_modifier = modifier[1..-1].to_i * -1
712
733
  end
713
734
  end
@@ -718,7 +739,7 @@ class LightWaveRF
718
739
 
719
740
  # parse the date string
720
741
  event_time = /When: ([\w ]+) (\d\d:\d\d) to ([\w ]+)?(\d\d:\d\d)&nbsp;\n(.*)<br>(.*)/.match e.elements['summary'].text
721
- debug and ( p "Event times are: " + event_time.to_s )
742
+ debug and ( p 'Event times are: ' + event_time.to_s )
722
743
  start_date = event_time[1].to_s
723
744
  start_time = event_time[2].to_s
724
745
  end_date = event_time[3].to_s
@@ -729,6 +750,7 @@ class LightWaveRF
729
750
  end
730
751
 
731
752
  time_modifier += self.class.variance e.elements['title'].text
753
+ event['annotate'] = ! ( /do not annotate/.match e.elements['title'].text )
732
754
 
733
755
  debug and ( p 'Start date: ' + start_date )
734
756
  debug and ( p 'Start time: ' + start_time )
@@ -884,7 +906,7 @@ class LightWaveRF
884
906
 
885
907
  # if has modifiers, check modifiers against states
886
908
  unless event['when_modifiers'].nil?
887
- debug and ( p 'Event has when modifiers. Checking they are all met...')
909
+ debug and ( p 'Event has when modifiers. Checking they are all met...' )
888
910
 
889
911
  # determine which states apply at the time of the event
890
912
  applicable_states = [ ]
@@ -893,12 +915,12 @@ class LightWaveRF
893
915
  applicable_states.push state['name']
894
916
  end
895
917
  end
896
- debug and ( p 'Applicable states are: ' + applicable_states.to_s)
918
+ debug and ( p 'Applicable states are: ' + applicable_states.to_s )
897
919
 
898
920
  # check that each when modifier exists in appliable states
899
921
  event['when_modifiers'].each do | modifier |
900
922
  unless applicable_states.include? modifier
901
- debug and ( p 'Event when modifier not met: ' + modifier)
923
+ debug and ( p 'Event when modifier not met: ' + modifier )
902
924
  run_now = false
903
925
  break
904
926
  end
@@ -907,7 +929,7 @@ class LightWaveRF
907
929
  # check that each unless modifier does not exist in appliable states
908
930
  event['unless_modifiers'].each do | modifier |
909
931
  if applicable_states.include? modifier
910
- debug and ( p 'Event unless modifier not met: ' + modifier)
932
+ debug and ( p 'Event unless modifier not met: ' + modifier )
911
933
  run_now = false
912
934
  break
913
935
  end
@@ -927,32 +949,32 @@ class LightWaveRF
927
949
 
928
950
  triggered = [ ]
929
951
 
952
+ annotate = false
930
953
  run_list.each do | event |
931
954
  # execute based on type
932
955
  case event['type']
933
956
  when 'mood'
934
957
  p 'Executing mood. Room: ' + event['room'] + ', Mood: ' + event['state']
935
958
  result = self.mood event['room'], event['state'], debug
936
- sleep 1
937
- triggered << [ event['room'], event['device'], event['state'] ]
938
959
  when 'sequence'
939
960
  p 'Executing sequence. Sequence: ' + event['state']
940
961
  result = self.sequence event['state'], debug
941
- sleep 1
942
- triggered << [ event['room'], event['device'], event['state'] ]
943
962
  else
944
963
  p 'Executing device. Room: ' + event['room'] + ', Device: ' + event['device'] + ', State: ' + event['state']
945
964
  result = self.send event['room'], event['device'], event['state'], debug
946
- sleep 1
947
- triggered << [ event['room'], event['device'], event['state'] ]
948
965
  end
949
- self.log_timer_event event['type'], event['room'], event['device'], event['state'], result
966
+ sleep 1
967
+ triggered << [ event['room'], event['device'], event['state'] ]
968
+ if event['annotate']
969
+ annotate = true
970
+ end
971
+ self.log_timer_event event['type'], event['room'], event['device'], event['state'], result
950
972
  end
951
973
 
952
974
  # update energy log
953
975
  title = nil
954
976
  text = nil
955
- if triggered.length > 0
977
+ if annotate
956
978
  debug and ( p triggered.length.to_s + ' events so annotating energy log too...' )
957
979
  title = 'timer'
958
980
  text = triggered.map { | e | e.join ' ' }.join ', '
@@ -981,9 +1003,9 @@ class LightWaveRF
981
1003
  debug and ( puts name + ' is ' + room.to_s )
982
1004
  list += '<dt><a>' + name + '</a></dt><dd><ul>'
983
1005
  room['device'].each do | device |
984
- # link ideally relative to avoid cross domain issues
985
- link = '/room/' + room['name'].to_s + '/' + device.first.to_s
986
- list += '<li><a class="ajax off" href="' + link + '">' + room['name'].to_s + ' ' + device.first.to_s + '</a></li>'
1006
+ # link ideally relative to avoid cross domain issues
1007
+ link = '/room/' + room['name'].to_s + '/' + device.first.to_s
1008
+ list += '<li><a class="ajax off" href="' + link + '">' + room['name'].to_s + ' ' + device.first.to_s + '</a></li>'
987
1009
  end
988
1010
  list += '</ul></dd>'
989
1011
  end
@@ -1004,39 +1026,39 @@ class LightWaveRF
1004
1026
  <html>
1005
1027
  <head>
1006
1028
  <title>#{title}</title>
1007
- <style type="text/css">
1008
- body { font-family: arial, verdana, sans-serif; }
1009
- div#energy_chart { width: 800px; height: 600px; }
1010
- div#gauge_div { width: 100px; height: 100px; }
1011
- dd { display: none; }
1012
- .off, .on:hover { padding-right: 18px; background: url(lightning_delete.png) no-repeat top right; }
1013
- .on, .off:hover { padding-right: 18px; background: url(lightning_add.png) no-repeat top right; }
1014
- </style>
1015
- </head>
1029
+ <style type="text/css">
1030
+ body { font-family: arial, verdana, sans-serif; }
1031
+ div#energy_chart { width: 800px; height: 600px; }
1032
+ div#gauge_div { width: 100px; height: 100px; }
1033
+ dd { display: none; }
1034
+ .off, .on:hover { padding-right: 18px; background: url(lightning_delete.png) no-repeat top right; }
1035
+ .on, .off:hover { padding-right: 18px; background: url(lightning_add.png) no-repeat top right; }
1036
+ </style>
1037
+ </head>
1016
1038
  <body>
1017
1039
  <div class="container">
1018
1040
  <div class="row">
1019
1041
  <div class="col">
1020
- <h1>#{title}</h1>
1021
- <p class="intro">#{intro}</p>
1042
+ <h1>#{title}</h1>
1043
+ <p class="intro">#{intro}</p>
1022
1044
  <div id="energy_chart">
1023
1045
  Not seeing an energy chart here?
1024
1046
  Maybe not working in your device yet, sorry.
1025
1047
  This uses google chart api which may generate FLASH :-(
1026
1048
  Try in a web browser.
1027
1049
  </div>
1028
- <h2>Rooms and devices</h2>
1029
- <p>@todo make these links to control the devices...</p>
1030
- <p class="help">#{help}</p>
1031
- #{js}
1032
- </div>
1050
+ <h2>Rooms and devices</h2>
1051
+ <p>@todo make these links to control the devices...</p>
1052
+ <p class="help">#{help}</p>
1053
+ #{js}
1054
+ </div>
1033
1055
  <div class="col">
1034
1056
  <div class="col" id="gauge_div"></div>
1035
- </div>
1036
- </div>
1037
- </div>
1038
- <p>By <a href="http://www.clarkeology.com/blog/">Paul Clarke</a>, a work in progress.</p>
1039
- </body>
1057
+ </div>
1058
+ </div>
1059
+ </div>
1060
+ <p>By <a href="http://www.clarkeology.com/blog/">Paul Clarke</a>, a work in progress.</p>
1061
+ </body>
1040
1062
  </html>
1041
1063
  end
1042
1064
  end
@@ -1045,35 +1067,38 @@ class LightWaveRF
1045
1067
  def summarise days = 7, debug = nil
1046
1068
  days = days.to_i
1047
1069
  data = [ ]
1048
- daily = { }
1070
+ file = self.get_summary_file.gsub 'summary', 'daily'
1071
+ json = self.class.get_contents file
1072
+ daily = JSON.parse json
1049
1073
  start_date = 0
1050
1074
  d = nil
1051
1075
  File.open( self.get_log_file, 'r' ).each_line do | line |
1052
- line = JSON.parse( line )
1076
+ line = JSON.parse line
1053
1077
  if line and line['timestamp']
1054
- new_line = []
1055
- d = line['timestamp'][2..3] + line['timestamp'][5..6] + line['timestamp'][8..9] # compact version of date
1056
- ts = Time.parse( line['timestamp'] ).strftime '%s'
1057
- ts = ts.to_i
1058
- if start_date > 0
1059
- ts = ts - start_date
1060
- else
1061
- start_date = ts
1062
- end
1063
- new_line << ts
1064
- new_line << line['message']['usage'].to_i / 10
1065
- if line['message']['annotation'] and line['message']['annotation']['title'] and line['message']['annotation']['text']
1066
- new_line << line['message']['annotation']['title']
1067
- new_line << line['message']['annotation']['text']
1068
- end
1069
- data << new_line
1070
- if ( ! daily[d] or line['message']['today'] > daily[d]['today'] )
1078
+ new_line = []
1079
+ d = line['timestamp'][2..3] + line['timestamp'][5..6] + line['timestamp'][8..9] # compact version of date
1080
+ ts = Time.parse( line['timestamp'] ).strftime '%s'
1081
+ ts = ts.to_i
1082
+ if start_date > 0
1083
+ ts = ts - start_date
1084
+ else
1085
+ start_date = ts
1086
+ end
1087
+ new_line << ts
1088
+ new_line << line['message']['usage'].to_i / 10
1089
+ if line['message']['annotation'] and line['message']['annotation']['title'] and line['message']['annotation']['text']
1090
+ new_line << line['message']['annotation']['title']
1091
+ new_line << line['message']['annotation']['text']
1092
+ end
1093
+ data << new_line
1094
+ if (( ! daily[d] ) or ( line['message']['today'] > daily[d]['today'] ))
1071
1095
  daily[d] = line['message']
1072
- end
1096
+ daily[d].delete 'usage'
1097
+ end
1073
1098
  end
1074
1099
  end
1075
1100
  debug and ( puts 'got ' + data.length.to_s + ' lines in the log' )
1076
- data = data.last( 60 * 24 * days )
1101
+ data = data.last 60 * 24 * days
1077
1102
  debug and ( puts 'now got ' + data.length.to_s + ' lines in the log ( 60 * 24 * ' + days.to_s + ' = ' + ( 60 * 24 * days ).to_s + ' )' )
1078
1103
  if data and data[0]
1079
1104
  debug and ( puts 'data[0] is ' + data[0].to_s )
@@ -1085,12 +1110,13 @@ class LightWaveRF
1085
1110
  File.open( summary_file, 'w' ) do |file|
1086
1111
  file.write data.to_s
1087
1112
  end
1088
- # @todo fix the daily stats, every night it reverts to the minimum value...
1113
+ # @todo fix the daily stats, every night it reverts to the minimum value because the timezones are different
1114
+ # so 1am on the wifi-link looks midnight on the server
1089
1115
  File.open( summary_file.gsub( 'summary', 'daily' ), 'w' ) do | file |
1090
- file.write daily.to_s
1116
+ file.write daily.to_json.to_s
1091
1117
  end
1092
1118
  File.open( summary_file.gsub( 'summary', 'daily.' + d ), 'w' ) do | file |
1093
- file.write daily.select { |key| key == daily.keys.last }.to_s
1119
+ file.write daily.select { |key| key == daily.keys.last }.to_json.to_s
1094
1120
  end
1095
1121
  end
1096
1122
 
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.6.0
4
+ version: 0.6.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: 2013-07-30 00:00:00.000000000 Z
14
+ date: 2013-08-04 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: htmlentities