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