lightwaverf 0.2.2 → 0.3.0

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 +4 -0
  2. data/lib/lightwaverf.rb +165 -17
  3. metadata +3 -2
data/bin/lightwaverf CHANGED
@@ -3,12 +3,16 @@ require 'lightwaverf'
3
3
  case ARGV[0]
4
4
  when 'help'
5
5
  puts LightWaveRF.new.help
6
+ when 'configure'
7
+ puts LightWaveRF.new.configure
6
8
  when 'sequence'
7
9
  puts LightWaveRF.new.sequence ARGV[1], ARGV[2]
8
10
  when 'energy'
9
11
  puts LightWaveRF.new.energy ARGV[1], ARGV[2], ARGV[3]
10
12
  when 'timer'
11
13
  puts LightWaveRF.new.timer ARGV[1], ARGV[2]
14
+ when 'update'
15
+ puts LightWaveRF.new.update_config ARGV[1], ARGV[2]
12
16
  else
13
17
  LightWaveRF.new.send ARGV[0], ARGV[1], ARGV[2], ARGV[3]
14
18
  end
data/lib/lightwaverf.rb CHANGED
@@ -11,7 +11,7 @@ class LightWaveRF
11
11
  # Display usage info
12
12
  def usage
13
13
  rooms = self.class.get_rooms self.get_config
14
- 'usage: lightwaverf ' + rooms.keys.first + ' ' + rooms.values.first['device'].keys.first.to_s + ' on # where "' + rooms.keys.first + '" is a room in ' + self.get_config_file
14
+ 'usage: lightwaverf ' + rooms.values.first['name'] + ' ' + rooms.values.first['device'].keys.first.to_s + ' on # where "' + rooms.keys.first + '" is a room in ' + self.get_config_file
15
15
  end
16
16
 
17
17
  # Display help
@@ -19,11 +19,53 @@ class LightWaveRF
19
19
  help = self.usage + "\n"
20
20
  help += "your rooms, devices, and sequences, as defined in " + self.get_config_file + ":\n\n"
21
21
  help += YAML.dump self.get_config['room']
22
- room = self.get_config['room'].keys.last
23
- device = self.get_config['room'][room].last
22
+ room = self.get_config['room'].last['name']
23
+ device = self.get_config['room'].last['device'].last
24
24
  help += "\n\nso to turn on " + room + " " + device + " type \"lightwaverf " + room + " " + device + " on\"\n"
25
25
  end
26
26
 
27
+ # Configure, build config file
28
+ def configure
29
+ config = { 'host' => self.get_config['host'], 'calendar' => self.get_config['calendar'] }
30
+ puts 'What is the ip address of your wifi link? (' + self.get_config['host'] + ')'
31
+ host = STDIN.gets.chomp
32
+ if ! host.to_s.empty?
33
+ config['host'] = host
34
+ end
35
+ puts 'What is the address of your google calendar? (' + self.get_config['calendar'] + ')'
36
+ calendar = STDIN.gets.chomp
37
+ if ! calendar.to_s.empty?
38
+ config['calendar'] = calendar
39
+ end
40
+ device = 'x'
41
+ while ! device.to_s.empty?
42
+ puts 'Give me the name of a room and its devices, space separated. For example "lounge light socket tv". Just hit enter to finish.'
43
+ if device = STDIN.gets.chomp
44
+ parts = device.split ' '
45
+ if !parts[0].to_s.empty? and !parts[1].to_s.empty?
46
+ new_room = parts.shift
47
+ puts 'got ' + device + ' todo: to split this up... new room is ' + new_room
48
+ if ! config['room']
49
+ config['room'] = [ ]
50
+ end
51
+ found = false
52
+ config['room'].each do | room |
53
+ if room['name'] == new_room
54
+ room['device'] = parts
55
+ found = true
56
+ end
57
+ p 'so now room is ' + room.to_s
58
+ end
59
+ if ! found
60
+ config['room'].push 'name' => new_room, 'device' => parts
61
+ end
62
+ end
63
+ end
64
+ end
65
+ puts 'end of configure, config is now ' + config.to_s
66
+ self.put_config config
67
+ end
68
+
27
69
  # Config file setter
28
70
  def set_config_file file
29
71
  @config_file = file
@@ -39,29 +81,130 @@ class LightWaveRF
39
81
  @log_file || File.expand_path('~') + '/lightwaverf.log'
40
82
  end
41
83
 
84
+ def put_config config = { 'host' => '192.168.1.64', 'room' => [ { 'name' => 'our', 'device' => [ 'light', 'lights' ] } ] }
85
+ puts 'put_config got ' + config.to_s
86
+ puts 'so writing ' + YAML.dump( config )
87
+ File.open( self.get_config_file, 'w' ) do | handle |
88
+ handle.write YAML.dump( config )
89
+ end
90
+ end
91
+
42
92
  # Get the config file, create it if it does not exist
