ant-wireless 0.1.0 → 0.4.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,197 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+ # vim: set nosta noet ts=4 sw=4:
4
+
5
+ require 'ant' unless defined?( Ant )
6
+
7
+ # Ant::BitVector -- a convenience class for manipulating and
8
+ # comparing bit vectors.
9
+ #
10
+ # This is a slightly-modified version of the same utility in StaticCling.
11
+ #
12
+ # == Synopsis
13
+ #
14
+ # require 'ant/bitvector'
15
+ #
16
+ # vector = Ant::BitVector.new
17
+ #
18
+ # vector.on( 4 ) # => 16
19
+ # vector.on( 12 ) # => 4112
20
+ # vector.toggle( 4 ) # => 4096
21
+ # vector.on?( 4 ) # => false
22
+ # vector.size # => 13
23
+ # vector.to_hex # => 0x1000
24
+ #
25
+ # vector2 = Ant::BitVector.new( 5 )
26
+ # vector > vector2 # => true
27
+ #
28
+ # vector2.each_with_index do |bit, i|
29
+ # puts "Bit %d is %s" % [ i + 1, bit.zero? ? 'off' : 'on' ]
30
+ # end
31
+ #
32
+ # Bit 1 is on
33
+ # Bit 2 is off
34
+ # Bit 3 is on
35
+ #
36
+ # == Version
37
+ #
38
+ # $Id$
39
+ #
40
+ # == Author
41
+ #
42
+ # * Mahlon E. Smith <mahlon@martini.nu>
43
+ #
44
+ # == License
45
+ #
46
+ # Copyright (c) 2000-2013, Mahlon E. Smith <mahlon@martini.nu>
47
+ #
48
+ # All rights reserved.
49
+ #
50
+ # Redistribution and use in source and binary forms, with or without
51
+ # modification, are permitted provided that the following conditions are met:
52
+ #
53
+ # * Redistributions of source code must retain the above copyright notice,
54
+ # this list of conditions and the following disclaimer.
55
+ #
56
+ # * Redistributions in binary form must reproduce the above copyright
57
+ # notice, this list of conditions and the following disclaimer in the
58
+ # documentation and/or other materials provided with the distribution.
59
+ #
60
+ # * Neither the name of the author, nor the names of contributors may be
61
+ # used to endorse or promote products derived from this software without
62
+ # specific prior written permission.
63
+ #
64
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
65
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
66
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
67
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
68
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
69
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
70
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
71
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
72
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
73
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
74
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
75
+ #
76
+ class Ant::BitVector
77
+ include Enumerable,
78
+ Comparable
79
+
80
+ ### Create a new bit vector object, optionally from a pre-existing
81
+ ### +init+ number (Any number that ruby supports natively should be
82
+ ### fine -- 0b, 0x, or decimal.)
83
+ def initialize( init=0 )
84
+ unless init.respond_to?( :to_i )
85
+ raise ArgumentError, "I don't know what to do with a %s object." % [ init.class.name ]
86
+ end
87
+
88
+ @bv = init.to_i
89
+ end
90
+
91
+
92
+ ######
93
+ public
94
+ ######
95
+
96
+ # let any additional methods fall through to Fixnum/Bignum objs,
97
+ # and return new vector objects. This allows for doing bitwise math
98
+ # or simple addition/subtraction on two BitVector objects.
99
+ %w{ % & * ** + - / << >> ^ | ~ }.each do |op|
100
+ define_method( op.to_sym ) do |arg|
101
+ res = @bv.send( op.to_sym, arg.bv )
102
+ return self.class.new( res )
103
+ end
104
+ end
105
+
106
+
107
+ ##
108
+ # Allow external access to the underlying Fixnum/Bignum
109
+ attr_reader :bv
110
+
111
+
112
+ ### Return the bit vector as a decimal.
113
+ def to_i
114
+ return @bv
115
+ end
116
+ alias_method :to_int, :to_i
117
+ alias_method :to_dec, :to_i
118
+
119
+
120
+ ### Return the bit vector as a binary string.
121
+ def to_bin
122
+ return "0b%s" % @bv.to_s(2)
123
+ end
124
+
125
+
126
+ ### Return the bit vector as a hexidecimal string.
127
+ def to_hex
128
+ return "0x%04x" % @bv
129
+ end
130
+
131
+
132
+ ### Return the length of the vector in bytes.
133
+ def size
134
+ return @bv.to_s(2).length
135
+ end
136
+
137
+
138
+ ### Switch a +bit+ on.
139
+ def on( bit )
140
+ @bv = @bv | ( 1 << bit )
141
+ end
142
+
143
+
144
+ ### Return boolean true if given +bit+ is currently on.
145
+ def on?( bit )
146
+ return @bv[ bit ].zero? ? false : true
147
+ end
148
+ alias_method :[], :on?
149
+
150
+
151
+ ### Switch a +bit+ off.
152
+ def off( bit )
153
+ @bv = @bv & ~( 1 << bit )
154
+ end
155
+
156
+
157
+ ### Return boolean true if given +bit+ is currently +off+.
158
+ def off?( bit )
159
+ return ! self.on?( bit )
160
+ end
161
+
162
+
163
+ ### Swap the current state of the given +bit+.
164
+ def toggle( bit )
165
+ @bv = @bv ^ ( 1 << bit )
166
+ end
167
+ alias_method :flip, :toggle
168
+
169
+
170
+ ### Set a +bit+ to +bool+ -- either true (on) or false (off).
171
+ ### Any value other than nil or false is treated as true.
172
+ ### This form also accepts ranges of bits, a la: vector[ 1..4 ] = true
173
+ def []=( bit, bool )
174
+ if bit.respond_to?( :each )
175
+ bit.each { |b| bool ? self.on( b ) : self.off( b ) }
176
+ else
177
+ bool ? self.on( bit ) : self.off( bit )
178
+ end
179
+ end
180
+
181
+
182
+ ### Yield each binary position, least significant +bit+ first.
183
+ def each
184
+ @bv.to_s(2).reverse.each_byte do |bit|
185
+ yield bit.chr.to_i
186
+ end
187
+ end
188
+
189
+
190
+ ### Comparision operator for Comparable mixin, fallthrough to
191
+ ### Fixnum/Bignum. Compares current state against +cmp+.
192
+ def <=>( cmp )
193
+ @bv <=> cmp.bv
194
+ end
195
+
196
+ end # class Ant::BitVector
197
+
@@ -13,8 +13,8 @@ require 'ant/mixins'
13
13
  # Refs:
