ant-wireless 0.1.0.pre.20210617213631
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.
- checksums.yaml +7 -0
- data/History.md +5 -0
- data/LICENSE.txt +20 -0
- data/README.md +79 -0
- data/ext/ant_ext/ant_ext.c +791 -0
- data/ext/ant_ext/ant_ext.h +101 -0
- data/ext/ant_ext/antdefines.h +355 -0
- data/ext/ant_ext/antmessage.h +445 -0
- data/ext/ant_ext/build_version.h +18 -0
- data/ext/ant_ext/callbacks.c +233 -0
- data/ext/ant_ext/channel.c +524 -0
- data/ext/ant_ext/defines.h +40 -0
- data/ext/ant_ext/extconf.rb +22 -0
- data/ext/ant_ext/message.c +377 -0
- data/ext/ant_ext/types.h +202 -0
- data/ext/ant_ext/version.h +41 -0
- data/lib/ant.rb +138 -0
- data/lib/ant/channel.rb +66 -0
- data/lib/ant/channel/event_callbacks.rb +207 -0
- data/lib/ant/message.rb +10 -0
- data/lib/ant/mixins.rb +34 -0
- data/lib/ant/response_callbacks.rb +528 -0
- data/lib/ant/wireless.rb +5 -0
- data/spec/ant_spec.rb +88 -0
- data/spec/spec_helper.rb +37 -0
- metadata +131 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
/*
|
2
|
+
This software is subject to the license described in the License.txt file
|
3
|
+
included with this software distribution. You may not use this file except
|
4
|
+
in compliance with this license.
|
5
|
+
|
6
|
+
Copyright (c) Dynastream Innovations Inc. 2016
|
7
|
+
All rights reserved.
|
8
|
+
*/
|
9
|
+
#if !defined(__VERSION_H__)
|
10
|
+
#define __VERSION_H__
|
11
|
+
|
12
|
+
#include "build_version.h"
|
13
|
+
|
14
|
+
#ifdef _UNICODE
|
15
|
+
#define _T(x) L ## x
|
16
|
+
#else
|
17
|
+
#define _T(x) x
|
18
|
+
#endif
|
19
|
+
|
20
|
+
#define STRINGIZE2(s) _T(#s)
|
21
|
+
#define STRINGIZE(s) STRINGIZE2(s)
|
22
|
+
|
23
|
+
#define VER_FILE_DESCRIPTION_STR _T(PRODUCT_STRING)
|
24
|
+
#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
|
25
|
+
_T(".") STRINGIZE(VERSION_MINOR)
|
26
|
+
|
27
|
+
// Version Information
|
28
|
+
#define SW_VER_PPP "ALU"
|
29
|
+
#define SW_VER_NUM VER_FILE_VERSION_STR
|
30
|
+
#if !defined(EXT_FUNCTIONALITY)
|
31
|
+
#define SW_VER_DEV "00"
|
32
|
+
#define SW_VER_SUFFIX ""
|
33
|
+
#else
|
34
|
+
#define SW_VER_DEV "0001" //Add two digits which are the ext lib version of the corresponding non-extended version
|
35
|
+
#define SW_VER_SUFFIX "_BAXEXT"
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#define SW_VER SW_VER_PPP SW_VER_NUM SW_VER_DEV SW_VER_SUFFIX
|
39
|
+
#define SW_DESCR ""
|
40
|
+
|
41
|
+
#endif // !defined(CONFIG_H)
|
data/lib/ant.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'loggability'
|
5
|
+
|
6
|
+
require_relative 'ant_ext'
|
7
|
+
|
8
|
+
|
9
|
+
#--
|
10
|
+
# See ext/ant_ext/ant_ext.c
|
11
|
+
module Ant
|
12
|
+
extend Loggability
|
13
|
+
|
14
|
+
# Package version
|
15
|
+
VERSION = '0.0.1'
|
16
|
+
|
17
|
+
# Version control revision
|
18
|
+
REVISION = %q$Revision$
|
19
|
+
|
20
|
+
|
21
|
+
# A Range for matching valid ANT device numbers
|
22
|
+
VALID_DEVICE_NUMBERS = ( 0...65535 ).freeze
|
23
|
+
|
24
|
+
# A Range for matching valid ANT device types (6 least signficant bits)
|
25
|
+
VALID_DEVICE_TYPES = ( 0...127 ).freeze
|
26
|
+
|
27
|
+
# The default range of frequencies for the channel period
|
28
|
+
VALID_CHANNEL_PERIODS = ( 0...65535 ).freeze
|
29
|
+
|
30
|
+
# The valid offsets for the "RF Frequency" setting; this is an offset from 2400Hz.
|
31
|
+
VALID_RF_FREQUENCIES = ( 0...124 ).freeze
|
32
|
+
|
33
|
+
|
34
|
+
# Loggability API -- set up a logger for the library
|
35
|
+
log_as :ant
|
36
|
+
|
37
|
+
|
38
|
+
Loggability.level = :debug
|
39
|
+
|
40
|
+
|
41
|
+
autoload :ResponseCallbacks, 'ant/response_callbacks'
|
42
|
+
autoload :DataUtilities, 'ant/mixins'
|
43
|
+
|
44
|
+
|
45
|
+
### Set up the given +mod+ as the handler module for response callbacks. You can
|
46
|
+
### create your own handler module and extend with the default Ant::ResponseCallbacks.
|
47
|
+
def self::set_response_handlers( mod=Ant::ResponseCallbacks )
|
48
|
+
self.extend( mod )
|
49
|
+
self.on_response( &self.method(:handle_response_callback) )
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
### Check that specified +number+ is a valid device number and raise an
|
54
|
+
### appropriate exception if it isn't. Returns the number as an Integer if it is
|
55
|
+
### valid.
|
56
|
+
def self::validate_device_number( number )
|
57
|
+
number = Integer( number )
|
58
|
+
unless VALID_DEVICE_NUMBERS.include?( number )
|
59
|
+
raise RangeError, "invalid device number; expected a number between %d and %d, got %p" %
|
60
|
+
[ VALID_DEVICE_NUMBERS.begin, VALID_DEVICE_NUMBERS.end, number ]
|
61
|
+
end
|
62
|
+
|
63
|
+
return number
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
### Check that specified +number+ is a valid device type and raise an
|
68
|
+
### appropriate exception if it isn't. Returns the number as an Integer if it is
|
69
|
+
### valid.
|
70
|
+
def self::validate_device_type( number )
|
71
|
+
number = Integer( number )
|
72
|
+
unless VALID_DEVICE_TYPES.include?( number )
|
73
|
+
raise RangeError, "invalid device type; expected a number between %d and %d, got %p" %
|
74
|
+
[ VALID_DEVICE_TYPES.begin, VALID_DEVICE_TYPES.end, number ]
|
75
|
+
end
|
76
|
+
|
77
|
+
return number
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
### Check that specified +frequency+ is a valid channel period and raise an
|
82
|
+
### appropriate exception if it isn't. Returns the frequency as an Integer if it is
|
83
|
+
### valid.
|
84
|
+
def self::validate_channel_period( frequency )
|
85
|
+
frequency = Integer( frequency )
|
86
|
+
unless VALID_CHANNEL_PERIODS.include?( frequency )
|
87
|
+
raise RangeError, "invalid channel period; expected a frequency between %d and %d, got %p" %
|
88
|
+
[ VALID_CHANNEL_PERIODS.begin, VALID_CHANNEL_PERIODS.end, frequency ]
|
89
|
+
end
|
90
|
+
|
91
|
+
return frequency
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
### Check that specified +number+ is a valid ANT network number and raise an
|
96
|
+
### appropriate exception if it isn't. Note that this does not check
|
97
|
+
### the local device(s) to ensure they support the given network. Returns the key
|
98
|
+
### as an Integer if it is valid.
|
99
|
+
def self::validate_network_number( number )
|
100
|
+
number = Integer( number )
|
101
|
+
unless number >= 0 && number <= 255
|
102
|
+
raise RangeError, "invalid network number; expected an eight-bit number, got %p" %
|
103
|
+
[ number ]
|
104
|
+
end
|
105
|
+
|
106
|
+
return number
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
### Check that specified +data+ is a valid ANT network key and raise an
|
111
|
+
### appropriate exception if it isn't. Returns the key itself if it is valid.
|
112
|
+
def self::validate_network_key( data )
|
113
|
+
data = data.to_s
|
114
|
+
unless data.bytesize == 8
|
115
|
+
raise RangeError, "invalid network key; expected exactly eight bytes, got %d" %
|
116
|
+
[ data.bytesize ]
|
117
|
+
end
|
118
|
+
|
119
|
+
self.log.debug "Validated network key: %p" % [ data ]
|
120
|
+
return data
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
### Check that specified +offset+ is a valid "rf frequency" and raise an
|
125
|
+
### appropriate exception if it isn't. Returns the offset as an Integer if it is
|
126
|
+
### valid.
|
127
|
+
def self::validate_rf_frequency( offset )
|
128
|
+
offset = Integer( offset )
|
129
|
+
unless VALID_RF_FREQUENCIES.include?( offset )
|
130
|
+
raise RangeError, "invalid RF Frequency; expected a offset between %d and %d, got %p" %
|
131
|
+
[ VALID_RF_FREQUENCIES.begin, VALID_RF_FREQUENCIES.end, offset ]
|
132
|
+
end
|
133
|
+
|
134
|
+
return offset
|
135
|
+
end
|
136
|
+
|
137
|
+
end # module Ant
|
138
|
+
|
data/lib/ant/channel.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'loggability'
|
5
|
+
|
6
|
+
require 'ant' unless defined?( Ant )
|
7
|
+
|
8
|
+
|
9
|
+
class Ant::Channel
|
10
|
+
extend Loggability
|
11
|
+
|
12
|
+
# The default network number
|
13
|
+
DEFAULT_NETWORK_NUMBER = 0
|
14
|
+
|
15
|
+
# The default channel options
|
16
|
+
DEFAULT_EXTENDED_OPTIONS = 0x0
|
17
|
+
|
18
|
+
|
19
|
+
#
|
20
|
+
# Autoloads
|
21
|
+
#
|
22
|
+
|
23
|
+
autoload :EventCallbacks, 'ant/channel/event_callbacks'
|
24
|
+
|
25
|
+
|
26
|
+
# Loggability API -- log to the Ant logger
|
27
|
+
log_to :ant
|
28
|
+
|
29
|
+
# Disallow manual instantiation
|
30
|
+
private_class_method :new
|
31
|
+
|
32
|
+
|
33
|
+
##
|
34
|
+
# Channel registry, keyed by channel number.
|
35
|
+
singleton_class.attr_reader( :registry )
|
36
|
+
|
37
|
+
|
38
|
+
######
|
39
|
+
public
|
40
|
+
######
|
41
|
+
|
42
|
+
alias_method :set_channel_rf_frequency, :set_channel_rf_freq
|
43
|
+
|
44
|
+
|
45
|
+
### Set up the given +mod+ as the handler module for channel events.
|
46
|
+
def set_event_handlers( mod=Ant::Channel::EventCallbacks )
|
47
|
+
self.extend( mod )
|
48
|
+
self.on_event( &self.method(:handle_event_callback) )
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
### Return a human-readable version of the object suitable for debugging.
|
53
|
+
def inspect
|
54
|
+
return "#<%p:%#x {%d} %#02x on network %d: %d%s>" % [
|
55
|
+
self.class,
|
56
|
+
self.object_id,
|
57
|
+
self.channel_number,
|
58
|
+
self.channel_type,
|
59
|
+
self.network_number,
|
60
|
+
self.extended_options,
|
61
|
+
self.closed? ? " (closed)" : "",
|
62
|
+
]
|
63
|
+
end
|
64
|
+
|
65
|
+
end # class Ant::Channel
|
66
|
+
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'securerandom'
|
5
|
+
require 'loggability'
|
6
|
+
|
7
|
+
require 'ant/channel' unless defined?( Ant::Channel )
|
8
|
+
require 'ant/mixins'
|
9
|
+
|
10
|
+
|
11
|
+
# A module that contains logging event callbacks for an ANT::Channel.
|
12
|
+
#
|
13
|
+
# Refs:
|
14
|
+
# * 9.5.6.1 Channel Response / Event (0x40) [ANT Message Protocol and Usage, Rev 5.1]
|
15
|
+
module Ant::Channel::EventCallbacks
|
16
|
+
extend Loggability
|
17
|
+
include Ant::DataUtilities
|
18
|
+
|
19
|
+
|
20
|
+
# Loggability API -- send logs to the Ant logger
|
21
|
+
log_to :ant
|
22
|
+
|
23
|
+
|
24
|
+
# Mapping of response message IDs to handler methods
|
25
|
+
HANDLER_METHODS = {
|
26
|
+
Ant::EVENT_CHANNEL_CLOSED => :on_event_channel_closed,
|
27
|
+
Ant::EVENT_CHANNEL_COLLISION => :on_event_channel_collision,
|
28
|
+
Ant::EVENT_RX_ACKNOWLEDGED => :on_event_rx_acknowledged,
|
29
|
+
Ant::EVENT_RX_BROADCAST => :on_event_rx_broadcast,
|
30
|
+
Ant::EVENT_RX_BURST_PACKET => :on_event_rx_burst_packet,
|
31
|
+
Ant::EVENT_RX_EXT_ACKNOWLEDGED => :on_event_rx_ext_acknowledged,
|
32
|
+
Ant::EVENT_RX_EXT_BROADCAST => :on_event_rx_ext_broadcast,
|
33
|
+
Ant::EVENT_RX_EXT_BURST_PACKET => :on_event_rx_ext_burst_packet,
|
34
|
+
Ant::EVENT_RX_FAIL => :on_event_rx_fail,
|
35
|
+
Ant::EVENT_RX_FAIL_GO_TO_SEARCH => :on_event_rx_fail_go_to_search,
|
36
|
+
Ant::EVENT_RX_FLAG_ACKNOWLEDGED => :on_event_rx_flag_acknowledged,
|
37
|
+
Ant::EVENT_RX_FLAG_BROADCAST => :on_event_rx_flag_broadcast,
|
38
|
+
Ant::EVENT_RX_FLAG_BURST_PACKET => :on_event_rx_flag_burst_packet,
|
39
|
+
Ant::EVENT_RX_SEARCH_TIMEOUT => :on_event_rx_search_timeout,
|
40
|
+
Ant::EVENT_TRANSFER_RX_FAILED => :on_event_transfer_rx_failed,
|
41
|
+
Ant::EVENT_TRANSFER_TX_COMPLETED => :on_event_transfer_tx_completed,
|
42
|
+
Ant::EVENT_TRANSFER_TX_FAILED => :on_event_transfer_tx_failed,
|
43
|
+
Ant::EVENT_TRANSFER_TX_START => :on_event_transfer_tx_start,
|
44
|
+
Ant::EVENT_TX => :on_event_tx,
|
45
|
+
}
|
46
|
+
|
47
|
+
# The mask of the channel number in buffer data
|
48
|
+
CHANNEL_NUMBER_MASK = 0x1F
|
49
|
+
|
50
|
+
# The mask of the sequence number in buffer data
|
51
|
+
SEQUENCE_NUMBER_MASK = 0xE0
|
52
|
+
|
53
|
+
|
54
|
+
### Default callback hook -- handles event callbacks.
|
55
|
+
def handle_event_callback( channel_num, event_id, data )
|
56
|
+
handler_method = HANDLER_METHODS[ event_id ] or
|
57
|
+
raise "Unhandled channel event %p" % [ event_id ]
|
58
|
+
|
59
|
+
if self.respond_to?( handler_method )
|
60
|
+
self.public_send( handler_method, channel_num, data )
|
61
|
+
else
|
62
|
+
Ant::Channel::EventCallbacks.log_event_callback( channel_num, handler_method, event_id, data )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
### Log the channel event by default.
|
68
|
+
def self::log_event_callback( channel_num, handler_method, event_id, data )
|
69
|
+
self.log.debug "Event on channel %d: %#0x (%s): %s" % [
|
70
|
+
channel_num,
|
71
|
+
event_id,
|
72
|
+
handler_method,
|
73
|
+
Ant::DataUtilities.hexdump( data[ 0..3 ] )
|
74
|
+
]
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
### Handle an TX event.
|
79
|
+
def on_event_tx( channel_num, data )
|
80
|
+
# self.log.info "Broadcast message on channel %d was transmitted." % [ channel_num ]
|
81
|
+
|
82
|
+
# data = SecureRandom.bytes( 8 )
|
83
|
+
# self.log.debug "Sending our own broadcast data: %p." % [ data ]
|
84
|
+
# self.send_broadcast_data( data )
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
### Handle a RX_SEARCH_TIMEOUT event.
|
89
|
+
def on_event_rx_search_timeout( channel_num, * )
|
90
|
+
self.log.warn "Search timeout on channel %d." % [ channel_num ]
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
### Handle a RX_FAIL event.
|
95
|
+
def on_event_rx_fail( channel_num, * )
|
96
|
+
self.log.warn "Receive failed on channel %d." % [ channel_num ]
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
### Handle a TRANSFER_RX_FAILED event.
|
101
|
+
def on_event_transfer_rx_failed( channel_num, * )
|
102
|
+
self.log.warn "Receive failed on channel %d." % [ channel_num ]
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
### Handle a TRANSFER_TX_COMPLETED event.
|
107
|
+
def on_event_transfer_tx_completed( channel_num, * )
|
108
|
+
self.log.warn "Transfer completed on channel %d." % [ channel_num ]
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
### Handle a TRANSFER_TX_FAILED event.
|
113
|
+
def on_event_transfer_tx_failed( channel_num, * )
|
114
|
+
self.log.warn "Transfer failed on channel %d." % [ channel_num ]
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
### Handle a CHANNEL_CLOSED event.
|
119
|
+
def on_event_channel_closed( channel_num, * )
|
120
|
+
self.log.warn "Channel %d was closed." % [ channel_num ]
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
### Handle a RX_FAIL_GO_TO_SEARCH event.
|
125
|
+
def on_event_rx_fail_go_to_search( channel_num, * )
|
126
|
+
self.log.warn "Channel %d dropped; resume search." % [ channel_num ]
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
### Handle a CHANNEL_COLLISION event.
|
131
|
+
def on_event_channel_collision( channel_num, * )
|
132
|
+
self.log.warn "Channel collision on channel %d." % [ channel_num ]
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
### Handle a TRANSFER_TX_START event.
|
137
|
+
def on_event_transfer_tx_start( channel_num, * )
|
138
|
+
self.log.warn "Burst transfer started on channel %d." % [ channel_num ]
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# def on_event_rx_flag_acknowledged( channel_num, data )
|
143
|
+
#
|
144
|
+
# end
|
145
|
+
|
146
|
+
### Handle an RX_FLAG_BURST_PACKET event.
|
147
|
+
def on_event_rx_flag_burst_packet( channel_num, data )
|
148
|
+
flags = data.bytes[ 9 ]
|
149
|
+
if flags & Ant::ANT_EXT_MESG_BITFIELD_DEVICE_ID
|
150
|
+
usDeviceNumber = data.bytes[10] | (data.bytes[11] << 8)
|
151
|
+
ucDeviceType = data.bytes[12]
|
152
|
+
ucTransmissionType = data.bytes[13]
|
153
|
+
self.log.info "Got a burst on Chan ID(%d/%d/%d)" %
|
154
|
+
[usDeviceNumber, ucDeviceType, ucTransmissionType]
|
155
|
+
end
|
156
|
+
|
157
|
+
self.on_event_rx_burst_packet( channel_num, data )
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
### Handle an RX_FLAG_BROADCAST event.
|
162
|
+
def on_event_rx_flag_broadcast( channel_num, data )
|
163
|
+
flags = data.bytes[ 9 ]
|
164
|
+
if flags & Ant::ANT_EXT_MESG_BITFIELD_DEVICE_ID
|
165
|
+
usDeviceNumber = data.bytes[10] | (data.bytes[11] << 8)
|
166
|
+
ucDeviceType = data.bytes[12]
|
167
|
+
ucTransmissionType = data.bytes[13]
|
168
|
+
self.log.info "Got a broadcast on Chan ID(%d/%d/%d)" %
|
169
|
+
[usDeviceNumber, ucDeviceType, ucTransmissionType]
|
170
|
+
end
|
171
|
+
|
172
|
+
self.on_event_rx_broadcast( channel_num, data )
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# def on_event_rx_acknowledged( channel_num, data )
|
177
|
+
#
|
178
|
+
# end
|
179
|
+
|
180
|
+
|
181
|
+
### Handle an RX_BURST_PACKET event.
|
182
|
+
def on_event_rx_burst_packet( channel_num, data )
|
183
|
+
channel = (data.bytes[0] & CHANNEL_NUMBER_MASK) >> 5
|
184
|
+
sequence_num = data.bytes[0] & SEQUENCE_NUMBER_MASK
|
185
|
+
|
186
|
+
self.log.info "Burst (0x%02x): Rx: %d:\n%s" % [ channel, sequence_num, hexdump(data[1..8]) ]
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
### Handle an RX_BROADCAST event.
|
191
|
+
def on_event_rx_broadcast( channel_num, data )
|
192
|
+
self.log.info "Broadcast: Rx:\n%s" % [ hexdump(data[1..8]) ]
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
# def on_event_rx_ext_acknowledged( channel_num, data )
|
197
|
+
#
|
198
|
+
# end
|
199
|
+
# def on_event_rx_ext_burst_packet( channel_num, data )
|
200
|
+
#
|
201
|
+
# end
|
202
|
+
# def on_event_rx_ext_broadcast( channel_num, data )
|
203
|
+
#
|
204
|
+
# end
|
205
|
+
|
206
|
+
|
207
|
+
end # module Ant::Channel::EventCallbacks
|