ruxbee 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,642 @@
1
+ require 'ruxbee/rfmodule'
2
+ require 'ruxbee/frame/frame'
3
+
4
+ module XBee
5
+ ##
6
+ # This is the main class for API mode for XBee radios.
7
+ class BaseAPIModeInterface < RFModule
8
+
9
+ VERSION = "1.2.0" # Version of this class
10
+
11
+ ##
12
+ # ==== Attributes
13
+ # * +xbee_usbdev_str+ - USB Device as a string
14
+ #
15
+ # ==== Options
16
+ # * +uart_config+ - XBeeUARTConfig
17
+ # * +operation_mode+ - Either :AT or :API for XBee operation mode
18
+ # * +transmission_mode+ - :SYNC for Synchronous communication or :ASYNC for Asynchonrous communication.
19
+ #
20
+ # A note on the asynchronous vs synchronous communication modes - A
21
+ # simplistic network of a few XBee nodes can pretty much work according to
22
+ # expected flows where requests and responses are always handled in
23
+ # synchronous ways. However, if bigger radio networks are being deployed
24
+ # (real scenarios) you cannot guarantee the synchronous nature of the network.
25
+ # You will have nodes joining/removing themselves, sleeping, sending data
26
+ # samples etc. Although the default behaviour is set as :SYNC, if you have a
27
+ # real network, then by design the network is Asynchronous, use :ASYNC instead.
28
+ # Otherwise you will most definitely run into "Invalid responses" issues.
29
+ #
30
+ # For handling the Asynchronous communication logic, use an external Queue
31
+ # and database to effectively handle the command/response and other frames
32
+ # that are concurrently being conversed on the PAN.
33
+ #
34
+ # ==== Example
35
+ # require 'ruby_xbee'
36
+ # @uart_config = XBee::Config::XBeeUARTConfig.new()
37
+ # @xbee_usbdev_str = '/dev/tty.usbserial-A101KYF6'
38
+ # @xbee = XBee::BaseAPIModeInterface.new(@xbee_usbdev_str, @uart_config, :API, :ASYNC)
39
+ #
40
+ def initialize(xbee_usbdev_str, uart_config = XBeeUARTConfig.new, operation_mode = :API, transmission_mode = :SYNC)
41
+ super(xbee_usbdev_str, uart_config, operation_mode, transmission_mode)
42
+ @frame_id = 1
43
+ if self.operation_mode == :AT
44
+ start_apimode_communication
45
+ end
46
+ end
47
+
48
+ def next_frame_id
49
+ @frame_id += 1
50
+ end
51
+
52
+ ##
53
+ # Switch to API mode - note that in Series 2 the Operation Mode is defined
54
+ # by the firmware flashed to the device. Only Series 1 can switch from
55
+ # AT (Transparent) to API Opearation and back seamlessly.
56
+ #
57
+ # API Mode 1 - API Enabled
58
+ # API Mode 2 - API Enabled, with escaped control characters
59
+ def start_apimode_communication
60
+ in_command_mode do
61
+ puts "Entering api mode"
62
+ # Set API Mode 2 (include escaped characters)
63
+ self.xbee_serialport.write("ATAP1\r")
64
+ self.xbee_serialport.read(3)
65
+ end
66
+ end
67
+
68
+ def get_param(at_param_name, at_param_unpack_string = nil)
69
+ frame_id = self.next_frame_id
70
+ at_command_frame = XBee::Frame::ATCommand.new(at_param_name,frame_id,nil,at_param_unpack_string)
71
+ puts "Sending ... [#{at_command_frame._dump(self.api_mode.in_symbol).unpack("C*").join(", ")}]" if $VERBOSE
72
+ self.xbee_serialport.write(at_command_frame._dump(self.api_mode.in_symbol))
73
+ if self.transmission_mode == :SYNC
74
+ r = XBee::Frame.new(self.xbee_serialport, self.api_mode.in_symbol)
75
+ if r.kind_of?(XBee::Frame::ATCommandResponse) && r.status == :OK && r.frame_id == frame_id
76
+ if block_given?
77
+ yield r
78
+ else
79
+ #### DEBUG ####
80
+ if $DEBUG then
81
+ print "At parameter unpack string to be used: #{at_param_unpack_string} | "
82
+ puts "Debug Return value for value: #{r.retrieved_value.unpack(at_param_unpack_string)}"
83
+ end
84
+ #### DEBUG ####
85
+ at_param_unpack_string.nil? ? r.retrieved_value : r.retrieved_value.unpack(at_param_unpack_string).first
86
+ end
87
+ else
88
+ raise "Response did not indicate successful retrieval of that parameter: #{r.inspect}"
89
+ end
90
+ end
91
+ end
92
+
93
+ def set_param(at_param_name, param_value, at_param_unpack_string = nil)
94
+ frame_id = self.next_frame_id
95
+ at_command_frame = XBee::Frame::ATCommand.new(at_param_name,frame_id,param_value,at_param_unpack_string)
96
+ # puts "Sending ... [#{at_command_frame._dump(self.api_mode.in_symbol).unpack("C*").join(", ")}]"
97
+ self.xbee_serialport.write(at_command_frame._dump(self.api_mode.in_symbol))
98
+ if self.transmission_mode == :SYNC
99
+ r = XBee::Frame.new(self.xbee_serialport, self.api_mode.in_symbol)
100
+ if r.kind_of?(XBee::Frame::ATCommandResponse) && r.status == :OK && r.frame_id == frame_id
101
+ if block_given?
102
+ yield r
103
+ else
104
+ at_param_unpack_string.nil? ? r.retrieved_value : r.retrieved_value.unpack(at_param_unpack_string).first
105
+ end
106
+ else
107
+ raise "Response did not indicate successful retrieval of that parameter: #{r.inspect}"
108
+ end
109
+ end
110
+ end
111
+
112
+ def get_remote_param(at_param_name, remote_address = 0x000000000000ffff, remote_network_address = 0xfffe, at_param_unpack_string = nil)
113
+ frame_id = self.next_frame_id
114
+ at_command_frame = XBee::Frame::RemoteCommandRequest.new(at_param_name, remote_address, remote_network_address, frame_id, nil, at_param_unpack_string)
115
+ puts "Sending ... [#{at_command_frame._dump(self.api_mode.in_symbol).unpack("C*").join(", ")}]"
116
+ self.xbee_serialport.write(at_command_frame._dump(self.api_mode.in_symbol))
117
+ if self.transmission_mode == :SYNC
118
+ r = XBee::Frame.new(self.xbee_serialport, self.api_mode.in_symbol)
119
+ if r.kind_of?(XBee::Frame::RemoteCommandResponse) && r.status == :OK && r.frame_id == frame_id
120
+ if block_given?
121
+ yield r
122
+ else
123
+ at_param_unpack_string.nil? ? r.retrieved_value : r.retrieved_value.unpack(at_param_unpack_string).first
124
+ end
125
+ else
126
+ raise "Response did not indicate successful retrieval of that parameter: #{r.inspect}"
127
+ end
128
+ end
129
+ end
130
+
131
+ def set_remote_param(at_param_name, param_value, remote_address = 0x000000000000ffff, remote_network_address = 0xfffe, at_param_unpack_string = nil)
132
+ frame_id = self.next_frame_id
133
+ at_command_frame = XBee::Frame::RemoteCommandRequest.new(at_param_name, remote_address, remote_network_address, frame_id, param_value, at_param_unpack_string)
134
+ puts "Sending ... [#{at_command_frame._dump(self.api_mode.in_symbol).unpack("C*").join(", ")}]"
135
+ self.xbee_serialport.write(at_command_frame._dump(self.api_mode.in_symbol))
136
+ if self.transmission_mode == :SYNC
137
+ r = XBee::Frame.new(self.xbee_serialport, self.api_mode.in_symbol)
138
+ if r.kind_of?(XBee::Frame::RemoteCommandResponse) && r.status == :OK && r.frame_id == frame_id
139
+ if block_given?
140
+ yield r
141
+ else
142
+ at_param_unpack_string.nil? ? r.retrieved_value : r.retrieved_value.unpack(at_param_unpack_string).first
143
+ end
144
+ else
145
+ raise "Response did not indicate successful retrieval of that parameter: #{r.inspect}"
146
+ end
147
+ end
148
+ end
149
+
150
+ ##
151
+ # Association Indication. Read information regarding last node join request:
152
+ # * 0x00 - Successful completion - Coordinator started or Router/End Device found and joined with a parent.
153
+ # * 0x21 - Scan found no PANs
154
+ # * 0x22 - Scan found no valid PANs based on current SC and ID settings
155
+ # * 0x23 - Valid Coordinator or Routers found, but they are not allowing joining (NJ expired) 0x27 - Node Joining attempt failed
156
+ # * 0x2A - Coordinator Start attempt failed‘
157
+ # * 0xFF - Scanning for a Parent
158
+ def association_indication
159
+ @association_indication ||= get_param("AI","n")
160
+ if @association_indication == nil then @association_indication = 0 end
161
+ end
162
+
163
+ ##
164
+ # Retrieve XBee firmware version
165
+ def fw_rev
166
+ @fw_rev ||= get_param("VR","n")
167
+ end
168
+
169
+ ##
170
+ # Retrieve XBee hardware version
171
+ def hw_rev
172
+ @hw_rev ||= get_param("HV","n")
173
+ end
174
+
175
+ ##
176
+ # Neighbor node discovery. Returns an array of hashes each element of the array contains a hash
177
+ # each hash contains keys: :MY, :SH, :SL, :DB, :NI
178
+ # representing addresses source address, Serial High, Serial Low, Received signal strength,
179
+ # node identifier respectively. Aan example of the results returned (hash as seen by pp):
180
+ #
181
+ # [{:NI=>" ", :MY=>"0", :SH=>"13A200", :SL=>"4008A642", :DB=>-24},
182
+ # {:NI=>" ", :MY=>"0", :SH=>"13A200", :SL=>"4008A697", :DB=>-33},
183
+ # {:NI=>" ", :MY=>"0", :SH=>"13A200", :SL=>"40085AD5", :DB=>-52}]
184
+ #
185
+ # Signal strength (:DB) is reported in units of -dBM.
186
+ def neighbors
187
+ frame_id = self.next_frame_id
188
+ # neighbors often takes more than 1000ms to return data
189
+ node_discover_cmd = XBee::Frame::ATCommand.new("ND",frame_id,nil)
190
+ #puts "Node discover command dump: #{node_discover_cmd._dump(self.api_mode.in_symbol).unpack("C*").join(", ")}"
191
+ tmp = @xbee_serialport.read_timeout
192
+ @xbee_serialport.read_timeout = Integer(self.node_discover_timeout.in_seconds * 1050)
193
+ @xbee_serialport.write(node_discover_cmd._dump(self.api_mode.in_symbol))
194
+ responses = []
195
+ #read_thread = Thread.new do
196
+ begin
197
+ loop do
198
+ r = XBee::Frame.new(self.xbee_serialport, self.api_mode.in_symbol)
199
+ # puts "Got a response! Frame ID: #{r.frame_id}, Command: #{r.at_command}, Status: #{r.status}, Value: #{r.retrieved_value}"
200
+ if r.kind_of?(XBee::Frame::ATCommandResponse) && r.status == :OK && r.frame_id == frame_id
201
+ if r.retrieved_value.empty?
202
+ # w00t - the module is telling us it's done with the discovery process.
203
+ break
204
+ else
205
+ responses << r
206
+ end
207
+ else
208
+ raise "Unexpected response to ATND command: #{r.inspect}"
209
+ end
210
+ end
211
+ rescue Exception => e
212
+ puts "Okay, must have finally timed out on the serial read: #{e}."
213
+ end
214
+ @xbee_serialport.read_timeout = tmp
215
+ responses.map do |r|
216
+ unpacked_fields = r.retrieved_value.unpack("nNNZ20nCCnn")
217
+ return_fields = [:SH, :SL, :NI, :PARENT_NETWORK_ADDRESS, :DEVICE_TYPE, :STATUS, :PROFILE_ID, :MANUFACTURER_ID]
218
+ unpacked_fields.shift #Throw out the junk at the start of the discover packet
219
+ return_fields.inject(Hash.new) do |return_hash, field_name|
220
+ return_hash[field_name] = unpacked_fields.shift
221
+ return_hash
222
+ end
223
+ end
224
+ end
225
+
226
+ ##
227
+ # Returns the low portion of the XBee device's current destination address
228
+ def destination_low
229
+ @destination_low ||= get_param("DL")
230
+ end
231
+
232
+ ##
233
+ # Sets the low portion of the XBee device's destination address
234
+ # Parameter range: 0 - 0xFFFFFFFF
235
+ def destination_low!(low_addr)
236
+ @xbee_serialport.write("ATDL#{low_addr}\r")
237
+ getresponse if self.transmission_mode == :SYNC
238
+ end
239
+
240
+ ##
241
+ # Returns the high portion of the XBee device's current destination address
242
+ def destination_high
243
+ @destination_high ||= get_param("DH")
244
+ end
245
+
246
+ ##
247
+ # Sets the high portion of the XBee device's current destination address
248
+ # Parameter range: 0 - 0xFFFFFFFF
249
+ def destination_high!(high_addr)
250
+ self.xbee_serialport.write("ATDH#{high_addr}\r")
251
+ getresponse if self.transmission_mode == :SYNC
252
+ end
253
+
254
+ ##
255
+ # Returns the low portion of the XBee device's serial number. this value is factory set.
256
+ def serial_num_low
257
+ @serial_low ||= get_param("SL","N")
258
+ end
259
+
260
+ ##
261
+ # Returns the high portion of the XBee device's serial number. this value is factory set.
262
+ def serial_num_high
263
+ @serial_high ||= get_param("SH","N")
264
+ end
265
+
266
+ ##
267
+ # Returns the complete serialnumber of XBee device by quering the high and low parts.
268
+ def serial_num
269
+ self.serial_num_high() << 32 | self.serial_num_low
270
+ end
271
+
272
+ ##
273
+ # returns the channel number of the XBee device. this value, along with the PAN ID,
274
+ # and MY address determines the addressability of the device and what it can listen to
275
+ def channel
276
+ # channel often takes more than 1000ms to return data
277
+ tmp = @xbee_serialport.read_timeout
278
+ @xbee_serialport.read_timeout = read_timeout(:long)
279
+ @xbee_serialport.write("ATCH\r")
280
+ if self.tranmission_mode == :SYNC
281
+ response = getresponse
282
+ @xbee_serialport.read_timeout = tmp
283
+ response.strip.chomp
284
+ end
285
+ end
286
+
287
+ ##
288
+ # sets the channel number of the device. The valid channel numbers are those of the 802.15.4 standard.
289
+ def channel!(new_channel)
290
+ # channel takes more than 1000ms to return data
291
+ tmp = @xbee_serialport.read_timeout
292
+ @xbee_serialport.read_timeout = read_timeout(:long)
293
+ @xbee_serialport.write("ATCH#{new_channel}\r")
294
+ if self.transmission_mode == :SYNC
295
+ response = getresponse
296
+ @xbee_serialport.read_timeout = tmp
297
+ response.strip.chomp
298
+ end
299
+ end
300
+
301
+ ##
302
+ # returns the node ID of the device. Node ID is typically a human-meaningful name
303
+ # to give to the XBee device, much like a hostname.
304
+ def node_id
305
+ @node_id ||= get_param("NI")
306
+ end
307
+
308
+ ##
309
+ # sets the node ID to a user-definable text string to make it easier to
310
+ # identify the device with "human" names. This node id is reported to
311
+ # neighboring XBees so consider it "public".
312
+ def node_id!(new_id)
313
+ tmp = @xbee_serialport.read_timeout
314
+ @xbee_serialport.read_timeout = read_timeout(:long)
315
+ @xbee_serialport.write("ATNI#{new_id}\r")
316
+ if self.transmission_mode == :SYNC
317
+ response = getresponse
318
+ @xbee_serialport.read_timeout = tmp
319
+ if ( response.nil? )
320
+ return ""
321
+ else
322
+ response.strip.chomp
323
+ end
324
+ end
325
+ end
326
+
327
+ ##
328
+ # returns the PAN ID of the device. PAN ID is one of the 3 main identifiers used to
329
+ # communicate with the device from other XBees. All XBees which are meant to communicate
330
+ # must have the same PAN ID and channel number. The 3rd identifier is the address of the
331
+ # device itself represented by its serial number (High and Low) and/or it's 16-bit MY
332
+ # source address.
333
+ def pan_id
334
+ @pan_id ||= get_param("ID").unpack("n")
335
+ end
336
+
337
+ ##
338
+ # sets the PAN ID of the device. Modules must have the same PAN ID in order to communicate
339
+ # with each other. The PAN ID value can range from 0 - 0xffff. The default from the factory
340
+ # is set to 0x3332.
341
+ def pan_id!(new_id)
342
+ @xbee_serialport.write("ATID#{new_id}\r")
343
+ getresponse if self.transmission_mode == :SYNC
344
+ end
345
+
346
+ ##
347
+ # returns the signal strength in dBm units of the last received packet. Expect a negative integer
348
+ # or 0 to be returned. If the XBee device has not received any neighboring packet data, the signal strength
349
+ # value will be 0
350
+ def received_signal_strength
351
+ -(get_param("DB").hex)
352
+ end
353
+
354
+ ##
355
+ # retrieves the baud rate of the device. Generally, this will be the same as the
356
+ # rate you're currently using to talk to the device unless you've changed the device's
357
+ # baud rate and are still in the AT command mode and/or have not exited command mode explicitly for
358
+ # the new baud rate to take effect.
359
+ def baud
360
+ @xbee_serialport.write("ATBD\r")
361
+ baudcode = getresponse
362
+ @baudcodes.index( baudcode.to_i )
363
+ end
364
+
365
+ ##
366
+ # sets the given baud rate into the XBee device. The baud change will not take
367
+ # effect until the AT command mode times out or the exit command mode command is given.
368
+ # acceptable baud rates are: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
369
+ def baud!( baud_rate )
370
+ @xbee_serialport.write("ATBD#{@baudcodes[baud_rate]}\r")
371
+ getresponse if self.transmission_mode == :SYNC
372
+ end
373
+
374
+ ##
375
+ # returns the parity of the device as represented by a symbol:
376
+ # :None - for 8-bit none
377
+ # :Even - for 8-bit even
378
+ # :Odd - for 8-bit odd
379
+ # :Mark - for 8-bit mark
380
+ # :Space - for 8-bit space
381
+ def parity
382
+ @xbee_serialport.write("ATNB\r")
383
+ if self.transmission_mode == :SYNC
384
+ response = getresponse().strip.chomp
385
+ @paritycodes.index( response.to_i )
386
+ end
387
+ end
388
+
389
+ ##
390
+ # sets the parity of the device to one represented by a symbol contained in the parity_type parameter
391
+ # :None - for 8-bit none
392
+ # :Even - for 8-bit even
393
+ # :Odd - for 8-bit odd
394
+ # :Mark - for 8-bit mark
395
+ # :Space - for 8-bit space
396
+ def parity!( parity_type )
397
+ # validate symbol before writing parity param
398
+ if !@paritycodes.include?(parity_type)
399
+ return false
400
+ end
401
+ @xbee_serialport.write("ATNB#{@paritycodes[parity_type]}\r")
402
+ getresponse if self.transmission_mode == :SYNC
403
+ end
404
+
405
+ ##
406
+ # reads an i/o port configuration on the XBee for analog to digital or digital input or output (GPIO)
407
+ # this method returns an I/O type symbol of:
408
+ #
409
+ # :Disabled
410
+ # :ADC
411
+ # :DI
412
+ # :DO_Low
413
+ # :DO_High
414
+ # :Associated_Indicator
415
+ # :RTS
416
+ # :CTS
417
+ # :RS485_Low
418
+ # :RS485_High
419
+ #
420
+ # Not all DIO ports are capable of every configuration listed above. This method will properly translate
421
+ # the XBee's response value to the symbol above when the same value has different meanings from port to port.
422
+ #
423
+ # The port parameter may be any symbol :D0 through :D8 representing the 8 I/O ports on an XBee
424
+ def dio( port )
425
+ at = "AT#{port.to_s}\r"
426
+ @xbee_serialport.write( at )
427
+ if self.transmission_mode == :SYNC
428
+ response = getresponse.to_i
429
+
430
+ if response == 1 # the value of 1 is overloaded based on port number
431
+ case port
432
+ when :D5
433
+ return :Associated_Indicator
434
+ when :D6
435
+ return :RTS
436
+ when :D7
437
+ return :CTS
438
+ end
439
+ else
440
+ @iotypes.index(response)
441
+ end
442
+ end
443
+ end
444
+
445
+ ##
446
+ # configures an i/o port on the XBee for analog to digital or digital input or output (GPIO)
447
+ #
448
+ # port parameter valid values are the symbols :D0 through :D8
449
+ #
450
+ # iotype parameter valid values are symbols:
451
+ # :Disabled
452
+ # :ADC
453
+ # :DI
454
+ # :DO_Low
455
+ # :DO_High
456
+ # :Associated_Indicator
457
+ # :RTS
458
+ # :CTS
459
+ # :RS485_Low
460
+ # :RS485_High
461
+ #
462
+ # note: not all iotypes are compatible with every port type, see the XBee manual for exceptions and semantics
463
+ #
464
+ # note: it is critical you have upgraded firmware in your XBee or DIO ports 0-4 cannot be read
465
+ # (ie: ATD0 will return ERROR - this is an XBee firmware bug that's fixed in revs later than 1083)
466
+ #
467
+ # note: tested with rev 10CD, fails with rev 1083
468
+ def dio!( port, iotype )
469
+ at = "AT#{port.to_s}#{@iotypes[iotype]}\r"
470
+ @xbee_serialport.write( at )
471
+ getresponse if self.transmission_mode == :SYNC
472
+ end
473
+
474
+ ##
475
+ # reads the bitfield values for change detect monitoring. returns a bitmask indicating
476
+ # which DIO lines, 0-7 are enabled or disabled for change detect monitoring
477
+ def dio_change_detect
478
+ @xbee_serialport.write("ATIC\r")
479
+ getresponse if self.transmission_mode == :SYNC
480
+ end
481
+
482
+ ##
483
+ # sets the bitfield values for change detect monitoring. The hexbitmap parameter is a bitmap
484
+ # which enables or disables the change detect monitoring for any of the DIO ports 0-7
485
+ def dio_change_detect!( hexbitmap )
486
+ @xbee_serialport.write("ATIC#{hexbitmask}\r")
487
+ getresponse if self.transmission_mode == :SYNC
488
+ end
489
+
490
+ ##
491
+ # Sets the digital output levels of any DIO lines which were configured for output using the dio! method.
492
+ # The parameter, hexbitmap, is a hex value which represents the 8-bit bitmap of the i/o lines on the
493
+ # XBee.
494
+ def io_output!( hexbitmap )
495
+ @xbee_serialport.write("ATIO#{hexbitmap}\r")
496
+ getresponse if self.transmission_mode == :SYNC
497
+ end
498
+
499
+ ##
500
+ # Forces a sampling of all DIO pins configured for input via dio!
501
+ # Returns a hash with the following key/value pairs:
502
+ # :NUM => number of samples
503
+ # :CM => channel mask
504
+ # :DIO => dio data if DIO lines are enabled
505
+ # :ADCn => adc sample data (one for each ADC channel enabled)
506
+ def io_input
507
+
508
+ tmp = @xbee_serialport.read_timeout
509
+ @xbee_serialport.read_timeout = read_timeout(:long)
510
+
511
+ @xbee_serialport.write("ATIS\r")
512
+ if self.transmission_mode == :SYNC
513
+ response = getresponse
514
+ linenum = 1
515
+ adc_sample = 1
516
+ samples = Hash.new
517
+
518
+ if response.match("ERROR")
519
+ samples[:ERROR] = "ERROR"
520
+ return samples
521
+ end
522
+
523
+ # otherwise parse input data
524
+ response.each_line do | line |
525
+ case linenum
526
+ when 1
527
+ samples[:NUM] = line.to_i
528
+ when 2
529
+ samples[:CM] = line.strip.chomp
530
+ when 3
531
+ samples[:DIO] = line.strip.chomp
532
+ else
533
+ sample = line.strip.chomp
534
+ if ( !sample.nil? && sample.size > 0 )
535
+ samples["ADC#{adc_sample}".to_sym] = line.strip.chomp
536
+ adc_sample += 1
537
+ end
538
+ end
539
+
540
+ linenum += 1
541
+ end
542
+
543
+ @xbee_serialport.read_timeout = tmp
544
+ samples
545
+ end
546
+ end
547
+
548
+ ##
549
+ # writes the current XBee configuration to the XBee device's flash. There
550
+ # is no undo for this operation
551
+ def save!
552
+ @xbee_serialport.write("ATWR\r")
553
+ getresponse if self.transmission_mode == :SYNC
554
+ end
555
+
556
+ ##
557
+ # Resets the XBee module through software and simulates a power off/on. Any configuration
558
+ # changes that have not been saved with the save! method will be lost during reset.
559
+ #
560
+ # The module responds immediately with "OK" then performs a reset ~2 seconds later.
561
+ # The reset is a required when the module's SC or ID has been changes to take into affect.
562
+ def reset!
563
+ @xbee_serialport.write("ATFR\r")
564
+ end
565
+
566
+ ##
567
+ # Performs a network reset on one or more modules within a PAN. The module responds
568
+ # immediately with an "OK" and then restarts the network. All network configuration
569
+ # and routing information is lost if not saved.
570
+ #
571
+ # Parameter range: 0-1
572
+ # * 0: Resets network layer parameters on the node issuing the command.
573
+ # * 1: Sends broadcast transmission to reset network layer parameters on all nodes in the PAN.
574
+ def network_reset!(reset_range)
575
+ if reset_range == 0
576
+ @xbee_serialport.write("ATNR0\r")
577
+ elsif reset_range == 1 then
578
+ @xbee_serialport.write("ATNR1\r")
579
+ else
580
+ #### DEBUG ####
581
+ if $DEBUG then
582
+ puts "Invalid parameter provided: #{reset_range}"
583
+ end
584
+ #### DEBUG ####
585
+ end
586
+ end
587
+
588
+ ##
589
+ # Restores all the module parameters to factory defaults
590
+ # Restore (RE) command does not reset the ID parameter.
591
+ def restore!
592
+ @xbee_serialport.write("ATRE\r")
593
+ end
594
+
595
+ ##
596
+ # just a straight pass through of data to the XBee. This can be used to send
597
+ # data when not in AT command mode, or if you want to control the XBee with raw
598
+ # commands, you can send them this way.
599
+ def send!(message)
600
+ @xbee_serialport.write( message )
601
+ end
602
+
603
+ ##
604
+ # exits the AT command mode - all changed parameters will take effect such as baud rate changes
605
+ # after the exit is complete. exit_command_mode does not permanently save the parameter changes
606
+ # when it exits AT command mode. In order to permanently change parameters, use the save! method
607
+ def exit_command_mode
608
+ @xbee_serialport.write("ATCN\r")
609
+ end
610
+
611
+ ##
612
+ # returns the version of this class
613
+ def version
614
+ VERSION
615
+ end
616
+
617
+ ##
618
+ # returns results from the XBee
619
+ def getresponse
620
+ XBee::Frame.new(self.xbee_serialport, self.api_mode.in_symbol)
621
+ end
622
+
623
+ end
624
+
625
+ class Series1APIModeInterface < BaseAPIModeInterface
626
+ ##
627
+ # returns the source address of the XBee device - the MY address value
628
+ def my_src_address
629
+ @my_src_address ||= get_param("MY")
630
+ end
631
+ end # class Series1APIModeInterface
632
+
633
+ class Series2APIModeInterface < BaseAPIModeInterface
634
+ ##
635
+ # Initiating the application firmware OTA upgrade for Programmable XBee modules
636
+ def init_ota_upgrade(password = nil, remote_address = 0x000000000000ffff, remote_network_address = 0xfffe)
637
+ frame_id = self.next_frame_id
638
+ command_frame = XBee::Frame::ExplicitAddressingCommand.new(frame_id, remote_address, remote_network_address, 0xE8, 0xE8, 0x1000, 0xC105, 0x00, 0x00, password)
639
+ self.xbee_serialport.write(command_frame._dump(self.api_mode.in_symbol))
640
+ end
641
+ end # class Series2APIModeInterface
642
+ end