14
14
  # * 9.5.6.1 Channel Response / Event (0x40) [ANT Message Protocol and Usage, Rev 5.1]
15
15
  module Ant::Channel::EventCallbacks
16
- extend Loggability
17
- include Ant::DataUtilities
16
+ extend Loggability,
17
+ Ant::DataUtilities
18
18
 
19
19
 
20
20
  # Mapping of response message IDs to handler methods
@@ -62,13 +62,9 @@ module Ant::Channel::EventCallbacks
62
62
  end
63
63
 
64
64
 
65
- ###############
66
- module_function
67
- ###############
68
-
69
65
  ### Default callback hook -- handles event callbacks.
70
66
  def handle_event_callback( channel_num, event_id, data )
71
- handler_method = HANDLER_METHODS[ event_id ] or
67
+ handler_method = Ant::Channel::EventCallbacks::HANDLER_METHODS[ event_id ] or
72
68
  raise "Unhandled channel event %p" % [ event_id ]
73
69
 
74
70
  if self.respond_to?( handler_method )
@@ -81,10 +77,10 @@ module Ant::Channel::EventCallbacks
81
77
 
82
78
  ### Handle an TX event.
83
79
  def on_event_tx( channel_num, data )
84
- # self.log.info "Broadcast message on channel %d was transmitted." % [ channel_num ]
85
- data = SecureRandom.bytes( 8 )
86
- self.log.info "Sending our own broadcast data: \n%s" % [ hexdump(data) ]
87
- self.send_broadcast_data( data )
80
+ channel = Ant::Channel.registry[ channel_num ]
81
+ self.log.debug "%p ready for transmission." % [ channel ]
82
+ ident = [ 1, 33 ].pack( "CC" )
83
+ channel.send_broadcast_data( ident )
88
84
  end
89
85
 
90
86
 
@@ -148,7 +144,7 @@ module Ant::Channel::EventCallbacks
148
144
  usDeviceNumber = data.bytes[10] | (data.bytes[11] << 8)
149
145
  ucDeviceType = data.bytes[12]
150
146
  ucTransmissionType = data.bytes[13]
151
- self.log.info "Got an acknowledge on Chan ID(%d/%d/%d)" %
147
+ self.log.debug "Got an acknowledge on Chan ID(%d/%d/%d)" %
152
148
  [usDeviceNumber, ucDeviceType, ucTransmissionType]
153
149
  end
154
150
 
@@ -162,7 +158,7 @@ module Ant::Channel::EventCallbacks
162
158
  usDeviceNumber = data.bytes[10] | (data.bytes[11] << 8)
163
159
  ucDeviceType = data.bytes[12]
164
160
  ucTransmissionType = data.bytes[13]
165
- self.log.info "Got a burst on Chan ID(%d/%d/%d)" %
161
+ self.log.debug "Got a burst on Chan ID(%d/%d/%d)" %
166
162
  [usDeviceNumber, ucDeviceType, ucTransmissionType]
167
163
  end
168
164
 
@@ -176,7 +172,7 @@ module Ant::Channel::EventCallbacks
176
172
  usDeviceNumber = data.bytes[10] | (data.bytes[11] << 8)
177
173
  ucDeviceType = data.bytes[12]
178
174
  ucTransmissionType = data.bytes[13]
179
- self.log.info "Got a broadcast on Chan ID(%d/%d/%d)" %
175
+ self.log.debug "Got a broadcast on Chan ID(%d/%d/%d)" %
180
176
  [usDeviceNumber, ucDeviceType, ucTransmissionType]
