xbee 1.0.2

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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +13 -0
  3. data/.gitignore +25 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +49 -0
  8. data/examples/check_and_set_destination_address.rb +161 -0
  9. data/examples/read_frames.rb +45 -0
  10. data/examples/response_parser_throughput.rb +35 -0
  11. data/lib/xbee.rb +5 -0
  12. data/lib/xbee/address.rb +23 -0
  13. data/lib/xbee/address_16.rb +39 -0
  14. data/lib/xbee/address_64.rb +40 -0
  15. data/lib/xbee/bytes.rb +21 -0
  16. data/lib/xbee/exceptions/exception.rb +9 -0
  17. data/lib/xbee/exceptions/frame_format_error.rb +9 -0
  18. data/lib/xbee/exceptions/unknown_frame_type.rb +9 -0
  19. data/lib/xbee/frames/addressed_frame.rb +27 -0
  20. data/lib/xbee/frames/at_command.rb +35 -0
  21. data/lib/xbee/frames/at_command_queue_parameter_value.rb +21 -0
  22. data/lib/xbee/frames/at_command_response.rb +31 -0
  23. data/lib/xbee/frames/create_source_route.rb +15 -0
  24. data/lib/xbee/frames/data/sample.rb +72 -0
  25. data/lib/xbee/frames/data_sample_rx_indicator.rb +51 -0
  26. data/lib/xbee/frames/explicit_addressing_command.rb +68 -0
  27. data/lib/xbee/frames/explicit_rx_indicator.rb +60 -0
  28. data/lib/xbee/frames/frame.rb +65 -0
  29. data/lib/xbee/frames/identified_frame.rb +24 -0
  30. data/lib/xbee/frames/many_to_one_route_request_indicator.rb +11 -0
  31. data/lib/xbee/frames/modem_status.rb +47 -0
  32. data/lib/xbee/frames/node_identification_indicator.rb +38 -0
  33. data/lib/xbee/frames/over_the_air_firmware_update_status.rb +28 -0
  34. data/lib/xbee/frames/receive_packet.rb +44 -0
  35. data/lib/xbee/frames/remote_at_command_request.rb +53 -0
  36. data/lib/xbee/frames/remote_at_command_response.rb +45 -0
  37. data/lib/xbee/frames/route_record_indicator.rb +28 -0
  38. data/lib/xbee/frames/transmit_request.rb +70 -0
  39. data/lib/xbee/frames/transmit_status.rb +63 -0
  40. data/lib/xbee/frames/unidentified_addressed_frame.rb +26 -0
  41. data/lib/xbee/frames/xbee_sensor_read_indicator.rb +50 -0
  42. data/lib/xbee/packet.rb +175 -0
  43. data/lib/xbee/version.rb +5 -0
  44. data/lib/xbee/xbee.rb +109 -0
  45. data/xbee.gemspec +40 -0
  46. metadata +245 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8610d87b16c2a9335c2ce72be4dc5a602aff5f10
