wifly 0.0.5 → 1.0.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.
- data/Gemfile +4 -0
- data/README.md +3 -5
- data/lib/wifly.rb +1 -0
- data/lib/wifly/calculations.rb +3 -3
- data/lib/wifly/connection.rb +39 -15
- data/lib/wifly/control.rb +13 -8
- data/lib/wifly/version.rb +1 -1
- data/spec/calculations_spec.rb +2 -0
- data/spec/connection_spec.rb +6 -7
- data/spec/control_spec.rb +4 -4
- data/spec/integration_spec.rb +24 -0
- data/spec/spec_helper.rb +4 -0
- metadata +6 -4
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Wifly
|
2
2
|
|
3
|
-
This Ruby gem can be used to talk to a [WiFly RN-XV](http://www.rovingnetworks.com/products/RN171XV) device at a specified address. The gem has no dependencies other than the socket libraries that ship with any Ruby installation.
|
4
|
-
* Unexpected output from the WiFly could cause the client to deadlock on a socket read, or could cause corrupt data in subsequent reads. I've tried to find the variants of output that I'm concerned with in my project; however, you might find some edge cases I haven't covered. In that case, pull requests are welcome.
|
5
|
-
* The version of the firmware must be passed into the client so that the size of the response strings can be predicted.
|
3
|
+
This Ruby gem can be used to talk to a [WiFly RN-XV](http://www.rovingnetworks.com/products/RN171XV) device at a specified address. The gem has no dependencies other than the socket libraries that ship with any Ruby installation.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -19,9 +17,9 @@ Or install it yourself as:
|
|
19
17
|
$ gem install wifly
|
20
18
|
|
21
19
|
## Usage
|
22
|
-
Create a client by passing in the host
|
20
|
+
Create a client by passing in the host and port
|
23
21
|
|
24
|
-
control = Wifly::Control.new('192.168.1.45', 2000
|
22
|
+
control = Wifly::Control.new('192.168.1.45', 2000)
|
25
23
|
|
26
24
|
Read the high pins:
|
27
25
|
|
data/lib/wifly.rb
CHANGED
data/lib/wifly/calculations.rb
CHANGED
@@ -5,9 +5,9 @@ module Wifly
|
|
5
5
|
# into an array of pins that are high
|
6
6
|
#
|
7
7
|
def parse_io(hex_str)
|
8
|
-
|
9
|
-
binary_string = hex_str
|
10
|
-
binary_string.reverse.
|
8
|
+
# use sprintf to pad with 0's to 16 bits
|
9
|
+
binary_string = "%016b" % hex_str.hex.to_i
|
10
|
+
binary_string.reverse.chars.each_with_index.map do |value, pin|
|
11
11
|
pin if value == "1"
|
12
12
|
end.compact
|
13
13
|
end
|
data/lib/wifly/connection.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
module Wifly
|
2
2
|
class Connection
|
3
|
-
attr_accessor :address, :port
|
3
|
+
attr_accessor :address, :port
|
4
4
|
|
5
5
|
##
|
6
6
|
# address => the hostname or IP address of the wifly device
|
7
7
|
# port => the port for communicating with the wifly
|
8
|
-
|
9
|
-
def initialize(address, port, version)
|
8
|
+
def initialize(address, port)
|
10
9
|
self.address = address
|
11
10
|
self.port = port
|
12
|
-
self.version = version
|
13
11
|
end
|
14
12
|
|
15
13
|
##
|
@@ -19,18 +17,15 @@ module Wifly
|
|
19
17
|
# The wifly will echo back the command (with carriage return)
|
20
18
|
# along with another CRLF and the command prompt string.
|
21
19
|
# Something like "lites\r\r\n<2.32> "
|
22
|
-
# Since the string has a predictable length, we can do a blocking read.
|
23
20
|
#
|
24
|
-
def send_command(str
|
21
|
+
def send_command(str)
|
25
22
|
str += "\r"
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
rescue Errno::EPIPE # connection closed on the client end
|
30
|
-
initialize_socket
|
31
|
-
retry
|
23
|
+
write(socket, str) # the write is blocking
|
24
|
+
sleep(0.2)
|
25
|
+
read(socket).gsub(prompt,'')
|
32
26
|
end
|
33
27
|
|
28
|
+
|
34
29
|
def close
|
35
30
|
socket.close
|
36
31
|
end
|
@@ -40,14 +35,43 @@ module Wifly
|
|
40
35
|
end
|
41
36
|
|
42
37
|
private
|
38
|
+
|
39
|
+
def read(sock)
|
40
|
+
result = ''
|
41
|
+
begin
|
42
|
+
result = sock.read_nonblock(1024)
|
43
|
+
# connection lost somehow
|
44
|
+
rescue Errno::ECONNRESET, Errno::EPIPE, IOError
|
45
|
+
initialize_socket
|
46
|
+
read(socket)
|
47
|
+
# No more data on socket
|
48
|
+
rescue Errno::EAGAIN
|
49
|
+
retry
|
50
|
+
rescue EOFError => e
|
51
|
+
# ain't nothin left on socket.
|
52
|
+
end
|
53
|
+
result.strip
|
54
|
+
end
|
55
|
+
|
56
|
+
def write(sock, str)
|
57
|
+
begin
|
58
|
+
sock.write(str)
|
59
|
+
rescue Errno::EPIPE, IOError
|
60
|
+
initialize_socket
|
61
|
+
write(socket, str)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
43
65
|
def prompt
|
44
|
-
|
66
|
+
# 2.32
|
67
|
+
# 3.2.23
|
68
|
+
/<[0-9]{1,}\.[0-9]{1,}(\.[0-9]{1,})?>/
|
45
69
|
end
|
46
70
|
|
47
71
|
def initialize_socket
|
48
72
|
sock = Socket.tcp(address, port)
|
49
|
-
|
50
|
-
|
73
|
+
write(sock, COMMAND_MODE) # enter command mode
|
74
|
+
read(sock) # read off the response
|
51
75
|
sock
|
52
76
|
end
|
53
77
|
end
|
data/lib/wifly/control.rb
CHANGED
@@ -7,12 +7,11 @@ module Wifly
|
|
7
7
|
##
|
8
8
|
# address - the hostname or IP address
|
9
9
|
# port - defaults to 2000
|
10
|
-
# version - the firmware version (a string)
|
11
10
|
# connection - the object to use for talking to the wifly. Responds to "send_command."
|
12
11
|
# Defaults to Wifly::Connection.
|
13
12
|
#
|
14
|
-
def initialize(address, port,
|
15
|
-
self.connection = connection || Connection.new(address, port
|
13
|
+
def initialize(address, port, connection=nil)
|
14
|
+
self.connection = connection || Connection.new(address, port)
|
16
15
|
end
|
17
16
|
|
18
17
|
##
|
@@ -27,7 +26,7 @@ module Wifly
|
|
27
26
|
#
|
28
27
|
def set_high(pin)
|
29
28
|
hex = pin_to_hex(pin)
|
30
|
-
connection.send_command "set sys output #{hex} #{hex}"
|
29
|
+
connection.send_command "set sys output #{hex} #{hex}"
|
31
30
|
end
|
32
31
|
|
33
32
|
##
|
@@ -35,7 +34,7 @@ module Wifly
|
|
35
34
|
#
|
36
35
|
def set_low(pin)
|
37
36
|
hex = pin_to_hex(pin)
|
38
|
-
connection.send_command "set sys output 0x00 #{hex}"
|
37
|
+
connection.send_command "set sys output 0x00 #{hex}"
|
39
38
|
end
|
40
39
|
|
41
40
|
##
|
@@ -52,6 +51,13 @@ module Wifly
|
|
52
51
|
parse_io(read_io)
|
53
52
|
end
|
54
53
|
|
54
|
+
##
|
55
|
+
# Close the connection.
|
56
|
+
#
|
57
|
+
def close
|
58
|
+
connection.close
|
59
|
+
end
|
60
|
+
|
55
61
|
private
|
56
62
|
|
57
63
|
##
|
@@ -60,9 +66,8 @@ module Wifly
|
|
60
66
|
def read_io
|
61
67
|
cmd = "show io\r"
|
62
68
|
|
63
|
-
#
|
64
|
-
|
65
|
-
str = connection.send_command("show io", "8d08\r\n".length)
|
69
|
+
# result is something like 'show io\r\r\n8d08'
|
70
|
+
str = connection.send_command "show io"
|
66
71
|
|
67
72
|
# Return only the middle part, which is the io state
|
68
73
|
str.gsub(cmd,'').strip
|
data/lib/wifly/version.rb
CHANGED
data/spec/calculations_spec.rb
CHANGED
data/spec/connection_spec.rb
CHANGED
@@ -13,12 +13,12 @@ class Wifly::TestServer
|
|
13
13
|
@client.close
|
14
14
|
end
|
15
15
|
|
16
|
-
def receive_command(command
|
16
|
+
def receive_command(command)
|
17
17
|
@client = @socket.accept
|
18
18
|
|
19
19
|
@client.write(Wifly::HELLO)
|
20
20
|
@client.read((command + "\r").length)
|
21
|
-
@client.write(command + "\r\r\n<
|
21
|
+
@client.write(command + "\r\r\n<2.32> ")
|
22
22
|
@client.close
|
23
23
|
end
|
24
24
|
end
|
@@ -28,17 +28,16 @@ describe Wifly::Connection do
|
|
28
28
|
@server = Wifly::TestServer.new(2000)
|
29
29
|
end
|
30
30
|
it 'should set stuff on initialize' do
|
31
|
-
connection = Wifly::Connection.new('localhost', 2000
|
31
|
+
connection = Wifly::Connection.new('localhost', 2000)
|
32
32
|
connection.address.should eq('localhost')
|
33
33
|
connection.port.should eq(2000)
|
34
|
-
connection.version.should eq('2.3.13')
|
35
34
|
end
|
36
35
|
|
37
36
|
it 'should enter command mode' do
|
38
37
|
t = Thread.new do
|
39
38
|
@server.simple_connect
|
40
39
|
end
|
41
|
-
connection = Wifly::Connection.new('localhost', 2000
|
40
|
+
connection = Wifly::Connection.new('localhost', 2000)
|
42
41
|
connection.socket
|
43
42
|
t.join
|
44
43
|
@server.input.should eq(Wifly::COMMAND_MODE)
|
@@ -47,9 +46,9 @@ describe Wifly::Connection do
|
|
47
46
|
|
48
47
|
it 'should send commands correctly' do
|
49
48
|
t = Thread.new do
|
50
|
-
@server.receive_command("lites"
|
49
|
+
@server.receive_command("lites")
|
51
50
|
end
|
52
|
-
connection = Wifly::Connection.new('localhost', 2000
|
51
|
+
connection = Wifly::Connection.new('localhost', 2000)
|
53
52
|
|
54
53
|
result = connection.send_command("lites")
|
55
54
|
t.join
|
data/spec/control_spec.rb
CHANGED
@@ -2,9 +2,9 @@ require 'spec_helper'
|
|
2
2
|
describe Wifly::Control do
|
3
3
|
it 'should set high and low' do
|
4
4
|
connection = double('connection')
|
5
|
-
connection.should_receive(:send_command).with("set sys output 0x20 0x20"
|
6
|
-
connection.should_receive(:send_command).with("set sys output 0x00 0x20"
|
7
|
-
control = Wifly::Control.new('localhost', 2000,
|
5
|
+
connection.should_receive(:send_command).with("set sys output 0x20 0x20")
|
6
|
+
connection.should_receive(:send_command).with("set sys output 0x00 0x20")
|
7
|
+
control = Wifly::Control.new('localhost', 2000, connection)
|
8
8
|
control.set_high(5)
|
9
9
|
control.set_low(5)
|
10
10
|
end
|
@@ -12,7 +12,7 @@ describe Wifly::Control do
|
|
12
12
|
it 'should get high pins' do
|
13
13
|
connection = double('connection')
|
14
14
|
connection.should_receive(:send_command).exactly(2).times.and_return("show io\r\r\n8d08\r\n")
|
15
|
-
control = Wifly::Control.new('localhost', 2000,
|
15
|
+
control = Wifly::Control.new('localhost', 2000, connection)
|
16
16
|
|
17
17
|
control.read_pin(8).should eq(1)
|
18
18
|
control.read_pin(7).should eq(0)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
#
|
3
|
+
# This test excercizes pretty much most of the control methods
|
4
|
+
# on an actual WiFly. Supplying the WIFLY_IP as an environment
|
5
|
+
# variable activates this test.
|
6
|
+
# That means you should have the WiFly connected to a network
|
7
|
+
# accessible by the computer running this test.
|
8
|
+
#
|
9
|
+
if WIFLY_IP
|
10
|
+
describe Wifly do
|
11
|
+
it 'should really work' do
|
12
|
+
2.times do
|
13
|
+
control=Wifly::Control.new(WIFLY_IP, 2000)
|
14
|
+
5.times do |n|
|
15
|
+
control.set_high(7)
|
16
|
+
control.read_pin(7).should eq(1)
|
17
|
+
control.set_low(7)
|
18
|
+
control.read_pin(7).should eq(0)
|
19
|
+
end
|
20
|
+
control.close
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
#
|
6
6
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
7
|
require 'wifly'
|
8
|
+
require 'pry'
|
9
|
+
|
10
|
+
# If you set WIFLY_IP, a special "real" test will run against your WiFly.
|
11
|
+
WIFLY_IP = ENV['WIFLY_IP'] || nil
|
8
12
|
|
9
13
|
RSpec.configure do |config|
|
10
14
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wifly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-02-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- spec/calculations_spec.rb
|
97
97
|
- spec/connection_spec.rb
|
98
98
|
- spec/control_spec.rb
|
99
|
+
- spec/integration_spec.rb
|
99
100
|
- spec/spec_helper.rb
|
100
101
|
- wifly.gemspec
|
101
102
|
homepage: ''
|
@@ -113,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
114
|
version: '0'
|
114
115
|
segments:
|
115
116
|
- 0
|
116
|
-
hash:
|
117
|
+
hash: 17962621
|
117
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
119
|
none: false
|
119
120
|
requirements:
|
@@ -122,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
123
|
version: '0'
|
123
124
|
segments:
|
124
125
|
- 0
|
125
|
-
hash:
|
126
|
+
hash: 17962621
|
126
127
|
requirements: []
|
127
128
|
rubyforge_project:
|
128
129
|
rubygems_version: 1.8.25
|
@@ -133,4 +134,5 @@ test_files:
|
|
133
134
|
- spec/calculations_spec.rb
|
134
135
|
- spec/connection_spec.rb
|
135
136
|
- spec/control_spec.rb
|
137
|
+
- spec/integration_spec.rb
|
136
138
|
- spec/spec_helper.rb
|