xbee 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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