ruxbee 0.1.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.
@@ -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