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
data/lib/module_config.rb
CHANGED
@@ -73,5 +73,22 @@ module XBee
|
|
73
73
|
super("NI", default)
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
class ApiEnableMode < RFModuleParameter
|
78
|
+
def initialize(default = 0x01)
|
79
|
+
unless default == 0x01 or default == 0x02
|
80
|
+
raise "XBee AP parameter range can be 1-2; 1 = API-enabled; 2 = API-enabled (with escaped control characters)"
|
81
|
+
end
|
82
|
+
super("AP", default)
|
83
|
+
end
|
84
|
+
|
85
|
+
def in_symbol
|
86
|
+
unless self.value == 0x01 or self.value == 0x02
|
87
|
+
raise "XBee AP parameter invalid range! Valid range 1-2; Set to: #{self.value}"
|
88
|
+
end
|
89
|
+
return :API1 if self.value == 0x01
|
90
|
+
return :API2 if self.value == 0x02
|
91
|
+
end
|
92
|
+
end
|
76
93
|
end
|
77
94
|
end
|
data/lib/ruby_xbee.rb
CHANGED
@@ -66,12 +66,12 @@ module XBee
|
|
66
66
|
# This is it, the base class where it all starts. Command mode or API mode, version 1 or version 2, all XBees descend
|
67
67
|
# from this class.
|
68
68
|
class RFModule
|
69
|
-
|
69
|
+
|
70
70
|
VERSION = "2.1"
|
71
|
-
|
71
|
+
|
72
72
|
include XBee
|
73
73
|
include Config
|
74
|
-
attr_accessor :xbee_serialport, :xbee_uart_config, :guard_time, :command_mode_timeout, :command_character, :node_discover_timeout, :node_identifier, :operation_mode, :transmission_mode
|
74
|
+
attr_accessor :xbee_serialport, :xbee_uart_config, :guard_time, :command_mode_timeout, :command_character, :node_discover_timeout, :node_identifier, :operation_mode, :api_mode, :transmission_mode
|
75
75
|
attr_reader :serial_number, :hardware_rev, :firmware_rev
|
76
76
|
|
77
77
|
def version
|
@@ -86,10 +86,10 @@ module XBee
|
|
86
86
|
raise "uart_config must be an instance of XBeeUARTConfig for this to work"
|
87
87
|
end
|
88
88
|
unless operation_mode == :AT || operation_mode == :API
|
89
|
-
raise "XBee operation_mode must be either AT or API"
|
89
|
+
raise "XBee operation_mode must be either :AT or :API"
|
90
90
|
end
|
91
91
|
unless transmission_mode == :SYNC || transmission_mode == :ASYNC
|
92
|
-
raise "XBee transmission_mode must be either SYNC (Synchronous) or ASYNC (Asynchronous)"
|
92
|
+
raise "XBee transmission_mode must be either :SYNC (Synchronous) or :ASYNC (Asynchronous)"
|
93
93
|
end
|
94
94
|
self.xbee_uart_config = uart_config
|
95
95
|
@xbee_serialport = SerialPort.new( xbee_usbdev_str, uart_config.baud, uart_config.data_bits, uart_config.stop_bits, uart_config.parity )
|
@@ -100,6 +100,7 @@ module XBee
|
|
100
100
|
@node_discover_timeout = NodeDiscoverTimeout.new
|
101
101
|
@node_identifier = NodeIdentifier.new
|
102
102
|
@operation_mode = operation_mode
|
103
|
+
@api_mode = ApiEnableMode.new
|
103
104
|
@transmission_mode = transmission_mode
|
104
105
|
end
|
105
106
|
|
@@ -123,7 +124,7 @@ module XBee
|
|
123
124
|
case type
|
124
125
|
when :short
|
125
126
|
1200
|
126
|
-
when :long
|
127
|
+
when :long
|
127
128
|
3000
|
128
129
|
else 3000
|
129
130
|
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
$: << File.dirname(__FILE__)
|
2
|
+
require 'ruby_xbee_api_frame_test'
|
3
|
+
# Test cases for ZigBee Explicit Addressing Command (Frame Type: 0x11)
|
4
|
+
# Test cases to cover the construction/sending and receiving/decoding
|
5
|
+
# scenarios.
|
6
|
+
class ExplicitAddressingCommand < RubyXbeeApiFrameTest
|
7
|
+
|
8
|
+
##
|
9
|
+
# Explicit Addressing ZigBee Command Frame (0x11)
|
10
|
+
# This allows ZigBee application layer fields (endpoint and cluster ID) to be specified for a data transmission.
|
11
|
+
# Here we send a valid OTA start request without encryption and OTA password set to broadcast destination network
|
12
|
+
# +----------------------------+--------------------------------------------------------------------------------------------------------------------------------+------+
|
13
|
+
# |___________Header___________|______________________________________________________________Frame_____________________________________________________________| |
|
14
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitDestination | Dest16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | BCRadius | Options | Data Payload | CSum |
|
15
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------+-----------+----------+---------+----------------+------+
|
16
|
+
# | 0x7e | 0x00 | 0x15 | 0x11 |0x10| 0x0101010101010ABC | 0xfffe | 0xE8 | 0xE8 | 0x1000 | 0xC105 | 0x00 | 0x00 | 0x00 | 0x6F |
|
17
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------------------+----------+---------+----------------+------+
|
18
|
+
def test_eac_receive_ota_init_no_password
|
19
|
+
Thread.fork(@server.accept) do |client|
|
20
|
+
f = [ 0x7E, 0x00, 0x15, 0x11, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0A, 0xBC, 0xFF, 0xFE, 0xE8, 0xE8, 0x10, 0x00, 0xC1, 0x05, 0x00, 0x00, 0x00, 0x6F ]
|
21
|
+
client.write(f.pack("c*"))
|
22
|
+
client.close
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
xbee_frame = XBee::Frame.new(@s)
|
27
|
+
assert_equal("\x10\x01\x01\x01\x01\x01\x01\x0A\xBC\xFF\xFE\xE8\xE8\x10\x00\xC1\x05\x00\x00\x00".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
28
|
+
assert_equal(0x11, xbee_frame.api_identifier)
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Explicit Addressing ZigBee Command Frame (0x11)
|
33
|
+
# This allows ZigBee application layer fields (endpoint and cluster ID) to be specified for a data transmission.
|
34
|
+
# Here we send a valid OTA start request without encryption and OTA password set to broadcast destination network
|
35
|
+
# +----------------------------+--------------------------------------------------------------------------------------------------------------------------------+------+
|
36
|
+
# |___________Header___________|______________________________________________________________Frame_____________________________________________________________| |
|
37
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitDestination | Dest16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | BCRadius | Options | Data Payload | CSum |
|
38
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------+-----------+----------+---------+----------------+------+
|
39
|
+
# | 0x7e | 0x00 | 0x15 | 0x11 |0x10| 0x0101010101010ABC | 0xfffe | 0xE8 | 0xE8 | 0x1000 | 0xC105 | 0x00 | 0x00 | 0x00 | 0x6F |
|
40
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------------------+----------+---------+----------------+------+
|
41
|
+
def test_eac_create_ota_init_no_password_default_payload_pack
|
42
|
+
Thread.fork(@server.accept) do |client|
|
43
|
+
frame = XBee::Frame::ExplicitAddressingCommand.new(0x10, 0x0101010101010ABC, 0x0000fffe, 0xE8, 0xE8, 0x1000, 0xC105, 0x00, 0x00)
|
44
|
+
client.write(frame._dump)
|
45
|
+
client.close
|
46
|
+
end
|
47
|
+
|
48
|
+
xbee_frame = XBee::Frame.new(@s)
|
49
|
+
assert_equal("\x10\x01\x01\x01\x01\x01\x01\x0A\xBC\xFF\xFE\xE8\xE8\x10\x00\xC1\x05\x00\x00\x00".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
50
|
+
assert_equal(0x11, xbee_frame.api_identifier)
|
51
|
+
|
52
|
+
# Build the frame from the received data
|
53
|
+
frame = XBee::Frame::ExplicitAddressingCommand.new()
|
54
|
+
frame.cmd_data = xbee_frame.cmd_data
|
55
|
+
|
56
|
+
assert_equal 0x10, frame.frame_id
|
57
|
+
assert_equal 0x0101010101010ABC, frame.destination_address
|
58
|
+
assert_equal 0xfffe, frame.destination_network
|
59
|
+
assert_equal 0xE8, frame.source_endpoint
|
60
|
+
assert_equal 0xE8, frame.destination_endpoint
|
61
|
+
assert_equal 0x1000, frame.cluster_id
|
62
|
+
assert_equal 0xc105, frame.profile_id
|
63
|
+
assert_equal 0x00, frame.broadcast_radius
|
64
|
+
assert_equal 0x00, frame.transmit_options
|
65
|
+
assert_equal "\0", frame.payload
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Explicit Addressing ZigBee Command Frame (0x11)
|
71
|
+
# This allows ZigBee application layer fields (endpoint and cluster ID) to be specified for a data transmission.
|
72
|
+
# Here we send a valid OTA start request without encryption and OTA password set to broadcast destination network
|
73
|
+
# +----------------------------+--------------------------------------------------------------------------------------------------------------------------------+------+
|
74
|
+
# |___________Header___________|______________________________________________________________Frame_____________________________________________________________| |
|
75
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitDestination | Dest16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | BCRadius | Options | Data Payload | CSum |
|
76
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------+-----------+----------+---------+----------------+------+
|
77
|
+
# | 0x7e | 0x00 | 0x15 | 0x11 |0x10| 0x0101010101010ABC | 0xfffe | 0xE8 | 0xE8 | 0x1000 | 0xC105 | 0x00 | 0x00 | 0x00 | 0x6F |
|
78
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------------------+----------+---------+----------------+------+
|
79
|
+
# This is an interesting packet because in AP2 (with escaped control characters) The Frame Type gets escaped
|
80
|
+
def test_eac_create_ota_init_no_password_default_payload_pack_ap2
|
81
|
+
Thread.fork(@server.accept) do |client|
|
82
|
+
frame = XBee::Frame::ExplicitAddressingCommand.new(0x10, 0x0101010101010ABC, 0x0000fffe, 0xE8, 0xE8, 0x1000, 0xC105, 0x00, 0x00)
|
83
|
+
client.write(frame._dump(:API2))
|
84
|
+
client.close
|
85
|
+
end
|
86
|
+
|
87
|
+
xbee_frame = XBee::Frame.new(@s, :API2)
|
88
|
+
assert_equal("\x10\x01\x01\x01\x01\x01\x01\x0A\xBC\xFF\xFE\xE8\xE8\x10\x00\xC1\x05\x00\x00\x00".force_encoding("iso-8859-1"), xbee_frame.cmd_data.force_encoding("iso-8859-1"))
|
89
|
+
assert_equal(0x11, xbee_frame.api_identifier)
|
90
|
+
|
91
|
+
# Build the frame from the received data
|
92
|
+
frame = XBee::Frame::ExplicitAddressingCommand.new()
|
93
|
+
frame.cmd_data = xbee_frame.cmd_data
|
94
|
+
|
95
|
+
assert_equal 0x10, frame.frame_id
|
96
|
+
assert_equal 0x0101010101010ABC, frame.destination_address
|
97
|
+
assert_equal 0xfffe, frame.destination_network
|
98
|
+
assert_equal 0xE8, frame.source_endpoint
|
99
|
+
assert_equal 0xE8, frame.destination_endpoint
|
100
|
+
assert_equal 0x1000, frame.cluster_id
|
101
|
+
assert_equal 0xc105, frame.profile_id
|
102
|
+
assert_equal 0x00, frame.broadcast_radius
|
103
|
+
assert_equal 0x00, frame.transmit_options
|
104
|
+
assert_equal "\0", frame.payload
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# Explicit Addressing ZigBee Command Frame (0x11)
|
110
|
+
# This allows ZigBee application layer fields (endpoint and cluster ID) to be specified for a data transmission.
|
111
|
+
# Here we send a valid OTA start request without encryption and OTA password set to broadcast destination network
|
112
|
+
# +----------------------------+--------------------------------------------------------------------------------------------------------------------------------+------+
|
113
|
+
# |___________Header___________|______________________________________________________________Frame_____________________________________________________________| |
|
114
|
+
# | SDelim | DlenMSB | DlenLSB | Type | ID | 64-bitDestination | Dest16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | BCRadius | Options | Data Payload | CSum |
|
115
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------+-----------+----------+---------+----------------+------+
|
116
|
+
# | 0x7e | 0x00 | 0x15 | 0x11 |0x10| 0x0101010101010ABC | 0xfffe | 0xE8 | 0xE8 | 0x1000 | 0xC105 | 0x00 | 0x00 | 0x00 | 0x6F |
|
117
|
+
# +--------+---------+---------+------+----+--------------------+--------+-----------+------------+-----------------------+----------+---------+----------------+------+
|
118
|
+
# Here we send the packet in AP2 mode (escaped) but receive the packet in AP1 mode (unescaped) - the world should collapse because of bad checksum
|
119
|
+
def test_eac_create_ota_init_no_password_default_payload_pack_ap2
|
120
|
+
Thread.fork(@server.accept) do |client|
|
121
|
+
frame = XBee::Frame::ExplicitAddressingCommand.new(0x10, 0x0101010101010ABC, 0x0000fffe, 0xE8, 0xE8, 0x1000, 0xC105, 0x00, 0x00)
|
122
|
+
client.write(frame._dump(:API2))
|
123
|
+
client.close
|
124
|
+
end
|
125
|
+
|
126
|
+
runtimeerror_raised = assert_raises(RuntimeError) {
|
127
|
+
xbee_frame = XBee::Frame.new(@s)
|
128
|
+
}
|
129
|
+
assert_equal("Bad checksum - data discarded", runtimeerror_raised.message)
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
$: << File.dirname(__FILE__)
|
2
|
+
require 'ruby_xbee_api_frame_test'
|
3
|
+
# Test cases for ZigBee Explicit Rx Indicator (Frame Type: 0x91)
|
4
|
+
# Test cases to cover the construction/sending and receiving/decoding
|
5
|
+
# scenarios.
|
6
|
+
class ExplicitRxIndicator < RubyXbeeApiFrameTest
|
7
|
+
##
|
8
|
+
# ZigBee Explicit Rx Indicator - (0x91) When the modem receives a ZigBee RF packet
|
9
|
+
# it is sent out the UART using this message type (when AO=1).
|
10
|
+
# +----------------------------+----------------------------------------------------------------------------------------------------------------+------+
|
11
|
+
# |___________Header___________|_____________________________________________________Frame______________________________________________________| |
|
12
|
+
# | SDelim | DlenMSB | DlenLSB | Type | 64-bit Source Addr | Src.16 | SrcEndPnt | DestEndPnt | ClusterID | ProfileID | Options | Data Payload | CSum |
|
13
|
+
# +--------+---------+---------+------+--------------------+--------+-----------+------------+-----------+-----------+---------+----------------+------+
|
14
|
+
# | 0x7E | 0x00 | 0x13 | 0x91 | 0x1234567890ABCDEF | 0x1234 | 0xE8 | 0xE8 | 0x0011 | 0xC105 | 0x01 | 0x43 | 0x32 |
|
15
|
+
# +--------+---------+---------+------+--------------------+--------+-----------+------------+-----------+-----------+---------+----------------+------+
|
16
|
+
# 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
|
17
|
+
# And use for example in OTA firmware upgrade
|
18
|
+
def test_zigbee_explicit_rx_indicator_xmodem_start
|
19
|
+
Thread.fork(@server.accept) do |client|
|
20
|
+
f = [ 0x7E, 0x00, 0x13, 0x91, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
|
21
|
+
0x12, 0x34, 0xE8, 0xE8, 0x00, 0x11, 0xC1, 0x05, 0x01, 0x43, 0x32 ]
|
22
|
+
client.write(f.pack("c*"))
|
23
|
+
client.close
|
24
|
+
end
|
25
|
+
|
26
|
+
xbee_frame = XBee::Frame.new(@s)
|
27
|
+
|
28
|
+
assert_equal 0x91, xbee_frame.api_identifier
|
29
|
+
assert_equal 0x1234567890ABCDEF, xbee_frame.source_address
|
30
|
+
assert_equal 0x1234, xbee_frame.source_network
|
31
|
+
assert_equal 0xE8, xbee_frame.source_endpoint
|
32
|
+
assert_equal 0xE8, xbee_frame.destination_endpoint
|
33
|
+
assert_equal 0x0011, xbee_frame.cluster_id
|
34
|
+
assert_equal 0xc105, xbee_frame.profile_id
|
35
|
+
assert_equal 0x01, xbee_frame.receive_options
|
36
|
+
assert_equal "C".force_encoding("iso-8859-1"), xbee_frame.received_data.force_encoding("iso-8859-1")
|
37
|
+
|
38
|
+
|
39
|
+
# Let's construct a frame from scratch and use the data previously received
|
40
|
+
frame = XBee::Frame::ExplicitRxIndicator.new
|
41
|
+
frame.cmd_data = xbee_frame.cmd_data
|
42
|
+
|
43
|
+
assert_equal frame.api_identifier, xbee_frame.api_identifier
|
44
|
+
assert_equal frame.source_address, xbee_frame.source_address
|
45
|
+
assert_equal frame.source_network, xbee_frame.source_network
|
46
|
+
assert_equal frame.source_endpoint, xbee_frame.source_endpoint
|
47
|
+
assert_equal frame.destination_endpoint, xbee_frame.destination_endpoint
|
48
|
+
assert_equal frame.cluster_id, xbee_frame.cluster_id
|
49
|
+
assert_equal frame.profile_id, xbee_frame.profile_id
|
50
|
+
assert_equal frame.receive_options, xbee_frame.receive_options
|
51
|
+
assert_equal frame.received_data, xbee_frame.received_data
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|