4
+ data.tar.gz: 4844015c3481f1de20c56b61361b87d546ab5a78
5
+ SHA512:
6
+ metadata.gz: 509e9b13d5baddcae59ba5193763840aa88f0cd7e4212294bb85405ab4c9af5ca6b4f703263d36af06d2d4020d19e620dbb03808082cef22477a16b2ee786f5a
7
+ data.tar.gz: 0e3895e30803d0e1708a701ae823220118bd8ebd02fabc12474c2690fadc8eeef62064c942393173fd02b3303852aa2b2fa98dd491f1ca05d4aa17d2653caca9
@@ -0,0 +1,13 @@
1
+ # EditorConfig is awesome: http://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ # Unix-style newlines with a newline ending every file
7
+ [*]
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ indent_size = tab
11
+ indent_style = tab
12
+ #tab_width = 4
13
+ trim_trailing_whitespace = true
@@ -0,0 +1,25 @@
1
+ # IntelliJ
2
+ /.idea
3
+
4
+ *.gem
5
+ *.rbc
6
+ .bundle
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
21
+ *~
22
+
23
+
24
+ # Sublime
25
+ *.sublime-workspace
@@ -0,0 +1 @@
1
+ 2.4.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2012-2013 Dirk Grappendorf, www.grappendorf.net
4
+ Copyright (c) 2017 Aaron Ten Clay, https://aarontc.com
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ XBee
2
+ ====
3
+
4
+ A Ruby API for XBee ZigBee-RF-Modules
5
+ -------------------------------------
6
+
7
+ This gem is forked from the original XBee-Ruby gem. Because major API changes are being made a new name is appropriate.
8
+
9
+ See the `examples/` directory for some working examples with slightly more complexity than the samples below.
10
+
11
+ The `spec/` directory is left over from the forked gem, and will be converted to Minitest in the near future.
12
+
13
+ Example: Transmit a packet to another node
14
+ ------------------------------------------
15
+
16
+ xbee = XBee::XBee.new device_path: '/dev/ttyUSB0', rate: 115200
17
+ xbee.open
18
+ request = XBee::Frames::RemoteATCommandRequest.new
19
+ request.address64 = XBee::Address64.from_string '0013A232408BACE4'
20
+ request.at_command = 'NI'
21
+ request.id = 0x01
22
+ xbee.write_frame request
23
+ puts xbee.read_frame
24
+ xbee.close
25
+
26
+ Example: Receive packets
27
+ ------------------------
28
+
29
+ xbee = XBee::XBee.new port: '/dev/ttyUSB0', rate: 115200
30
+ xbee.open
31
+ loop do
32
+ frame = xbee.read_frame
33
+ puts "Frame received: #{frame.inspect}"
34
+ end
35
+
36
+ Contributing
37
+ ------------
38
+ All development happens via Git using the [Git Flow](http://nvie.com/posts/a-successful-git-branching-model/) branching model. The canonical source location is
39
+ [XBee Bitbucket](https://work.techtonium.com/bitbucket/projects/XBEE). This repository is automatically mirrored to [GitHub](https://github.com/IdleEngineers/xbee).
40
+
41
+ If you find a bug or have a feature request, please create an issue in the [XBee issue tracker](https://work.techtonium.com/jira/browse/XBEE).
42
+
43
+
44
+ License
45
+ -------
46
+
47
+ The XBee code is licensed under the the MIT License
48
+
49
+ You find the license in the attached LICENSE.txt file
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ require 'timeout'
4
+ require_relative '../lib/xbee'
5
+
6
+ class CheckAndSetDestinationAddress
7
+ def run
8
+ xbee = XBee::XBee.new device_path: '/dev/ttyUSB0', rate: 115200
9
+ xbee.open
10
+
11
+ # First get Identifier
12
+ request = XBee::Frames::RemoteATCommandRequest.new
13
+ request.address64 = XBee::Address64.from_string '0013A200408BACE4'
14
+ request.at_command = 'NI'
15
+ request.id = 0x01
16
+ puts "Transmitting frame: #{request.inspect}"
17
+ xbee.write_frame request
18
+ Timeout.timeout(10) do
19
+ loop do
20
+ response = xbee.read_frame
21
+ if response.is_a?(XBee::Frames::RemoteATCommandResponse)
22
+ if response.address64 == request.address64
23
+ @ni = response.data.pack('C*')
24
+ puts format('Got node identity from %s: %s', request.address64.to_s, response.data.pack('C*'))
25
+ break
26
+ else
27
+ puts format('Got response from wrong node %s: %s', request.address64.to_s, response.data.pack('C*'))
28
+ end
29
+ end
30
+ puts "Got response we don't need: #{response}"
31
+ end
32
+ end
33
+
34
+
35
+ # Now get destination address
36
+ request = XBee::Frames::RemoteATCommandRequest.new
37
+ request.address64 = XBee::Address64.from_string '0013A200408BACE4'
38
+ request.at_command = 'DH'
39
+ request.id = 0x02
40
+ puts "Transmitting frame: #{request.inspect}"
41
+ xbee.write_frame request
42
+ Timeout.timeout(10) do
43
+ loop do
44
+ response = xbee.read_frame
45
+ if response.is_a?(XBee::Frames::RemoteATCommandResponse)
46
+ if response.address64 == request.address64
47
+ puts format('Got DH from %s: %s', request.address64.to_s, response.data)
48
+ @dh = response.data
49
+ break
50
+ else
51
+ puts format('Got response from wrong node %s: %s', request.address64.to_s, response.data.pack('C*'))
52
+ end
53
+ end
54
+ puts "Got response we don't need: #{response}"
55
+ end
56
+ end
57
+
58
+ request = XBee::Frames::RemoteATCommandRequest.new
59
+ request.address64 = XBee::Address64.from_string '0013A200408BACE4'
60
+ request.at_command = 'DL'
61
+ request.id = 0x03
62
+ puts "Transmitting frame: #{request.inspect}"
63
+ xbee.write_frame request
64
+ Timeout.timeout(10) do
65
+ loop do
66
+ response = xbee.read_frame
67
+ if response.is_a?(XBee::Frames::RemoteATCommandResponse)
68
+ if response.address64 == request.address64
69
+ puts format('Got DL from %s: %s', request.address64.to_s, response.data)
70
+ @dl = response.data
71
+ break
72
+ else
73
+ puts format('Got response from wrong node %s: %s', request.address64.to_s, response.data.pack('C*'))
74
+ end
75
+ end
76
+ puts "Got response we don't need: #{response}"
77
+ end
78
+ end
79
+
80
+ @dest = XBee::Address64.new *@dh, *@dl
81
+ puts "Node #{@ni.inspect} Destination: #{@dest}"
82
+ # @target = XBee::Address64::COORDINATOR
83
+ @target = XBee::Address64.from_string '0013A20040B79952'
84
+
85
+ unless @dest == @target
86
+ puts "Updating destination address to be #{@target}..."
87
+ request = XBee::Frames::RemoteATCommandRequest.new
88
+ request.address64 = XBee::Address64.from_string '0013A200408BACE4'
89
+ request.at_command = 'DH'
90
+ request.command_parameter = @target.to_a[0..3]
91
+ request.id = 0x04
92
+ puts "Transmitting frame: #{request.inspect}"
93
+ xbee.write_frame request
94
+ Timeout.timeout(10) do
95
+ loop do
96
+ response = xbee.read_frame
97
+ if response.is_a?(XBee::Frames::RemoteATCommandResponse)
98
+ if response.address64 == request.address64
99
+ puts format('Got DH from %s: %s', request.address64.to_s, response.data)
100
+ @dl = response.data
101
+ break
102
+ else
103
+ puts format('Got response from wrong node %s: %s', request.address64.to_s, response.data.pack('C*'))
104
+ end
105
+ end
106
+ puts "Got response we don't need: #{response}"
107
+ end
108
+ end
109
+
110
+ request = XBee::Frames::RemoteATCommandRequest.new
111
+ request.address64 = XBee::Address64.from_string '0013A200408BACE4'
112
+ request.at_command = 'DL'
113
+ request.command_parameter = @target.to_a[4..7]
114
+ request.id = 0x05
115
+ puts "Transmitting frame: #{request.inspect}"
116
+ xbee.write_frame request
117
+ Timeout.timeout(10) do
118
+ loop do
119
+ response = xbee.read_frame
120
+ if response.is_a?(XBee::Frames::RemoteATCommandResponse)
121
+ if response.address64 == request.address64
122
+ puts format('Got DL from %s: %s', request.address64.to_s, response.data)
123
+ @dl = response.data
124
+ break
125
+ else
126
+ puts format('Got response from wrong node %s: %s', request.address64.to_s, response.data.pack('C*'))
127
+ end
128
+ end
129
+ puts "Got response we don't need: #{response}"
130
+ end
131
+ end
132
+
133
+ request = XBee::Frames::RemoteATCommandRequest.new
134
+ request.address64 = XBee::Address64.from_string '0013A200408BACE4'
135
+ request.at_command = 'AC'
136
+ request.id = 0x06
137
+ puts "Transmitting frame: #{request.inspect}"
138
+ xbee.write_frame request
139
+ Timeout.timeout(10) do
140
+ loop do
141
+ response = xbee.read_frame
142
+ if response.is_a?(XBee::Frames::RemoteATCommandResponse)
143
+ if response.address64 == request.address64
144
+ puts format('Got AC from %s: %s', request.address64.to_s, response.data)
145
+ @dl = response.data
146
+ break
147
+ else
148
+ puts format('Got response from wrong node %s: %s', request.address64.to_s, response.data.pack('C*'))
149
+ end
150
+ end
151
+ puts "Got response we don't need: #{response}"
152
+ end
153
+ end
154
+ end
155
+
156
+ ensure
157
+ xbee.close
158
+ end
159
+ end
160
+
161
+ CheckAndSetDestinationAddress.new.run if $0 == __FILE__
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+ require 'bundler/setup'
5
+ require 'semantic_logger'
6
+ require 'trollop'
7
+
8
+ @options = Trollop.options do
9
+ opt :device, 'Path to serial device', default: '/dev/ttyUSB0', type: :string
10
+ opt :baud, 'Baud rate for XBee radio', default: 115200, type: :integer
11
+ opt :log_path, 'Path for log file', default: nil, type: :string
12
+ opt :log_level, 'Logging level - trace, debug, info, warn, error, fatal', default: 'debug', type: :string, callback: lambda { |s| raise Trollop::CommandlineError, 'Invalid logging level specified' unless SemanticLogger::LEVELS.include? s.to_sym}
13
+ end
14
+
15
+ SemanticLogger.default_level = @options.log_level.to_sym
16
+ SemanticLogger.add_appender file_name: @options.log_path, formatter: :color if @options.log_path
17
+ SemanticLogger.add_appender io: $stdout, formatter: :color
18
+
19
+
20
+ require 'xbee'
21
+
22
+ class ReadFrames
23
+ include SemanticLogger::Loggable
24
+
25
+
26
+ def initialize(device_path: @options.device, rate: @options.baud)
27
+ @device_path = device_path
28
+ @rate = rate
29
+ end
30
+
31
+
32
+ def run
33
+ xbee = XBee::XBee.new device_path: @device_path, rate: @rate
34
+ xbee.open
35
+ loop do
36
+ frame = xbee.read_frame
37
+ logger.info 'Frame received.', frame: frame
38
+ end
39
+ end
40
+ end
41
+
42
+ if $0 == __FILE__
43
+ reader = ReadFrames.new device_path: @options.device, rate: @options.baud
44
+ reader.run
45
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/xbee'
4
+
5
+ class FakeIO
6
+ def initialize
7
+ @queue = Queue.new
8
+ end
9
+
10
+ def readbyte
11
+ if @queue.empty?
12
+ load_queue
13
+ end
14
+ @queue.pop
15
+ end
16
+
17
+ def load_queue
18
+ [0x7e, 0x00, 0x07, 0x8b, 0x02, 0x79, 0x38, 0x00, 0x00, 0x00, 0xc1].each do |b|
19
+ @queue.push b
20
+ end
21
+ end
22
+ end
23
+
24
+ xbee = XBee::XBee.new io: FakeIO.new
25
+ xbee.open
26
+ num_reads = 0
27
+ start_time = Time.now.to_f
28
+ end_time = start_time + 10
29
+ puts 'Reading responses from a faked serial connection for 10 seconds'
30
+ while Time.now.to_f < end_time
31
+ xbee.read_frame
32
+ num_reads += 1
33
+ end
34
+ puts 'Done'
35
+ puts "#{num_reads / 10.0} per second"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ require 'serialport'
3
+
4
+ require_relative 'xbee/version'
5
+ require_relative 'xbee/xbee'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XBee
4
+ class Address
5
+ include Comparable
6
+
7
+
8
+ def <=>(other)
9
+ to_a <=> other.to_a
10
+ end
11
+
12
+
13
+ def ==(other)
14
+ to_a == other.to_a
15
+ end
16
+
17
+
18
+ def to_a
19
+ @bytes
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'address'
3
+
4
+ module XBee
5
+ class Address16 < Address
6
+ def initialize(msb, lsb)
7
+ @bytes = [msb, lsb]
8
+ end
9
+
10
+
11
+ class << self
12
+ def from_string(string)
13
+ if (matcher = /^(\h\h)[^\h]*(\h\h)$/.match(string))
14
+ new *(matcher[1..2].map &:hex)
15
+ else
16
+ raise ArgumentError, "#{string} is not a valid 16-bit address string"
17
+ end
18
+ end
19
+
20
+
21
+ def from_array(array)
22
+ if array.length == 2 && array.all? { |x| (0..255).cover? x }
23
+ new *array
24
+ else
25
+ raise ArgumentError, "#{array.inspect} is not a valid 16-bit address array"
26
+ end
27
+ end
28
+ end
29
+
30
+
31
+ def to_s
32
+ '%02x%02x' % @bytes
33
+ end
34
+
35
+
36
+ BROADCAST = new(0xff, 0xfe).freeze
37
+ COORDINATOR = new(0x00, 0x00).freeze
38
+ end
39
+ end