ruxbee 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruxbee"
5
+ require 'pp'
6
+ require 'getoptlong'
7
+
8
+
9
+ opts = GetoptLong.new(
10
+ [ '--device', '-d', GetoptLong::REQUIRED_ARGUMENT ],
11
+ [ '--speed', '-s', GetoptLong::REQUIRED_ARGUMENT ]
12
+ )
13
+
14
+ @dev = nil
15
+ @speed = nil
16
+
17
+ opts.each do |opt, arg|
18
+ case opt
19
+ when '--device'
20
+ @dev = arg
21
+ when '--speed'
22
+ @speed = arg.to_i
23
+ end
24
+ end
25
+
26
+ @xbee = XBee.new @dev, @speed, :API_S1
27
+
28
+ loop do
29
+ res = @xbee.getresponse
30
+ if not res.nil? and res.api_identifier == '81'
31
+ res = {rssi: res.rssi, address: res.address_16_bits, api_frame_id: res.api_identifier, data: res.cmd_data}
32
+ pp res
33
+ end
34
+ end
35
+
data/icon.jpg ADDED
Binary file
@@ -0,0 +1,28 @@
1
+ module XBee
2
+ module ATCommands
3
+ class ParameterDescriptor
4
+ def initialize
5
+ yield self if block_given?
6
+ end
7
+ end
8
+
9
+ class CommandDescriptor
10
+ attr_reader :command, :command_name, :command_description, :parameter
11
+
12
+ def initialize (command, command_name, command_description = nil, parameter = nil)
13
+ @command = command
14
+ @command_name = command_name
15
+ @command_description = command_description
16
+ @parameter = parameter
17
+ yield self if block_given?
18
+ end
19
+
20
+ def has_parameter?
21
+ parameter.nil?
22
+ end
23
+ end
24
+
25
+ AP_PARAM_DESCRIPTOR = ParameterDescriptor.new
26
+ AP = CommandDescriptor.new("AP","API Mode","0 = off; 1 = on, unescaped; 2 = on, escaped", AP_PARAM_DESCRIPTOR)
27
+ end
28
+ end
@@ -0,0 +1,96 @@
1
+
2
+ module XBee
3
+ module Config
4
+ ##
5
+ # A class for encapsulating UART communication parameters
6
+
7
+ class XBeeUARTConfig
8
+ attr_accessor :baud, :data_bits, :parity, :stop_bits
9
+
10
+ ##
11
+ # Defaults to standard 9600 baud 8N1 communications
12
+ def initialize(baud = 9600, data_bits = 8, parity = 0, stop_bits = 1)
13
+ self.baud = Integer(baud)
14
+ self.data_bits = Integer(data_bits)
15
+ self.parity = Integer(parity)
16
+ self.stop_bits = Integer(stop_bits)
17
+ end
18
+
19
+ end
20
+
21
+ ##
22
+ # A class for encapsulating XBee programmable parameters
23
+ class RFModuleParameter
24
+ attr_accessor :at_name, :value, :default_value, :retrieved, :operation_mode
25
+
26
+ def initialize(at_name, default_value)
27
+ self.at_name= at_name
28
+ self.default_value = default_value
29
+ self.value = default_value
30
+ self.retrieved = false
31
+ end
32
+
33
+ end
34
+
35
+ class GuardTime < RFModuleParameter
36
+ def initialize(default = 0x3E8)
37
+ super("GT", default)
38
+ end
39
+
40
+ def in_seconds
41
+ self.value / 1000.0
42
+ end
43
+ end
44
+
45
+ class CommandModeTimeout < RFModuleParameter
46
+ def initialize(default = 0x64)
47
+ super("CT", default)
48
+ end
49
+
50
+ def in_seconds
51
+ self.value / 1000.0
52
+ end
53
+ end
54
+
55
+ class CommandCharacter < RFModuleParameter
56
+ def initialize(default = '+')
57
+ super("CC", default)
58
+ end
59
+ end
60
+
61
+
62
+ class NodeDiscoverTimeout < RFModuleParameter
63
+ def initialize(default = 0x82)
64
+ super("NT", default)
65
+ end
66
+
67
+ def in_seconds
68
+ self.value / 10.0
69
+ end
70
+ end
71
+
72
+ class NodeIdentifier < RFModuleParameter
73
+ def initialize(default = " ")
74
+ super("NI", default)
75
+ end
76
+ end
77
+
78
+ class ApiEnableMode < RFModuleParameter
79
+ def initialize(default = 0x01)
80
+ unless default == 0x01 or default == 0x02
81
+ raise "XBee AP parameter range can be 1-2; 1 = API-enabled; 2 = API-enabled (with escaped control characters)"
82
+ end
83
+ super("AP", default)
84
+ end
85
+
86
+ def in_symbol
87
+ unless self.value == 0x01 or self.value == 0x02
88
+ raise "XBee AP parameter invalid range! Valid range 1-2; Set to: #{self.value}"
89
+ end
90
+ return :API1 if self.value == 0x01
91
+ return :API2 if self.value == 0x02
92
+ end
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,35 @@
1
+
2
+ module XBee
3
+ module Frame
4
+ class ATCommand < XBee::Frame::Base
5
+ def api_identifier ; 0x08 ; end
6
+
7
+ attr_accessor :at_command, :parameter_value, :parameter_pack_string
8
+
9
+ def initialize(at_command, frame_id = nil, parameter_value = nil, parameter_pack_string = "a*")
10
+ self.frame_id = frame_id
11
+ self.at_command = at_command # TODO: Check for valid AT command codes here
12
+ self.parameter_value = parameter_value
13
+ self.parameter_pack_string = parameter_pack_string
14
+ yield self if block_given?
15
+ end
16
+
17
+ def cmd_data=(data_string)
18
+ self.frame_id, self.at_command, self.parameter_value = data_string.unpack("ca2#{parameter_pack_string}")
19
+ end
20
+
21
+ def cmd_data
22
+ if parameter_value.nil?
23
+ [frame_id, at_command].pack("ca2")
24
+ else
25
+ [frame_id, at_command, parameter_value].pack("ca2#{parameter_pack_string}")
26
+ end
27
+ end
28
+ end
29
+
30
+ class ATCommandQueueParameterValue < ATCommand
31
+ def api_identifier ; 0x09 ; end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ module XBee
2
+ module Frame
3
+ class ATCommandResponse < ReceivedFrame
4
+ attr_accessor :frame_id, :at_command, :status, :retrieved_value
5
+
6
+ def initialize(data = nil)
7
+ super(data) && (yield self if block_given?)
8
+ end
9
+
10
+ def command_statuses
11
+ [:OK, :ERROR, :Invalid_Command, :Invalid_Parameter]
12
+ end
13
+
14
+ def cmd_data=(data_string)
15
+ self.frame_id, self.at_command, status_byte, self.retrieved_value = data_string.unpack("Ca2Ca*")
16
+ self.status = case status_byte
17
+ when 0..3
18
+ command_statuses[status_byte]
19
+ else
20
+ raise "AT Command Response frame appears to include an invalid status: 0x%x" % status_byte
21
+ end
22
+ #actually assign and move along
23
+ @cmd_data = data_string
24
+ #### DEBUG ####
25
+ if $DEBUG then
26
+ print "Retrieved Value: #{self.retrieved_value.unpack('C*').join(', ')} | "
27
+ print "Retrieved Value: #{self.retrieved_value.unpack('a*')} | "
28
+ end
29
+ #### DEBUG ####
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ module XBee
2
+ module Frame
3
+
4
+ class Base
5
+ attr_accessor :api_identifier, :cmd_data, :frame_id
6
+
7
+ def api_identifier ; @api_identifier ||= 0x00 ; end
8
+
9
+ def cmd_data ; @cmd_data ||= "" ; end
10
+
11
+ def length ; data.length ; end
12
+
13
+ def data
14
+ Array(api_identifier).pack("C") + cmd_data
15
+ end
16
+
17
+ def _dump(api_mode = :API1)
18
+ unless api_mode == :API1 or api_mode == :API2
19
+ raise "XBee api_mode must be either :API1 (non-escaped) or :API2 (escaped, default)"
20
+ end
21
+ raise "Too much data (#{self.length} bytes) to fit into one frame!" if (self.length > 0xFFFF)
22
+
23
+ if (api_mode == :API1)
24
+ "~" + [length].pack("n") + data + [Frame.checksum(data)].pack("C")
25
+ elsif (api_mode == :API2)
26
+ "~" + [length].pack("n").xb_escape + data.xb_escape + [Frame.checksum(data)].pack("C")
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ module XBee
2
+ module Frame
3
+ ##
4
+ # Explicit Addressing ZigBee Command Frame (0x11)
5
+ #
6
+ # This frame allows ZigBee Application Layer fields to be specified for
7
+ # a data transmission. This frame is similar to Zigbee Transmit Request (0x10)
8
+ # but requires the ZigBee application layer addressing fields to be set.
9
+ #
10
+ # This frame is also used for triggering Programmable XBee (S2B) module
11
+ # Over-the-Air firmware upgrade process.
12
+ #
13
+ class ExplicitAddressingCommand < Base
14
+ def api_identifier ; 0x11 ; end
15
+
16
+ attr_accessor :destination_address, :destination_network, :source_endpoint, :destination_endpoint, :cluster_id, :profile_id, :broadcast_radius, :transmit_options, :payload, :payload_pack_string
17
+
18
+ def initialize(frame_id = nil, destination_address = 0x000000000000ffff, destination_network = 0x0000fffe, source_endpoint = nil, destination_endpoint = nil, cluster_id = nil, profile_id = nil, broadcast_radius = 0x00, transmit_options = 0x00, payload = nil, payload_pack_string = "a*")
19
+ self.frame_id = frame_id
20
+ self.destination_address = destination_address
21
+ self.destination_network = destination_network
22
+ self.source_endpoint = source_endpoint
23
+ self.destination_endpoint = destination_endpoint
24
+ self.cluster_id = cluster_id
25
+ self.profile_id = profile_id
26
+ self.broadcast_radius = broadcast_radius
27
+ self.transmit_options = transmit_options
28
+ self.payload = payload
29
+ self.payload_pack_string = payload_pack_string
30
+ end
31
+
32
+ def cmd_data=(data_string)
33
+ # We need to read in the 64-bit destination_address in two 32-bit parts.
34
+ dest_high = dest_low = 0
35
+ self.frame_id, dest_high, dest_low, self.destination_network, self.source_endpoint, self.destination_endpoint, self.cluster_id, self.profile_id, self.broadcast_radius, self.transmit_options, self.payload = data_string.unpack("CNNnCCnnCC#{payload_pack_string}")
36
+ self.destination_address = dest_high << 32 | dest_low
37
+ end
38
+
39
+ def cmd_data
40
+ # We need to pack the 64-bit destination_address in two 32-bit parts.
41
+ dest_high = (self.destination_address >> 32) & 0xFFFFFFFF
42
+ dest_low = self.destination_address & 0xFFFFFFFF
43
+ if payload.nil?
44
+ # By default we send a null-byte payload \0
45
+ [self.frame_id, dest_high, dest_low, self.destination_network, self.source_endpoint, self.destination_endpoint, self.cluster_id, self.profile_id, self.broadcast_radius, self.transmit_options, self.payload].pack("CNNnCCnnCCx")
46
+ else
47
+ [self.frame_id, dest_high, dest_low, self.destination_network, self.source_endpoint, self.destination_endpoint, self.cluster_id, self.profile_id, self.broadcast_radius, self.transmit_options, self.payload].pack("CNNnCCnnCC#{payload_pack_string}")
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ module XBee
2
+ module Frame
3
+ ##
4
+ # ZigBee Explicit Rx Indicator (0x91) (AO=1)
5
+ class ExplicitRxIndicator < ReceivedFrame
6
+ def api_identifier ; 0x91 ; end
7
+ attr_accessor :source_address, :source_network, :source_endpoint, :destination_endpoint, :cluster_id, :profile_id, :receive_options, :received_data
8
+
9
+ def initialize(data = nil)
10
+ super(data) && (yield self if block_given?)
11
+ end
12
+
13
+ def cmd_data=(data_string)
14
+ # We need to read in the 64-bit source_address in two 32-bit parts.
15
+ src_high = src_low = 0
16
+ src_high, src_low, self.source_network, self.source_endpoint, self.destination_endpoint, self.cluster_id, self.profile_id, self.receive_options, self.received_data = data_string.unpack("NNnCCnnCa*")
17
+ self.source_address = src_high << 32 | src_low
18
+ @cmd_data = data_string
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,128 @@
1
+ require 'ruxbee/frame/base_frame'
2
+ require 'ruxbee/frame/received_frame'
3
+ require 'ruxbee/frame/at_command'
4
+ require 'ruxbee/frame/at_command_response'
5
+ require 'ruxbee/frame/explicit_addressing_command'
6
+ require 'ruxbee/frame/explicit_rx_indicator'
7
+ require 'ruxbee/frame/io_data_sample_rx_indicator'
8
+ require 'ruxbee/frame/modem_status'
9
+ require 'ruxbee/frame/receive_packet'
10
+ require 'ruxbee/frame/remote_command_request'
11
+ require 'ruxbee/frame/remote_command_response'
12
+ require 'ruxbee/frame/transmit_request'
13
+ require 'ruxbee/frame/transmit_status'
14
+ require 'ruxbee/frame/receive_packet_16'
15
+
16
+ class String
17
+ def xb_escape
18
+ self.gsub(/[\176\175\021\023]/) { |c| [0x7D, c[0].ord ^ 0x20].pack("CC")}
19
+ end
20
+ def xb_unescape
21
+ self.gsub(/\175./) { |ec| [ec.unpack("CC").last ^ 0x20].pack("C")}
22
+ end
23
+ end
24
+
25
+ module XBee
26
+ module Frame
27
+ def Frame.checksum(data)
28
+ 0xFF - (data.unpack("C*").inject(0) { |sum, byte| (sum + byte) & 0xFF })
29
+ end
30
+
31
+ def Frame.new(source_io, api_mode = :API1)
32
+ stray_bytes = []
33
+ unless api_mode == :API1 or api_mode == :API2
34
+ raise "XBee api_mode must be either :API1 (non-escaped) or :API2 (escaped, default)"
35
+ end
36
+ until (start_delimiter = source_io.readchar.unpack('H*').join.to_i(16)) == 0x7e
37
+ #puts "Stray byte 0x%x" % start_delimiter
38
+ print "DEBUG: #{start_delimiter} | " if $DEBUG
39
+ stray_bytes << start_delimiter
40
+ end
41
+ if $VERBOSE
42
+ puts "Got some stray bytes for ya: #{stray_bytes.map {|b| "0x%x" % b} .join(", ")}" unless stray_bytes.empty?
43
+ end
44
+ if(api_mode == :API1)
45
+ header = source_io.read(3)
46
+ elsif(api_mode == :API2)
47
+ header = source_io.read(2).xb_unescape
48
+ end
49
+ print "Reading ... header after start byte: #{header.unpack("C*").join(", ")} | " if $DEBUG
50
+ frame_remaining = frame_length = api_identifier = cmd_data = ""
51
+ if api_mode == :API2
52
+ if header.length == 2
53
+ frame_length = header.unpack("n").first
54
+ else
55
+ read_extra_byte = source_io.readchar
56
+ if(read_extra_byte == "\175")
57
+ # We stumbled upon another escaped character, read another byte and unescape
58
+ read_extra_byte += source_io.readchar
59
+ read_extra_byte = read_extra_byte.xb_unescape
60
+ else
61
+ header += read_extra_byte
62
+ end
63
+ frame_length = header.unpack("n")
64
+ end
65
+ api_identifier = source_io.readchar
66
+ if(api_identifier == "\175")
67
+ api_identifier += source_io.readchar
68
+ api_identifier = api_identifier.xb_unescape
69
+ end
70
+ api_identifier = api_identifier.unpack("C").first
71
+ else
72
+ frame_length, api_identifier = header.unpack("nC")
73
+ end
74
+ #### DEBUG ####
75
+ if $DEBUG then
76
+ print "Frame length: #{frame_length} | "
77
+ print "Api Identifier: #{api_identifier} | "
78
+ end
79
+ #### DEBUG ####
80
+ cmd_data_intended_length = frame_length - 1
81
+ if api_mode == :API2
82
+ while ((unescaped_length = cmd_data.xb_unescape.length) < cmd_data_intended_length)
83
+ cmd_data += source_io.read(cmd_data_intended_length - unescaped_length)
84
+ end
85
+ data = api_identifier.chr + cmd_data.xb_unescape
86
+ else
87
+ while (cmd_data.length < cmd_data_intended_length)
88
+ cmd_data += source_io.read(cmd_data_intended_length)
89
+ end
90
+ data = api_identifier.chr + cmd_data
91
+ end
92
+ sent_checksum = source_io.getc.unpack('H*').join.to_i(16)
93
+ #### DEBUG ####
94
+ if $DEBUG then
95
+ print "Sent checksum: #{sent_checksum} | "
96
+ print "Received checksum: #{Frame.checksum(data)} | "
97
+ print "Payload: #{cmd_data.unpack("C*").join(", ")} | "
98
+ end
99
+ #### DEBUG ####
100
+ unless sent_checksum == Frame.checksum(data)
101
+ raise "Bad checksum - data discarded"
102
+ end
103
+ case data[0].unpack('H*')[0].to_i(16)
104
+ when 0x8A
105
+ ModemStatus.new(data)
106
+ when 0x81
107
+ ReceivePacket16.new(data)
108
+ when 0x88
109
+ ATCommandResponse.new(data)
110
+ when 0x97
111
+ RemoteCommandResponse.new(data)
112
+ when 0x8B
113
+ TransmitStatus.new(data)
114
+ when 0x90
115
+ ReceivePacket.new(data)
116
+ when 0x91
117
+ ExplicitRxIndicator.new(data)
118
+ when 0x92
119
+ IODataSampleRxIndicator.new(data)
120
+ else
121
+ ReceivedFrame.new(data)
122
+ end
123
+ rescue EOFError
124
+ # No operation as we expect eventually something
125
+ end
126
+
127
+ end
128
+ end
@@ -0,0 +1,10 @@
1
+ module XBee
2
+ module Frame
3
+ class IODataSampleRxIndicator < ReceivedFrame
4
+ def cmd_data=(data_string)
5
+
6
+ @cmd_data = data_string
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,32 @@
1
+ module XBee
2
+ module Frame
3
+ class ModemStatus < ReceivedFrame
4
+ attr_accessor :status
5
+
6
+ def initialize(data = nil)
7
+ super(data) && (yield self if block_given?)
8
+ end
9
+
10
+ def modem_statuses
11
+ [
12
+ [0, :Hardware_Reset],
13
+ [1, :Watchdog_Timer_Reset],
14
+ [2, :Associated],
15
+ ]
16
+ end
17
+
18
+ def cmd_data=(data_string)
19
+ status_byte = data_string.unpack("c")[0]
20
+ # update status ivar for later use
21
+ self.status = case status_byte
22
+ when 0..2
23
+ modem_statuses.assoc(status_byte)
24
+ else
25
+ raise "ModemStatus frame appears to include an invalid status value: 0x%02x" % status_byte
26
+ end
27
+ #actually assign and move along
28
+ @cmd_data = data_string
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,6 @@
1
+ module XBee
2
+ module Frame
3
+ class ReceivePacket < ReceivedFrame
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,29 @@
1
+ module XBee
2
+ module Frame
3
+
4
+ class ReceivePacket16 < Base
5
+ attr_reader :rssi, :address_16_bits, :options
6
+ @rssi = 0x00
7
+ @address_16_bits = 0x0000
8
+ @options = 0x00
9
+
10
+ def initialize(frame_data)
11
+ self.api_identifier = frame_data[0].unpack('H*')[0] #.join.to_i(16) unless frame_data.nil?
12
+ if $DEBUG then
13
+ print "Initializing a ReceivedFrame of type 0x%02x | " % self.api_identifier
14
+ elsif $VERBOSE
15
+ puts "Initializing a ReceivedFrame of type 0x%02x" % self.api_identifier
16
+ end
17
+ @address_16_bits = frame_data[1..2] unless frame_data.nil?
18
+ @rssi = frame_data[3] unless frame_data.nil?
19
+ @options = frame_data[4] unless frame_data.nil?
20
+ self.cmd_data = frame_data[5..-1] unless frame_data.nil?
21
+
22
+ @rssi = @rssi.unpack('C')[0]
23
+ @address_16_bits = @address_16_bits.unpack('B8B8').join()
24
+ @options = @options.unpack('B8')[0]
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module XBee
2
+ module Frame
3
+ class ReceivedFrame < Base
4
+ def initialize(frame_data)
5
+ self.api_identifier = frame_data[0].unpack('H*').join.to_i(16) unless frame_data.nil?
6
+ if $DEBUG then
7
+ print "Initializing a ReceivedFrame of type 0x%02x | " % self.api_identifier
8
+ elsif $VERBOSE
9
+ puts "Initializing a ReceivedFrame of type 0x%02x" % self.api_identifier
10
+ end
11
+ self.cmd_data = frame_data[1..-1] unless frame_data.nil?
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ require 'ruxbee/frame/at_command'
2
+
3
+ module XBee
4
+ module Frame
5
+ class RemoteCommandRequest < XBee::Frame::ATCommand
6
+ def api_identifier ; 0x17 ; end
7
+
8
+ attr_accessor :destination_address, :destination_network
9
+
10
+ def initialize(at_command, destination_address = 0x000000000000ffff, destination_network = 0x0000fffe, frame_id = nil, parameter_value = nil, parameter_pack_string = "a*")
11
+ self.destination_address = destination_address
12
+ self.destination_network = destination_network
13
+ super(at_command, frame_id, parameter_value, parameter_pack_string)
14
+ yield self if block_given?
15
+ end
16
+
17
+ def cmd_data=(data_string)
18
+ dest_high = dest_low = 0
19
+ self.frame_id, dest_high, dest_low, self.destination_network, self.at_command, self.parameter_value = data_string.unpack("CNNnxa2#{parameter_pack_string}")
20
+ self.destination_address = dest_high << 32 | dest_low
21
+ end
22
+
23
+ def cmd_data
24
+ dest_high = (self.destination_address >> 32) & 0xFFFFFFFF
25
+ dest_low = self.destination_address & 0xFFFFFFFF
26
+ if parameter_value.nil?
27
+ [self.frame_id, dest_high, dest_low, self.destination_network, 0x00, self.at_command].pack("CNNnCa2")
28
+ else
29
+ [self.frame_id, dest_high, dest_low, self.destination_network, 0x02, self.at_command, self.parameter_value].pack("CNNnCa2#{parameter_pack_string}")
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ require 'ruxbee/frame/at_command_response'
2
+
3
+ module XBee
4
+ module Frame
5
+ class RemoteCommandResponse < XBee::Frame::ATCommandResponse
6
+ attr_accessor :destination_address, :destination_network
7
+ def cmd_data=(data_string)
8
+ dest_high = dest_low = 0
9
+ self.frame_id, dest_high, dest_low, self.destination_network, self.at_command, status_byte, self.retrieved_value = data_string.unpack("CNNna2Ca*")
10
+ self.destination_address = dest_high << 32 | dest_low
11
+ self.status = case status_byte
12
+ when 0..4
13
+ command_statuses[status_byte]
14
+ else
15
+ raise "AT Command Response frame appears to include an invalid status: 0x%02x" % status_byte
16
+ end
17
+ #actually assign and move along
18
+ @cmd_data = data_string
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ module XBee
2
+ module Frame
3
+ class TransmitRequest < Base
4
+ def api_identifier ; 0x10 ; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module XBee
2
+ module Frame
3
+ class TransmitStatus < ReceivedFrame
4
+ end
5
+ end
6
+ end