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
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
|