43
93
  def get_config
44
94
  if ! @config
45
95
  if ! File.exists? self.get_config_file
46
- File.open( self.get_config_file, 'w' ) do | handle |
47
- handle.write YAML.dump( { 'host' => '192.168.0.14', 'room' => { 'our' => [ 'light', 'lights' ] }, 'sequence' => { 'lights' => [ [ 'our', 'light', 'on' ], [ 'our', 'lights', 'on' ] ] }} )
48
- end
96
+ puts self.get_config_file + ' does not exist - copy lightwaverf-configy.yml from https://github.com/pauly/lightwaverf to your home directory or type lightwaverf configure'
97
+ self.put_config
49
98
  end
50
99
  @config = YAML.load_file self.get_config_file
51
100
  end
52
101
  @config
53
102
  end
54
103
 
104
+ # Update the LightWaveRF Gem config file from the LightWaveRF Host server
105
+ #
106
+ # Example:
107
+ # >> LightWaveRF.new.update_config 'name@example.com', '1234'
108
+ #
109
+ # Arguments:
110
+ # email: (String)
111
+ # pin: (String)
112
+ # debug: (Boolean)
113
+ #
114
+ # Credits:
115
+ # wonko - http://lightwaverfcommunity.org.uk/forums/topic/querying-configuration-information-from-the-lightwaverf-website/
116
+ def update_config email = nil, pin = nil, debug = false
117
+
118
+ # Login to LightWaveRF Host server
119
+ require 'net/http'
120
+ require 'uri'
121
+ uri = URI.parse('https://lightwaverfhost.co.uk/manager/index.php')
122
+ http = Net::HTTP.new(uri.host, uri.port)
123
+ if uri.scheme == 'https'
124
+ require 'net/https'
125
+ http.use_ssl = true
126
+ end
127
+ data = 'pin=' + pin + '&email=' + email
128
+ headers = {'Content-Type'=> 'application/x-www-form-urlencoded'}
129
+ resp, data = http.post(uri.request_uri, data, headers)
130
+
131
+ if resp and resp.body
132
+ # Extract JavaScript variables from the page
133
+ # var gDeviceNames = [""]
134
+ # var gDeviceStatus = [""]
135
+ # var gRoomNames = [""]
136
+ # var gRoomStatus = [""]
137
+ # http://rubular.com/r/UH0H4b4afF
138
+ variables = Hash.new
139
+ resp.body.scan(/var (gDeviceNames|gDeviceStatus|gRoomNames|gRoomStatus)\s*=\s*([^;]*)/).each do |variable|
140
+ variables[variable[0]] = variable[1].scan(/"([^"]*)\"/)
141
+ end
142
+ debug and (p '[Info - LightWaveRF Gem] Javascript variables ' + variables.to_s)
143
+
144
+ rooms = Array.new
145
+ # Rooms - gRoomNames is a collection of 8 values, or room names
146
+ variables['gRoomNames'].each_with_index do |(roomName), roomIndex|
147
+ # Room Status - gRoomStatus is a collection of 8 values indicating the status of the corresponding room in gRoomNames
148
+ # A: Active
149
+ # I: Inactive
150
+ if variables['gRoomStatus'] and variables['gRoomStatus'][roomIndex] and variables['gRoomStatus'][roomIndex][0] == 'A'
151
+ # Devices - gDeviceNames is a collection of 80 values, structured in blocks of ten values for each room:
152
+ # Devices 1 - 6, Mood 1 - 3, All Off
153
+ roomDevices = Array.new
154
+ deviceNamesIndexStart = roomIndex*10
155
+ variables['gDeviceNames'][(deviceNamesIndexStart)..(deviceNamesIndexStart+5)].each_with_index do |(deviceName), deviceIndex|
156
+ # Device Status - gDeviceStatus is a collection of 80 values which indicate the status/type of the corresponding device in gDeviceNames
157
+ # O: On/Off Switch
158
+ # D: Dimmer
159
+ # R: Radiator(s)
160
+ # P: Open/Close
161
+ # I: Inactive (i.e. not configured)
162
+ # m: Mood (inactive)
163
+ # M: Mood (active)
164
+ # o: All Off
165
+ deviceStatusIndex = roomIndex*10+deviceIndex
166
+ if variables['gDeviceStatus'] and variables['gDeviceStatus'][deviceStatusIndex] and variables['gDeviceStatus'][deviceStatusIndex][0] != 'I'
167
+ roomDevices << deviceName
168
+ end
169
+ end
170
+ # Create a hash of the active room and active devices and add to rooms array
171
+ if roomName and roomDevices and roomDevices.any?
172
+ rooms << {'name'=>roomName,'device'=>roomDevices}
173
+ end
174
+ end
175
+ end
176
+
177
+ # Update 'room' element in LightWaveRF Gem config file
178
+ # config['room'] is an array of hashes containing the room name and device names
179
+ # in the format { 'name' => 'Room Name', 'device' => ['Device 1', Device 2'] }
180
+ if rooms and rooms.any?
181
+ config = self.get_config
182
+ config['room'] = rooms
183
+ File.open( self.get_config_file, 'w' ) do | handle |
184
+ handle.write YAML.dump( config )
185
+ end
186
+ debug and (p '[Info - LightWaveRF Gem] Updated config with ' + rooms.size.to_s + ' room(s): ' + rooms.to_s)
187
+ else
188
+ debug and (p '[Info - LightWaveRF Gem] Unable to update config: No active rooms or devices found')
189
+ end
190
+ else
191
+ debug and (p '[Info - LightWaveRF Gem] Unable to update config: No response from Host server')
192
+ end
193
+ self.get_config
194
+ end
195
+
55
196
  # Get a cleaned up version of the rooms and devices from the config file
