ruby-xbee 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|