ruby-xbee 1.1.0 → 1.2.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.
- checksums.yaml +5 -13
- data/README.rdoc +5 -4
- data/bin/apilisten.rb +2 -2
- data/bin/ota_upgrade.rb +213 -0
- data/lib/apimode/frame/explicit_addressing_command.rb +46 -1
- data/lib/apimode/frame/explicit_rx_indicator.rb +17 -0
- data/lib/apimode/frame/frame.rb +63 -23
- data/lib/apimode/frame/modem_status.rb +1 -1
- data/lib/apimode/frame/remote_command_response.rb +1 -1
- data/lib/apimode/xbee_api.rb +63 -23
- data/lib/module_config.rb +17 -0
- data/lib/ruby_xbee.rb +7 -6
- data/test/ruby_xbee_api_frame_eac_test.rb +132 -0
- data/test/ruby_xbee_api_frame_erxi_test.rb +54 -0
- data/test/ruby_xbee_api_frame_test.rb +530 -0
- data/test/ruby_xbee_apimode_test.rb +52 -0
- data/test/ruby_xbee_test.rb +3 -3
- data/test/test_helper.rb +11 -8
- metadata +124 -11
@@ -0,0 +1,530 @@
|
|
1
|
+
$: << File.dirname(__FILE__)
|
2
|
+
require 'test_helper'
|
3
|
+
require 'socket'
|
4
|
+
##
|
5
|
+
# The main goal of these testcases is to test basic API frame reading from
|
6
|
+
# socket, ensuring the integrity of frames by checksum calculation and
|
7
|
+
# ability to construct frames. Some of the frame examples for testing are
|
8
|
+
# based on the XBee reference manuals but feel free to run with your
|
9
|
+
# imagination.
|
10
|
+
#
|
11
|
+
# More detailed frame testing are kept separate from this file. Only
|
12
|
+
# basic frame stuff here.
|
13
|
+
# ==================================================
|
14
|
+
# Currently known frames, o = covered by test frames
|
15
|
+
# ==================================================
|
16
|
+
# o - 0x08 - AT Command
|
17
|
+
# o - 0x09 - AT Command - Queue Parameter Value
|
18
|
+
# o - 0x10 - ZigBee Transmit Request
|
19
|
+
# o - 0x11 - Explicit Addressing ZigBee Command Frame
|
20
|
+
# o - 0x17 - Remote Command Request
|
21
|
+
# o - 0x21 - Create Source Route
|
22
|
+
# o - 0x88 - AT Command Response
|
23
|
+
# o - 0x8a - Modem Status
|
24
|
+
# o - 0x8b - ZigBee Transmit Status
|
25
|
+
# o - 0x90 - ZigBee Receive Packet (AO=0)
|
26
|
+
# o - 0x91 - ZigBee Explicit Rx Indicator (AO=1)
|
27
|
+
# o - 0x92 - ZigBee IO Data Sample Rx Indicator
|
28
|
+
# x - 0x94 - XBee Sensor Read Indicator (AO=0)
|
29
|
+
# x - 0x95 - Node Identification Indicator (AO=0)
|
30
|
+
# o - 0x97 - Remote Command Response
|
31
|
+
# x - 0xA0 - Over-the-Air Firmware Update Status
|
32
|
+
# x - 0xA1 - Route Record Indicator
|
33
|
+
# x - 0xA3 - Many-to-One Route Request Indicator
|
34
|
+
class RubyXbeeApiFrameTest < MiniTest::Test
|
35
|
+
def setup
|
36
|
+
if ENV['OS'] != "Windows_NT"
|
37
|
+
@unix_socket = '/tmp/ruby-xbee-test.sock'
|
38
|
+
File.delete( @unix_socket ) if FileTest.exists?( @unix_socket )
|
39
|
+
@server = UNIXServer.new(@unix_socket)
|
40
|
+
@s = UNIXSocket.open(@unix_socket)
|
41
|
+
else
|
42
|
+
@server = TCPServer.new(2000)
|
43
|
+
@s = TCPSocket.new('localhost', 2000)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# We test sending the most simplistic packet possible
|
49
|
+
# (unknown frame type)
|
50
|
+
# +----------------------------+-----------------------------+------+
|
51
|
+
# |___________Header___________|____________Frame____________| |
|
52
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | A T | (Par) | CSum |
|
53
|
+
# +--------+---------+---------+------+----+---------+-------+------+
|
54
|
+
# | 0x7e | 0x00 | 0x00 | 0x00 | | | | | 0xff |
|
55
|
+
# +--------+---------+---------+------+----+-----------------+------+
|
56
|
+
def test_frame_00
|
57
|
+
Thread.fork(@server.accept) do |client|
|
58
|
+
f = [ 0x7e, 0x00, 0x01, 0x00, 0xff]
|
59
|
+
client.write(f.pack("c*"))
|
60
|
+
client.close
|
61
|
+
end
|
62
|
+
|
63
|
+
xbee_frame = XBee::Frame.new(@s)
|
64
|
+
assert_equal(0x00, xbee_frame.api_identifier)
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# We test sending the most simplistic packet possible with incorrect checksum
|
69
|
+
# (unknown frame type)
|
70
|
+
# +----------------------------+-----------------------------+------+
|
71
|
+
# |___________Header___________|____________Frame____________| |
|
72
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | A T | (Par) | CSum |
|
73
|
+
# +--------+---------+---------+------+----+---------+-------+------+
|
74
|
+
# | 0x7e | 0x00 | 0x00 | 0x00 | | | | | 0x80 |
|
75
|
+
# +--------+---------+---------+------+----+-----------------+------+
|
76
|
+
def test_bad_checksum
|
77
|
+
Thread.fork(@server.accept) do |client|
|
78
|
+
f = [ 0x7e, 0x00, 0x01, 0x00, 0x80]
|
79
|
+
client.write(f.pack("c*"))
|
80
|
+
client.close
|
81
|
+
end
|
82
|
+
|
83
|
+
runtimeerror_raised = assert_raises(RuntimeError) {
|
84
|
+
xbee_frame = XBee::Frame.new(@s)
|
85
|
+
}
|
86
|
+
assert_equal("Bad checksum - data discarded", runtimeerror_raised.message)
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# AT Command (0x08) that allows joining by setting NJ to 0xFF; AT = NJ
|
91
|
+
# +----------------------------+-----------------------------+------+
|
92
|
+
# |___________Header___________|____________Frame____________| |
|
93
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | A T | (Par) | CSum |
|
94
|
+
# +--------+---------+---------+------+----+---------+-------+------+
|
95
|
+
# | 0x7e | 0x00 | 0x05 | 0x08 |0x01|0x4e|0x4a| 0xff | 0x5f |
|
96
|
+
# +--------+---------+---------+------+----+-----------------+------+
|
97
|
+
def test_allow_join
|
98
|
+
Thread.fork(@server.accept) do |client|
|
99
|
+
f = [ 0x7e, 0x00, 0x05, 0x08, 0x01, 0x4e, 0x4a, 0xff, 0x5f ]
|
100
|
+
client.write(f.pack("c*"))
|
101
|
+
client.close
|
102
|
+
end
|
103
|
+
|
104
|
+
xbee_frame = XBee::Frame.new(@s)
|
105
|
+
assert_equal("\x01NJ\xFF".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
106
|
+
assert_equal(0x08, xbee_frame.api_identifier)
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# AT Command (0x08) for Network Discovery; AT = ND
|
111
|
+
# +----------------------------+-----------------------------+------+
|
112
|
+
# |___________Header___________|____________Frame____________| |
|
113
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | A T | (Par) | CSum |
|
114
|
+
# +--------+---------+---------+------+----+---------+-------+------+
|
115
|
+
# | 0x7e | 0x00 | 0x04 | 0x08 |0x01|0x4e|0x44| | 0x64 |
|
116
|
+
# +--------+---------+---------+------+----+-----------------+------+
|
117
|
+
def test_network_discovery
|
118
|
+
Thread.fork(@server.accept) do |client|
|
119
|
+
f = [ 0x7e, 0x00, 0x04, 0x08, 0x01, 0x4e, 0x44, 0x64 ]
|
120
|
+
client.write(f.pack("c*"))
|
121
|
+
client.close
|
122
|
+
end
|
123
|
+
|
124
|
+
xbee_frame = XBee::Frame.new(@s)
|
125
|
+
assert_equal("\x01ND".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
126
|
+
assert_equal(0x08, xbee_frame.api_identifier)
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# AT Command - Queue Parameter Value (0x09); AT = BD
|
131
|
+
# +----------------------------+-----------------------------+------+
|
132
|
+
# |___________Header___________|____________Frame____________| |
|
133
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | A T | (Par) | CSum |
|
134
|
+
# +--------+---------+---------+------+----+---------+-------+------+
|
135
|
+
# | 0x7e | 0x00 | 0x05 | 0x09 |0x01|0x42|0x44| 0x07 | 0x68 |
|
136
|
+
# +--------+---------+---------+------+----+-----------------+------+
|
137
|
+
def test_at_command_queue_parameter_value
|
138
|
+
Thread.fork(@server.accept) do |client|
|
139
|
+
f = [ 0x7e, 0x00, 0x05, 0x09, 0x01, 0x42, 0x44, 0x07, 0x68 ]
|
140
|
+
client.write(f.pack("c*"))
|
141
|
+
client.close
|
142
|
+
end
|
143
|
+
|
144
|
+
xbee_frame = XBee::Frame.new(@s)
|
145
|
+
assert_equal("\x01BD\x07".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
146
|
+
assert_equal(0x09, xbee_frame.api_identifier)
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# ZigBee Transmit Request (0x10)
|
151
|
+
# A Transmit Request API frame causes the module to send data as an RF packet
|
152
|
+
# to the specified destination.
|
153
|
+
# +----------------------------+-----------------------------------------------------------------------------------+------+
|
154
|
+
# |___________Header___________|_______________________________________Frame_______________________________________| |
|
155
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitDestination | Dest16 | BCRadius | Options | RF Data | CSum |
|
156
|
+
# +--------+---------+---------+------+----+--------------------+--------+----------+---------+--------------------+------+
|
157
|
+
# | 0x7e | 0x00 | 0x16 | 0x10 |0x01| 0x0013a200400a0127 | 0xfffe | 0x00 | 0x00 | 0x5478446174613041 | 0x13 |
|
158
|
+
# +--------+---------+---------+------+----+--------------------+--------+----------+---------+--------------------+------+
|
159
|
+
def test_zigbee_transmit_request
|
160
|
+
Thread.fork(@server.accept) do |client|
|
161
|
+
f = [ 0x7e, 0x00, 0x16, 0x10, 0x01, 0x00, 0x13, 0xa2, 0x00, 0x40, 0x0a, 0x01, 0x27, 0xff, 0xfe, 0x00, 0x00, 0x54, 0x78,
|
162
|
+
0x44, 0x61, 0x74, 0x61, 0x30, 0x41, 0x13 ]
|
163
|
+
client.write(f.pack("c*"))
|
164
|
+
client.close
|
165
|
+
end
|
166
|
+
|
167
|
+
xbee_frame = XBee::Frame.new(@s)
|
168
|
+
assert_equal("\x01\x00\x13\xa2\x00\x40\x0a\x01\x27\xff\xfe\x00\x00\x54\x78\x44\x61\x74\x61\x30\x41".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
169
|
+
assert_equal(0x10, xbee_frame.api_identifier)
|
170
|
+
end
|
171
|
+
|
172
|
+
##
|
173
|
+
# Explicit Addressing ZigBee Command Frame (0x11)
|
174
|
+
# This allows ZigBee application layer fields (endpoint and cluster ID) to be specified for a data transmission.
|
175
|
+
# +----------------------------+--------------------------------------------------------------------------------------------------------------------------------+------+
|
176
|
+
# |___________Header___________|______________________________________________________________Frame_____________________________________________________________| |
|
177
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitDestination | Dest16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | BCRadius | Options | Data Payload | CSum |
|
178
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------+-----------+----------+---------+----------------+------+
|
179
|
+
# | 0x7e | 0x00 | 0x1A | 0x11 |0x01| 0x0000000000000000 | 0xfffe | 0xA0 | 0xA1 | 0x1554 | 0xC105 | 0x00 | 0x00 | 0x547844617461 | 0x3A |
|
180
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------------------+----------+---------+----------------+------+
|
181
|
+
def test_explicit_addressing_zigbee
|
182
|
+
Thread.fork(@server.accept) do |client|
|
183
|
+
f = [ 0x7e, 0x00, 0x1a, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
184
|
+
0x00, 0x00, 0xff, 0xfe, 0xa0, 0xa1, 0x15, 0x54, 0xc1, 0x05, 0x00,
|
185
|
+
0x00, 0x54, 0x78, 0x44, 0x61, 0x74, 0x61, 0x3a ]
|
186
|
+
client.write(f.pack("c*"))
|
187
|
+
client.close
|
188
|
+
end
|
189
|
+
|
190
|
+
xbee_frame = XBee::Frame.new(@s)
|
191
|
+
assert_equal("\x01\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\xa0\xa1\x15\x54\xc1\x05\x00\x00\x54\x78\x44\x61\x74\x61".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
192
|
+
assert_equal(0x11, xbee_frame.api_identifier)
|
193
|
+
end
|
194
|
+
|
195
|
+
##
|
196
|
+
# Remote Command Request (0x17)
|
197
|
+
# Send remote command to the coordinator and set AD1/DIO1 as a digital input
|
198
|
+
# applying the changes to force IO update; AT = D1
|
199
|
+
# +----------------------------+-----------------------------------------------------------------------+------+
|
200
|
+
# |___________Header___________|_________________________________Frame_________________________________| |
|
201
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | CoordinatorAddress | Dest16 | RemComOpt | A T | (Par) | CSum |
|
202
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+---------+-------+------+
|
203
|
+
# | 0x7e | 0x00 | 0x10 | 0x17 |0x01| 0x0123456789abcdef | 0xfcfe | 0x02 |0x44|0x31| 0x03 | 0xb3 |
|
204
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+----+----+-------+------+
|
205
|
+
def test_remote_command_request
|
206
|
+
Thread.fork(@server.accept) do |client|
|
207
|
+
f = [ 0x7e, 0x00, 0x10, 0x17, 0x01, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfc, 0xfe, 0x02, 0x44, 0x31, 0x03, 0xb3 ]
|
208
|
+
client.write(f.pack("c*"))
|
209
|
+
client.close
|
210
|
+
end
|
211
|
+
|
212
|
+
xbee_frame = XBee::Frame.new(@s)
|
213
|
+
assert_equal("\x01\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFC\xFE\x02D1\x03".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
214
|
+
assert_equal(0x17, xbee_frame.api_identifier)
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Crete Source Route (0x21)
|
219
|
+
# This frame creates the source route in the module. A source route specifies
|
220
|
+
# the complete route a packet should traverse to get from source to destination.
|
221
|
+
# +----------------------------+----------------------------------------------------------------------------------------------+------+
|
222
|
+
# |___________Header___________|____________________________________________Frame_____________________________________________| |
|
223
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | CoordinatorAddress | Dest16 | RouteOpt | NumberOfAddr | Addr 1 | Addr 2 | Addr 3 | CSum |
|
224
|
+
# +--------+---------+---------+------+----+--------------------+--------+----------+--------------+--------+--------+--------+------+
|
225
|
+
# | 0x7e | 0x00 | 0x14 | 0x21 |0x00| 0x0013a20040401122 | 0x3344 | 0x00 | 0x03 | 0xeeff | 0xccdd | 0xaabb | 0x01 |
|
226
|
+
# +--------+---------+---------+------+----+--------------------+--------+-------------------------+--------+--------+--------+------+
|
227
|
+
def test_create_source_route
|
228
|
+
Thread.fork(@server.accept) do |client|
|
229
|
+
f = [ 0x7e, 0x00, 0x14, 0x21, 0x00, 0x00, 0x13, 0xa2, 0x00, 0x40, 0x40, 0x11, 0x22, 0x33, 0x44, 0x00, 0x03, 0xee, 0xff, 0xcc, 0xdd, 0xaa, 0xbb, 01 ]
|
230
|
+
client.write(f.pack("c*"))
|
231
|
+
client.close
|
232
|
+
end
|
233
|
+
|
234
|
+
xbee_frame = XBee::Frame.new(@s)
|
235
|
+
assert_equal("\x00\x00\x13\xa2\x00\x40\x40\x11\x22\x33\x44\x00\x03\xee\xff\xcc\xdd\xaa\xbb".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
236
|
+
assert_equal(0x21, xbee_frame.api_identifier)
|
237
|
+
end
|
238
|
+
|
239
|
+
##
|
240
|
+
# AT Command Response (0x88) are sent in a response to an AT Command. Some
|
241
|
+
# commands trigger multiple responses, like the ATND (Node Discover) command.
|
242
|
+
# AT = BD
|
243
|
+
# +----------------------------+---------------------------------+------+
|
244
|
+
# |___________Header___________|______________Frame______________| |
|
245
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | A T |Status|Data| CSum |
|
246
|
+
# +--------+---------+---------+------+----+---------+------+----+------+
|
247
|
+
# | 0x7e | 0x00 | 0x05 | 0x88 |0x01|0x42|0x44| 0x00 | | 0xf0 |
|
248
|
+
# +--------+---------+---------+------+----+----------------+----+------+
|
249
|
+
def test_command_response
|
250
|
+
Thread.fork(@server.accept) do |client|
|
251
|
+
f = [ 0x7e, 0x00, 0x05, 0x88, 0x01, 0x42, 0x44, 0x00, 0xf0 ]
|
252
|
+
client.write(f.pack("c*"))
|
253
|
+
client.close
|
254
|
+
end
|
255
|
+
|
256
|
+
xbee_frame = XBee::Frame.new(@s)
|
257
|
+
assert_equal("\x01\x42\x44\x00".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
258
|
+
assert_equal(0x88, xbee_frame.api_identifier)
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Modem Status (0x8A) These frames are sent on specific conditions
|
263
|
+
# This frame is sent by end-device upon joining a network
|
264
|
+
# +----------------------------+---------------+------+
|
265
|
+
# |___________Header___________|_____Frame_____| |
|
266
|
+
# | SDelim | DlenMSB | DlenLSB | Type | Status | CSum |
|
267
|
+
# +--------+---------+---------+------+--------+------+
|
268
|
+
# | 0x7e | 0x00 | 0x02 | 0x8a | 0x02 | 0x73 |
|
269
|
+
# +--------+---------+---------+------+--------+------+
|
270
|
+
def test_modem_status_joined_network
|
271
|
+
Thread.fork(@server.accept) do |client|
|
272
|
+
f = [ 0x7e, 0x00, 0x02, 0x8a, 0x02, 0x73 ]
|
273
|
+
client.write(f.pack("c*"))
|
274
|
+
client.close
|
275
|
+
end
|
276
|
+
|
277
|
+
xbee_frame = XBee::Frame.new(@s)
|
278
|
+
assert_equal("\x02", xbee_frame.cmd_data)
|
279
|
+
assert_equal(2, xbee_frame.status[0])
|
280
|
+
assert_equal(:Associated, xbee_frame.status[1])
|
281
|
+
assert_equal(0x8a, xbee_frame.api_identifier)
|
282
|
+
end
|
283
|
+
|
284
|
+
##
|
285
|
+
# Modem Status (0x8A) These frames are sent on specific conditions
|
286
|
+
# This frame is sent by coordinator upon forming a network
|
287
|
+
# (currently this is unimplemented and raises a RuntimeError)
|
288
|
+
# BORKEN
|
289
|
+
# +----------------------------+---------------+------+
|
290
|
+
# |___________Header___________|_____Frame_____| |
|
291
|
+
# | SDelim | DlenMSB | DlenLSB | Type | Status | CSum |
|
292
|
+
# +--------+---------+---------+------+--------+------+
|
293
|
+
# | 0x7e | 0x00 | 0x02 | 0x8a | 0x06 | 0x6f |
|
294
|
+
# +--------+---------+---------+------+--------+------+
|
295
|
+
def test_modem_status_coordinator_started_invalid_status
|
296
|
+
Thread.fork(@server.accept) do |client|
|
297
|
+
f = [ 0x7e, 0x00, 0x02, 0x8a, 0x06, 0x6f ]
|
298
|
+
client.write(f.pack("c*"))
|
299
|
+
client.close
|
300
|
+
end
|
301
|
+
|
302
|
+
runtimeerror_raised = assert_raises(RuntimeError) {
|
303
|
+
xbee_frame = XBee::Frame.new(@s);
|
304
|
+
assert_equal(0x8a, xbee_frame.api_identifier)
|
305
|
+
}
|
306
|
+
|
307
|
+
assert_equal("ModemStatus frame appears to include an invalid status value: 0x06", runtimeerror_raised.message)
|
308
|
+
end
|
309
|
+
|
310
|
+
##
|
311
|
+
# ZigBee Transmit Status (0x8B) When a TX Request is completed, the module
|
312
|
+
# sends a TX Status message to indicate successful transfer or failure.
|
313
|
+
# +----------------------------+----------------------------------------------------------------------------+------+
|
314
|
+
# |___________Header___________|___________________________________Frame____________________________________| |
|
315
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | Dest16 | TransmitRetryCount | DeliveryStatus | DiscoveryStatus | CSum |
|
316
|
+
# +--------+---------+---------+------+----+--------+--------------------+----------------+-----------------+------+
|
317
|
+
# | 0x7e | 0x00 | 0x07 | 0x8b |0x01| 0x7c84 | 0x00 | 0x00 | 0x01 | 0x72 |
|
318
|
+
# +--------+---------+---------+------+----+--------+--------------------+----------------+-----------------+------+
|
319
|
+
def test_zigbee_transmit_status_ok
|
320
|
+
Thread.fork(@server.accept) do |client|
|
321
|
+
f = [ 0x7e, 0x00, 0x07, 0x8b, 0x01, 0x7c, 0x84, 0x00, 0x00, 0x01, 0x72 ]
|
322
|
+
client.write(f.pack("c*"))
|
323
|
+
client.close
|
324
|
+
end
|
325
|
+
|
326
|
+
xbee_frame = XBee::Frame.new(@s)
|
327
|
+
assert_equal(0x8b, xbee_frame.api_identifier)
|
328
|
+
end
|
329
|
+
|
330
|
+
##
|
331
|
+
# ZigBee Transmit Status (0x8B) with escaped payload
|
332
|
+
# +----------------------------+----------------------------------------------------------------------------+------+
|
333
|
+
# |___________Header___________|___________________________________Frame____________________________________| |
|
334
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | Dest16 | TransmitRetryCount | DeliveryStatus | DiscoveryStatus | CSum |
|
335
|
+
# +--------+---------+---------+------+----+--------+--------------------+----------------+-----------------+------+
|
336
|
+
# | 0x7e | 0x00 | 0x07 | 0x8b |0x01| 0x7d84 | 0x00 | 0x00 | 0x01 | 0x71 |
|
337
|
+
# +--------+---------+---------+------+----+--------+--------------------+----------------+-----------------+------+
|
338
|
+
def test_zigbee_transmit_status_escaped_dataload
|
339
|
+
Thread.fork(@server.accept) do |client|
|
340
|
+
# 7d needs to be escaped 7d => 7d 5d
|
341
|
+
f = [ 0x7e, 0x00, 0x07, 0x8b, 0x01, 0x7d, 0x5d, 0x84, 0x00, 0x00, 0x01, 0x71 ]
|
342
|
+
client.write(f.pack("c*"))
|
343
|
+
client.close
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
xbee_frame = XBee::Frame.new(@s, :API2)
|
348
|
+
assert_equal("\x01\x7d\x84\x00\x00\x01".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
349
|
+
assert_equal(0x8b, xbee_frame.api_identifier)
|
350
|
+
end
|
351
|
+
|
352
|
+
##
|
353
|
+
# ZigBee Receive Packet - (0x90) When the module receives an RF packet,
|
354
|
+
# it is sent out the UART with this message.
|
355
|
+
# +----------------------------+---------------------------------------------------------------+------+
|
356
|
+
# |___________Header___________|_____________________________Frame_____________________________| |
|
357
|
+
# | SDelim | DlenMSB | DlenLSB | Type | 64-bit SourceAddr | Src16 | Options | ReceivedData | CSum |
|
358
|
+
# +--------+---------+---------+------+--------------------+--------+---------+----------------+------+
|
359
|
+
# | 0x7e | 0x00 | 0x12 | 0x90 | 0x0013a20040522baa | 0x7d84 | 0x01 | 0x527844617461 | 0x0D |
|
360
|
+
# +--------+---------+---------+------+--------------------+--------+--------------------------+------+
|
361
|
+
def test_zigbee_receive_packet
|
362
|
+
# 13 is escaped to 7d 33
|
363
|
+
# 7d is escaped to 7d 5d
|
364
|
+
Thread.fork(@server.accept) do |client|
|
365
|
+
f = [ 0x7e, 0x00, 0x12, 0x90, 0x00, 0x7d, 0x33, 0xa2, 0x00, 0x40, 0x52, 0x2b,
|
366
|
+
0xaa, 0x7d, 0x5d, 0x84, 0x01, 0x52, 0x78, 0x44, 0x61, 0x74, 0x61, 0x0D]
|
367
|
+
client.write(f.pack("c*"))
|
368
|
+
client.close
|
369
|
+
end
|
370
|
+
|
371
|
+
xbee_frame = XBee::Frame.new(@s, :API2)
|
372
|
+
assert_equal("\x00\x13\xa2\x00\x40\x52\x2b\xaa\x7d\x84\x01\x52\x78\x44\x61\x74\x61".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
373
|
+
assert_equal(0x90, xbee_frame.api_identifier)
|
374
|
+
end
|
375
|
+
|
376
|
+
##
|
377
|
+
# ZigBee Receive Packet - (0x90) When the module receives an RF packet,
|
378
|
+
# it is sent out the UART with this message.
|
379
|
+
# We send this in API Mode 1 - API Operation (AP parameter = 1)
|
380
|
+
# +----------------------------+---------------------------------------------------------------+------+
|
381
|
+
# |___________Header___________|_____________________________Frame_____________________________| |
|
382
|
+
# | SDelim | DlenMSB | DlenLSB | Type | 64-bit SourceAddr | Src16 | Options | ReceivedData | CSum |
|
383
|
+
# +--------+---------+---------+------+--------------------+--------+---------+----------------+------+
|
384
|
+
# | 0x7e | 0x00 | 0x12 | 0x90 | 0x0013a20040522baa | 0x7d84 | 0x01 | 0x527844617461 | 0x0D |
|
385
|
+
# +--------+---------+---------+------+--------------------+--------+--------------------------+------+
|
386
|
+
def test_zigbee_receive_packet_api1
|
387
|
+
Thread.fork(@server.accept) do |client|
|
388
|
+
f = [ 0x7E, 0x00, 0x12, 0x90, 0x00, 0x13, 0xA2, 0x00, 0x40, 0x52, 0x2B, 0xAA,
|
389
|
+
0x7D, 0x84, 0x01, 0x52, 0x78, 0x44, 0x61, 0x74, 0x61, 0x0D ]
|
390
|
+
client.write(f.pack("c*"))
|
391
|
+
client.close
|
392
|
+
end
|
393
|
+
|
394
|
+
xbee_frame = XBee::Frame.new(@s, :API1)
|
395
|
+
assert_equal("\x00\x13\xa2\x00\x40\x52\x2b\xaa\x7d\x84\x01\x52\x78\x44\x61\x74\x61".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
396
|
+
assert_equal(0x90, xbee_frame.api_identifier)
|
397
|
+
end
|
398
|
+
|
399
|
+
##
|
400
|
+
# ZigBee Explicit Rx Indicator - (0x91) When the modem receives a ZigBee RF packet
|
401
|
+
# it is sent out the UART using this message type (when AO=1).
|
402
|
+
# +----------------------------+----------------------------------------------------------------------------------------------------------------+------+
|
403
|
+
# |___________Header___________|_____________________________________________________Frame______________________________________________________| |
|
404
|
+
# | SDelim | DlenMSB | DlenLSB | Type | 64-bit Source Addr | Src.16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | Options | Data Payload | CSum |
|
405
|
+
# +--------+---------+---------+------+--------------------+--------+-----------+------------+-----------+-----------+---------+----------------+------+
|
406
|
+
# | 0x7E | 0x00 | 0x13 | 0x91 | 0x1234567890ABCDEF | 0x1234 | 0xE8 | 0xE8 | 0x0011 | 0xC105 | 0x01 | 0x43 | 0x32 |
|
407
|
+
# +--------+---------+---------+------+--------------------+--------+-----------+------------+-----------+-----------+---------+----------------+------+
|
408
|
+
# This frame is sent in response to type ZigBee Explicit Addressing Command (Frame Type: 0x11). The cluster 0x0011 is used by Digi as Virtual serial line
|
409
|
+
# And use for example in OTA firmware upgrade
|
410
|
+
def test_zigbee_explicit_rx_indicator
|
411
|
+
Thread.fork(@server.accept) do |client|
|
412
|
+
f = [ 0x7E, 0x00, 0x13, 0x91, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
|
413
|
+
0x12, 0x34, 0xE8, 0xE8, 0x00, 0x11, 0xC1, 0x05, 0x01, 0x43, 0x32 ]
|
414
|
+
client.write(f.pack("c*"))
|
415
|
+
client.close
|
416
|
+
end
|
417
|
+
|
418
|
+
|
419
|
+
xbee_frame = XBee::Frame.new(@s)
|
420
|
+
assert_equal("\x12\x34\x56\x78\x90\xAB\xCD\xEF\x12\x34\xE8\xE8\x00\x11\xC1\x05\x01\x43".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
421
|
+
assert_equal(0x91, xbee_frame.api_identifier)
|
422
|
+
end
|
423
|
+
|
424
|
+
##
|
425
|
+
# ZigBee IO Data Sample Rx Indicator (0x92)
|
426
|
+
# When the module receives an IO sample fram efrom remote device, it sends the
|
427
|
+
# sample out the UART using this frame (when AO=0). Only modules running API
|
428
|
+
# firmware will send IO samples out the UART. In a wireless sensor network
|
429
|
+
# this frame is probably the most important data carrier for sensory payloads.
|
430
|
+
# +----------------------------+
|
431
|
+
# |___________Header___________|
|
432
|
+
# | SDelim | DlenMSB | DlenLSB |
|
433
|
+
# +--------+---------+---------+
|
434
|
+
# | 0x7e | 0x00 | 0x14 |
|
435
|
+
# +--------+---------+---------+------------------------------------------------------------------------------------+------+
|
436
|
+
# |______________________________________________________Frame______________________________________________________| |
|
437
|
+
# | Type | 64-bitRemoteSource | SNet16 | ReceiveOptions | NoOfSamples | DChanlMask | AChanlMask | DSample | ASample | CSum |
|
438
|
+
# +------+--------------------+--------+----------------+-------------+------------+------------+---------+---------+------+
|
439
|
+
# | 0x92 | 0x0012a20040522baa | 0x7c84 | 0x01 | 0x01 | 0x001c | 0x02 | 0x0014 | 0x0225 | 0xf7 |
|
440
|
+
# +------+--------------------+--------+----------------+-------------+------------+------------+---------+---------+------+
|
441
|
+
def test_zigbee_io_data_sample_rx_indicator
|
442
|
+
Thread.fork(@server.accept) do |client|
|
443
|
+
f = [ 0x7e, 0x00, 0x14, 0x92, 0x00, 0x12, 0xa2, 0x00, 0x40, 0x52, 0x2b, 0xaa, 0x7c, 0x84, 0x01, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x14, 0x02, 0x25, 0xf7 ]
|
444
|
+
client.write(f.pack("c*"))
|
445
|
+
client.close
|
446
|
+
end
|
447
|
+
|
448
|
+
xbee_frame = XBee::Frame.new(@s)
|
449
|
+
assert_equal("\x00\x12\xa2\x00\x40\x52\x2b\xaa\x7c\x84\x01\x01\x00\x1c\x02\x00\x14\x02\x25".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
450
|
+
assert_equal(0x92, xbee_frame.api_identifier)
|
451
|
+
end
|
452
|
+
|
453
|
+
##
|
454
|
+
# Remote Command Response (0x97)
|
455
|
+
# If a module receives a remote command response RF data frame in response to a Remote AT Command Request,
|
456
|
+
# the module will send out a Remote AT Command response message back. Some commands can trigger sending back
|
457
|
+
# multiple frames, for example Node Discover (ND).
|
458
|
+
# +----------------------------+---------------------------------------------------------------------------+------+
|
459
|
+
# |___________Header___________|___________________________________Frame___________________________________| |
|
460
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitRemoteSource | SNet16 | A T | CStatus | CommandData | CSum |
|
461
|
+
# +--------+---------+---------+------+----+--------------------+--------+---------+---------+-------------+------+
|
462
|
+
# | 0x7e | 0x00 | 0x13 | 0x97 |0x04| 0x0012a20040522baa | 0x7c84 |0x53|0x4c| 0x00 | 0x40522baa | 0x43 |
|
463
|
+
# +--------+---------+---------+------+----+--------------------+--------+---------+---------+-------------+------+
|
464
|
+
def test_remote_command_response_ok
|
465
|
+
Thread.fork(@server.accept) do |client|
|
466
|
+
f = [ 0x7e, 0x00, 0x13, 0x97, 0x04, 0x00, 0x12, 0xa2, 0x00, 0x40, 0x52, 0x2b, 0xaa, 0x7c, 0x84, 0x53, 0x4c, 0x00, 0x40, 0x52, 0x2b, 0xaa, 0x43 ]
|
467
|
+
client.write(f.pack("c*"))
|
468
|
+
client.close
|
469
|
+
end
|
470
|
+
|
471
|
+
xbee_frame = XBee::Frame.new(@s)
|
472
|
+
assert_equal(0x97, xbee_frame.api_identifier)
|
473
|
+
end
|
474
|
+
|
475
|
+
##
|
476
|
+
# Remote Command Response (0x97) - Remote Command Transmission Failed
|
477
|
+
# At the moment this is generic ReceivedFrame where api_identifier and cmd_data are populated
|
478
|
+
# +----------------------------+---------------------------------------------------------------------------+------+
|
479
|
+
# |___________Header___________|___________________________________Frame___________________________________| |
|
480
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitRemoteSource | SNet16 | A T | CStatus | CommandData | CSum |
|
481
|
+
# +--------+---------+---------+------+----+--------------------+--------+---------+---------+-------------+------+
|
482
|
+
# | 0x7e | 0x00 | 0x13 | 0x97 |0x04| 0x0012a20040522baa | 0x7c84 |0x53|0x4c| 0x04 | 0x40522baa | 0x3f |
|
483
|
+
# +--------+---------+---------+------+----+--------------------+--------+---------+---------+-------------+------+
|
484
|
+
def test_remote_command_response_transmission_failed
|
485
|
+
Thread.fork(@server.accept) do |client|
|
486
|
+
f = [ 0x7e, 0x00, 0x13, 0x97, 0x04, 0x00, 0x12, 0xa2, 0x00, 0x40, 0x52, 0x2b, 0xaa, 0x7c, 0x84, 0x53, 0x4c, 0x04, 0x40, 0x52, 0x2b, 0xaa, 0x3f ]
|
487
|
+
client.write(f.pack("c*"))
|
488
|
+
client.close
|
489
|
+
end
|
490
|
+
|
491
|
+
xbee_frame = XBee::Frame.new(@s)
|
492
|
+
assert_equal(0x97, xbee_frame.api_identifier)
|
493
|
+
assert_equal("\x04\x00\x12\xa2\x00\x40\x52\x2b\xaa\x7c\x84\x53\x4c\x04\x40\x52\x2b\xaa".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
494
|
+
end
|
495
|
+
|
496
|
+
##
|
497
|
+
# Remote Command Response (0x97) - Invalid status byte
|
498
|
+
# At the moment this is generic ReceivedFrame where api_identifier and cmd_data are populated
|
499
|
+
# +----------------------------+---------------------------------------------------------------------------+------+
|
500
|
+
# |___________Header___________|___________________________________Frame___________________________________| |
|
501
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitRemoteSource | SNet16 | A T | CStatus | CommandData | CSum |
|
502
|
+
# +--------+---------+---------+------+----+--------------------+--------+---------+---------+-------------+------+
|
503
|
+
# | 0x7e | 0x00 | 0x13 | 0x97 |0x04| 0x0012a20040522baa | 0x7c84 |0x53|0x4c| 0x05 | 0x40522baa | 0x3e |
|
504
|
+
# +--------+---------+---------+------+----+--------------------+--------+---------+---------+-------------+------+
|
505
|
+
def test_remote_command_response_invalid_status_byte
|
506
|
+
Thread.fork(@server.accept) do |client|
|
507
|
+
f = [ 0x7e, 0x00, 0x13, 0x97, 0x04, 0x00, 0x12, 0xa2, 0x00, 0x40, 0x52, 0x2b, 0xaa, 0x7c, 0x84, 0x53, 0x4c, 0x05, 0x40, 0x52, 0x2b, 0xaa, 0x3e ]
|
508
|
+
client.write(f.pack("c*"))
|
509
|
+
client.close
|
510
|
+
end
|
511
|
+
|
512
|
+
runtimeerror_raised = assert_raises(RuntimeError) {
|
513
|
+
xbee_frame = XBee::Frame.new(@s)
|
514
|
+
assert_equal(0x97, xbee_frame.api_identifier)
|
515
|
+
}
|
516
|
+
assert_equal("AT Command Response frame appears to include an invalid status: 0x05", runtimeerror_raised.message)
|
517
|
+
|
518
|
+
end
|
519
|
+
|
520
|
+
##
|
521
|
+
# Teardown
|
522
|
+
def teardown
|
523
|
+
@s.close
|
524
|
+
@server.close
|
525
|
+
unless ENV['OS'] == "Windows_NT"
|
526
|
+
File.delete( @unix_socket ) if FileTest.exists?( @unix_socket )
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
$: << File.dirname(__FILE__)
|
2
|
+
require 'test_helper'
|
3
|
+
require 'ruby-xbee'
|
4
|
+
|
5
|
+
##
|
6
|
+
# The goal of these tests is simply to instantiate the main XBee class for
|
7
|
+
# API mode access. If a device is present and configured a simple association
|
8
|
+
# check retrieval is made.
|
9
|
+
class RubyXbeeApimodeSetup < MiniTest::Test
|
10
|
+
def setup
|
11
|
+
@xbee_missing = false
|
12
|
+
@uart_config = XBee::Config::XBeeUARTConfig.new()
|
13
|
+
@xbee_usbdev_str = TOPLEVEL_BINDING.eval('self').instance_variable_get(:@xbee_usbdev_str)
|
14
|
+
begin
|
15
|
+
@xbee = XBee::BaseAPIModeInterface.new(@xbee_usbdev_str, @uart_config, :API, :SYNC)
|
16
|
+
rescue
|
17
|
+
@xbee_missing = true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_uart
|
22
|
+
assert_kind_of String, @xbee_usbdev_str
|
23
|
+
assert_equal 9600, @uart_config.baud
|
24
|
+
assert_equal 8, @uart_config.data_bits
|
25
|
+
assert_equal 0, @uart_config.parity
|
26
|
+
assert_equal 1, @uart_config.stop_bits
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_operation_mode
|
30
|
+
unless @xbee_missing
|
31
|
+
assert_equal :API, @xbee.operation_mode
|
32
|
+
@xbee.operation_mode = :AT
|
33
|
+
assert_equal :AT, @xbee.operation_mode
|
34
|
+
@xbee.operation_mode = :API
|
35
|
+
assert_equal :API, @xbee.operation_mode
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_transmission_mode
|
40
|
+
unless @xbee_missing
|
41
|
+
assert_equal :SYNC, @xbee.transmission_mode
|
42
|
+
@xbee.transmission_mode = :ASYNC
|
43
|
+
assert_equal :ASYNC, @xbee.transmission_mode
|
44
|
+
@xbee.transmission_mode = :SYNC
|
45
|
+
assert_equal :SYNC, @xbee.transmission_mode
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_association_indication
|
50
|
+
assert_equal 0, @xbee.association_indication unless @xbee_missing
|
51
|
+
end
|
52
|
+
end
|
data/test/ruby_xbee_test.rb
CHANGED
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
require 'version'
|
4
4
|
|
5
5
|
# The most simple test there can possibly BE, let's check constant for constant
|
6
|
-
class RubyXbeeTest < MiniTest::
|
6
|
+
class RubyXbeeTest < MiniTest::Test
|
7
7
|
def setup
|
8
8
|
@xbee_version_major = ::XBee::Version::MAJOR
|
9
9
|
@xbee_version_minor = ::XBee::Version::MINOR
|
@@ -13,8 +13,8 @@ class RubyXbeeTest < MiniTest::Unit::TestCase
|
|
13
13
|
|
14
14
|
def test_version_matches_testsuite
|
15
15
|
assert_equal 1, @xbee_version_major
|
16
|
-
assert_equal
|
16
|
+
assert_equal 2, @xbee_version_minor
|
17
17
|
assert_equal 0, @xbee_version_patch
|
18
|
-
assert_equal '1.
|
18
|
+
assert_equal '1.2.0', @xbee_version_string
|
19
19
|
end
|
20
20
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,22 +1,25 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'versioncheck'
|
3
|
-
require 'minitest/autorun'
|
4
|
-
require 'minitest/reporters'
|
5
2
|
|
6
3
|
rb_vc = VersionCheck.rubyversion
|
7
|
-
if !rb_vc.have_version?(2,
|
4
|
+
if !rb_vc.have_version?(2,1)
|
8
5
|
require 'simplecov'
|
9
6
|
SimpleCov.command_name 'MiniTest'
|
10
7
|
SimpleCov.start
|
11
8
|
end
|
12
9
|
|
10
|
+
if ENV['TRAVIS'] == "true" && ENV['CI'] =="true"
|
11
|
+
require 'coveralls'
|
12
|
+
Coveralls.wear!
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'rubygems'
|
16
|
+
require 'minitest/autorun'
|
17
|
+
require 'minitest/reporters'
|
18
|
+
|
13
19
|
MiniTest::Reporters.use!
|
14
20
|
|
15
21
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
16
22
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'bin'))
|
17
23
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
18
24
|
|
19
|
-
require 'ruby_xbee'
|
20
|
-
require 'coveralls'
|
21
|
-
|
22
|
-
Coveralls.wear!
|
25
|
+
require 'ruby_xbee'
|