181
177
  end
182
178
 
@@ -185,7 +181,7 @@ module Ant::Channel::EventCallbacks
185
181
 
186
182
 
187
183
  def on_event_rx_acknowledged( channel_num, data )
188
- self.log.info "Acknowledged: Rx:\n%s" % [ hexdump(data[1..9]) ]
184
+ self.log.debug "Acknowledged: Rx [%d]:\n%s" % [ data.bytes[0], Ant::DataUtilities.hexdump(data[1..9]) ]
189
185
  end
190
186
 
191
187
 
@@ -193,12 +189,12 @@ module Ant::Channel::EventCallbacks
193
189
  channel = (data.bytes[0] & CHANNEL_NUMBER_MASK) >> 5
194
190
  sequence_num = data.bytes[0] & SEQUENCE_NUMBER_MASK
195
191
 
196
- self.log.info "Burst (0x%02x): Rx: %d:\n%s" % [ channel, sequence_num, hexdump(data[1..9]) ]
192
+ self.log.debug "Burst (0x%02x): Rx: %d:\n%s" % [ channel, sequence_num, Ant::DataUtilities.hexdump(data[1..9]) ]
197
193
  end
198
194
 
199
195
 
200
196
  def on_event_rx_broadcast( channel_num, data )
201
- self.log.info "Broadcast: Rx:\n%s" % [ hexdump(data[1..9]) ]
197
+ self.log.debug "Broadcast: Rx [%d]:\n%s" % [ data.bytes[0], Ant::DataUtilities.hexdump(data[1..9]) ]
202
198
  end
203
199
 
204
200
 
data/lib/ant/channel.rb CHANGED
@@ -9,6 +9,7 @@ require 'ant' unless defined?( Ant )
9
9
  class Ant::Channel
10
10
  extend Loggability
11
11
 
12
+
12
13
  # The default network number
13
14
  DEFAULT_NETWORK_NUMBER = 0
14
15
 
@@ -20,7 +21,8 @@ class Ant::Channel
20
21
  # Autoloads
21
22
  #
22
23
 
23
- autoload :EventCallbacks, 'ant/channel/event_callbacks'
24
+ require 'ant/channel/event_callbacks'
25
+ include Ant::Channel::EventCallbacks
24
26
 
25
27
 
26
28
  # Loggability API -- log to the Ant logger
@@ -44,23 +46,68 @@ class Ant::Channel
44
46
 
45
47
 
46
48
  ### Set up the given +mod+ as the handler module for channel events.
47
- def set_event_handlers( object=Ant::Channel::EventCallbacks )
49
+ def set_event_handlers( object=self )
48
50
  self.on_event( &object.method(:handle_event_callback) )
49
51
  end
50
52
 
51
53
 
54
+ ### Return the ANT channel ID if one has been assigned.
55
+ def channel_id
56
+ device_number = self.device_number or return nil
57
+ device_type = self.device_type & 0x7f
58
+ pairing_bit = self.device_type & 0x80
59
+ transmission_type = self.transmission_type
60
+
61
+ return "%d/%d/%d%s" % [
62
+ device_number,
63
+ device_type,
64
+ transmission_type,
65
+ pairing_bit.nonzero? ? '+' : '',
66
+ ]
67
+ end
68
+
69
+
70
+ ### Return a human-readable description of the channel type.
71
+ def channel_type_description
72
+ case self.channel_type
73
+ when Ant::PARAMETER_RX_NOT_TX
74
+ return :slave
75
+ when Ant::PARAMETER_TX_NOT_RX
76
+ return :master
77
+ when Ant::PARAMETER_SHARED_CHANNEL
78
+ return :shared
79
+ when Ant::PARAMETER_NO_TX_GUARD_BAND
80
+ return :no_tx_guard_band
81
+ when Ant::PARAMETER_ALWAYS_RX_WILD_CARD_SEARCH_ID
82
+ return :always_rx_wild_card_search_id
83
+ when Ant::PARAMETER_RX_ONLY
84
+ return :rx_only
85
+ else
86
+ return nil
87
+ end
88
+ end
89
+
90
+
91
+ ### Returns +true+ if the channel is not closed.
92
+ def open?
93
+ return !self.closed?
94
+ end
95
+
96
+
52
97
  ### Return a human-readable version of the object suitable for debugging.
53
98
  def inspect
54
- return "#<%p:%#x {%d} %#02x on network %d: %d%s>" % [
99
+ return "#<%p:%#x %s {%s} #%d @%dMHz on network %d%s>" % [
55
100
  self.class,
56
101
  self.object_id,
102
+ self.channel_type_description,
103
+ self.channel_id || '-',
57
104
  self.channel_number,
58
- self.channel_type,
105
+ self.rf_frequency + 2400,
59
106
  self.network_number,
60
- self.extended_options,
61
107
  self.closed? ? " (closed)" : "",
62
108
  ]
63
109
  end
64
110
 
65
111
  end # class Ant::Channel
66
112
 
113
+