56
- def self.get_rooms config = { 'room' => { }}
197
+ def self.get_rooms config = { 'room' => [ ]}, debug = false
57
198
  rooms = { }
58
199
  r = 1
59
- config['room'].each do | name, devices |
60
- rooms[name] = { 'id' => 'R' + r.to_s, 'name' => name, 'device' => { }}
200
+ config['room'].each do | room |
201
+ debug and ( puts room['name'] + ' = R' + r.to_s )
202
+ rooms[room['name']] = { 'id' => 'R' + r.to_s, 'name' => room['name'], 'device' => { }}
61
203
  d = 1
62
- devices.each do | device |
204
+ room['device'].each do | device |
63
205
  # @todo possibly need to complicate this to get a device name back in here
64
- rooms[name]['device'][device] = 'D' + d.to_s
206
+ debug and ( puts ' - ' + device + ' = D' + d.to_s )
207
+ rooms[room['name']]['device'][device] = 'D' + d.to_s
65
208
  d += 1
66
209
  end
67
210
  r += 1
@@ -78,8 +221,8 @@ class LightWaveRF
78
221
  # Arguments:
79
222
  # state: (String)
80
223
  def self.get_state state = 'on'
81
- if /^\d+$/.match state.to_s
82
- state = state.to_i
224
+ if /^\d+%?$/.match state.to_s
225
+ state = state.to_i
83
226
  end
84
227
  case state
85
228
  when 'off'
@@ -107,7 +250,7 @@ class LightWaveRF
107
250
  # state: (String)
108
251
  def command room, device, state
109
252
  # @todo get the device name in here...
110
- '666,!' + room['id'] + room['device'][device] + state + '|' + room['name'] + ' ' + room['id'] + '|via @pauly'
253
+ '666,!' + room['id'] + room['device'][device] + state + '|' + room['name'] + ' ' + device + ' ' + state + '|via @pauly'
111
254
  end
112
255
 
113
256
  # Turn one of your devices on or off
@@ -121,12 +264,13 @@ class LightWaveRF
121
264
  # state: (String)
122
265
  def send room = nil, device = nil, state = 'on', debug = false
123
266
  debug and ( puts 'config is ' + self.get_config.to_s )
124
- rooms = self.class.get_rooms self.get_config
267
+ rooms = self.class.get_rooms self.get_config, debug
125
268
  state = self.class.get_state state
126
269
  if rooms[room] and device and state and rooms[room]['device'][device]
127
270
  command = self.command rooms[room], device, state
128
271
  debug and ( p 'command is ' + command )
129
- self.raw command
272
+ data = self.raw command
273
+ debug and ( p 'response is ' + data )
130
274
  else
131
275
  STDERR.puts self.usage
132
276
  end
@@ -213,7 +357,11 @@ class LightWaveRF
213
357
  debug and ( p url )
214
358
  parsed_url = URI.parse url
215
359
  http = Net::HTTP.new parsed_url.host, parsed_url.port
216
- http.use_ssl = true
360
+ begin
361
+ http.use_ssl = true
362
+ rescue
363
+ debug && ( p 'cannot use ssl' )
364
+ end
217
365
  request = Net::HTTP::Get.new parsed_url.request_uri
218
366
  response = http.request request
219
367
  doc = REXML::Document.new response.body
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lightwaverf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Clarke
9
+ - Ian Perrin
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2013-02-10 00:00:00.000000000 Z
13
+ date: 2013-02-26 00:00:00.000000000 Z
13
14
  dependencies: []
14
15
  description: Interact with lightwaverf wifi link from code or the command line. Control
15
16
  your lights, heating, sockets etc. Also set up timers using a google calendar and