ant-wireless 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b16333eed832c3068cd6e95d167bffe8132aaba7543ccabd773d809fac840199
4
- data.tar.gz: 92d089d1bcf5121dd46477befeabc33e43abbac10de105d3d94d176b54c9af8a
3
+ metadata.gz: 1cbf09bffd2b5ac2d18ea9fb271bb1e358707b45a49bd45651129d5030598e95
4
+ data.tar.gz: f2d892f9c17f352e81b1b6236ac567a62f24b61495860b0f071975bd80446ea8
5
5
  SHA512:
6
- metadata.gz: 51dbc06b6c199f16404fb0d79fd78e10cf53c4ca68e221462d225e1dff171a51f5f1807da2ebe2719e45109e981ece26781090ebd583d4c8c01d6e1539c5e43a
7
- data.tar.gz: da1492d614d52e83402c85bbeed0d45d03f7f101bd6b5036ae9bc7a488dfbd5df41ee5aa2a0a3b0a7b4e7019c4d95bc55d0167a3a6e77c1825565ca299ba492e
6
+ metadata.gz: 8ecd19b9d5c711fe0e71be58e5fa3c1386fa340bc9cafa0279e08ba52b48ebe8f7169386faf93fe5b7a900a8ee70d84d049f31db3405dc2c7e957fa5126fce2c
7
+ data.tar.gz: 83aa2b97810514c2279182d1853efeed48087e270cb6db2533b151cae046370a6071c7fa2ed164cf6558c79b1f970a3d18526c2188ea281dc4493ec8313ebec5
checksums.yaml.gz.sig CHANGED
Binary file
data/History.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Release History for ruby-ant
2
2
 
3
3
  ---
4
+ ## v0.4.0 [2021-11-05] Michael Granger <ged@FaerieMUD.org>
5
+
6
+ Enhancements:
7
+
8
+ - Add advanced burst support (with a customized ANT-SDK).
9
+
10
+
4
11
  ## v0.3.0 [2021-10-11] Michael Granger <ged@FaerieMUD.org>
5
12
 
6
13
  Enhancements:
data/README.md CHANGED
@@ -24,7 +24,10 @@ manner.
24
24
  * [Garmin USB ANT Stick][antstick]
25
25
  * [ANT SDK][antsdk]
26
26
 
27
- Note that we had trouble compiling the latest ANT SDK on some platforms, so we are currently using a modified version of it with a reworked build system for MacOS and FreeBSD. That is available under the same licensing terms at:
27
+ Note that we had trouble compiling the latest ANT SDK on some platforms, so we
28
+ are currently using a modified version of it with a reworked build system for
29
+ MacOS and FreeBSD, and with implementations for advanced burst and checking
30
+ initialization status. That is available under the same licensing terms at:
28
31
 
29
32
  https://github.com/RavnGroup/Garmin-ANT-SDK
30
33
 
@@ -225,6 +225,15 @@ rant_s_init( int argc, VALUE *argv, VALUE _module )
225
225
  }
226
226
 
227
227
 
228
+ /*
229
+ * call-seq:
230
+ * Ant.initialized? -> true or false
231
+ *
232
+ * Returns +true+ if the ANT library has been initialized.
233
+ *
234
+ * Note: this requires a modified version of the Garmin ANT-SDK.
235
+ *
236
+ */
228
237
  static VALUE
229
238
  rant_s_initialized_p( VALUE _module )
230
239
  {
@@ -418,6 +427,56 @@ rant_s_use_extended_messages_eq( VALUE _module, VALUE true_false )
418
427
  }
419
428
 
420
429
 
430
+ /*
431
+ * call-seq:
432
+ * Ant.configure_advanced_burst( enabled, max_packet_length, required_fields, optional_fields,
433
+ * stall_count=3210, retry_count=4 )
434
+ *
435
+ * Enable/disable and configure advanced burst. This is the lower-level method; the
436
+ * higher-level methods are: #enable_advanced_burst and #disable_advanced_burst.
437
+ *
438
+ */
439
+ static VALUE
440
+ rant_s_configure_advanced_burst( int argc, VALUE *argv, VALUE _module )
441
+ {
442
+ VALUE enabled,
443
+ max_packet_length,
444
+ required_fields,
445
+ optional_fields,
446
+ stall_count = Qnil,
447
+ retry_count = Qnil;
448
+ bool bEnable;
449
+ unsigned char ucMaxPacketLength,
450
+ ucRetryCount = 0;
451
+ unsigned long ulRequiredFields,
452
+ ulOptionalFields;
453
+ unsigned short usStallCount = 0;
454
+ bool rval;
455
+
456
+ rb_scan_args( argc, argv, "42", &enabled, &max_packet_length, &required_fields,
457
+ &optional_fields, &stall_count, &retry_count );
458
+
459
+ bEnable = RTEST( enabled );
460
+ ucMaxPacketLength = NUM2CHR( max_packet_length );
461
+ ulRequiredFields = NUM2ULONG( required_fields );
462
+ ulOptionalFields = NUM2ULONG( optional_fields );
463
+
464
+ if ( RTEST(stall_count) ) {
465
+ usStallCount = NUM2USHORT( stall_count );
466
+ }
467
+ if ( RTEST(retry_count) ) {
468
+ ucRetryCount = NUM2CHR( retry_count );
469
+ }
470
+
471
+ rant_log( "warn", "Configuring advanced burst: enable = %d, maxpacketlength = %d",
472
+ bEnable, ucMaxPacketLength );
473
+ rval = ANT_ConfigureAdvancedBurst_ext( bEnable, ucMaxPacketLength, ulRequiredFields,
474
+ ulOptionalFields, usStallCount, ucRetryCount );
475
+
476
+ return rval ? Qtrue : Qfalse;
477
+ }
478
+
479
+
421
480
  // Buffer for response data.
422
481
  // static UCHAR pucResponseBuffer[ MESG_RESPONSE_EVENT_SIZE ];
423
482
  static UCHAR pucResponseBuffer[ MESG_MAX_SIZE_VALUE ];
@@ -510,7 +569,7 @@ rant_s_on_response( int argc, VALUE *argv, VALUE module )
510
569
  *
511
570
  */
512
571
  static VALUE
513
- rant_s_request_capabilities( VALUE module )
572
+ rant_s_request_capabilities( VALUE _module )
514
573
  {
515
574
  bool rval = ANT_RequestMessage( 0, MESG_CAPABILITIES_ID );
516
575
  return rval ? Qtrue : Qfalse;
@@ -527,7 +586,7 @@ rant_s_request_capabilities( VALUE module )
527
586
  *
528
587
  */
529
588
  static VALUE
530
- rant_s_request_serial_num( VALUE module )
589
+ rant_s_request_serial_num( VALUE _module )
531
590
  {
532
591
  bool rval = ANT_RequestMessage( 0, MESG_GET_SERIAL_NUM_ID );
533
592
  return rval ? Qtrue : Qfalse;
@@ -544,13 +603,30 @@ rant_s_request_serial_num( VALUE module )
544
603
  *
545
604
  */
546
605
  static VALUE
547
- rant_s_request_version( VALUE module )
606
+ rant_s_request_version( VALUE _module )
548
607
  {
549
608
  bool rval = ANT_RequestMessage( 0, MESG_VERSION_ID );
550
609
  return rval ? Qtrue : Qfalse;
551
610
  }
552
611
 
553
612
 
613
+ /*
614
+ * call-seq:
615
+ * Ant.request_advanced_burst_capabilities
616
+ *
617
+ * Request the current device's advanced burst capabilities. The result will
618
+ * be delivered via a callback to the #on_version response callback, which by
619
+ * default extracts it and stores it at Ant.advanced_burst_capabilities.
620
+ *
621
+ */
622
+ static VALUE
623
+ rant_s_request_advanced_burst_capabilities( VALUE _module )
624
+ {
625
+ bool rval = ANT_RequestMessage( 0, MESG_CONFIG_ADV_BURST_ID );
626
+ return rval ? Qtrue : Qfalse;
627
+ }
628
+
629
+
554
630
  /*
555
631
  * call-seq:
556
632
  * Ant.log_directory = "path/to/log/dir"
@@ -606,6 +682,8 @@ Init_ant_ext()
606
682
 
607
683
  rb_define_singleton_method( rant_mAnt, "use_extended_messages=",
608
684
  rant_s_use_extended_messages_eq, 1 );
685
+ rb_define_singleton_method( rant_mAnt, "configure_advanced_burst",
686
+ rant_s_configure_advanced_burst, -1 );
609
687
 
610
688
  rb_define_singleton_method( rant_mAnt, "on_response", rant_s_on_response, -1 );
611
689
  // EXPORT void ANT_UnassignAllResponseFunctions(); //Unassigns all response functions
@@ -613,6 +691,8 @@ Init_ant_ext()
613
691
  rb_define_singleton_method( rant_mAnt, "request_capabilities", rant_s_request_capabilities, 0 );
614
692
  rb_define_singleton_method( rant_mAnt, "request_serial_num", rant_s_request_serial_num, 0 );
615
693
  rb_define_singleton_method( rant_mAnt, "request_version", rant_s_request_version, 0 );
694
+ rb_define_singleton_method( rant_mAnt, "request_advanced_burst_capabilities",
695
+ rant_s_request_advanced_burst_capabilities, 0 );
616
696
 
617
697
  rb_define_singleton_method( rant_mAnt, "log_directory=", rant_s_log_directory_eq, 1 );
618
698
 
@@ -9,6 +9,9 @@
9
9
 
10
10
  #include "ant_ext.h"
11
11
 
12
+ #define DEFAULT_ADV_PACKETS 3
13
+ #define ADVANCED_BURST_TIMEOUT 5
14
+
12
15
  VALUE rant_cAntChannel;
13
16
 
14
17
  VALUE rant_mAntDataUtilities;
@@ -300,8 +303,16 @@ rant_channel_set_channel_rf_freq( VALUE self, VALUE frequency )
300
303
  }
301
304
 
302
305
 
306
+ /*
307
+ * call-seq:
308
+ * channel.set_frequency_agility( freq1, freq2, freq3 )
309
+ *
310
+ * Set the frequencies to use in frequency agility (integers between 0 and 124). These values
311
+ * use the same convention as the +rf_frequency+ setting; i.e., they're offsets from 2400 MHz.
312
+ *
313
+ */
303
314
  static VALUE
304
- rant_channet_set_frequency_agility( VALUE self, VALUE freq1, VALUE freq2, VALUE freq3 )
315
+ rant_channel_set_frequency_agility( VALUE self, VALUE freq1, VALUE freq2, VALUE freq3 )
305
316
  {
306
317
  rant_channel_t *ptr = rant_get_channel( self );
307
318
  unsigned char ucFreq1 = NUM2CHR( freq1 ),
@@ -582,6 +593,61 @@ rant_channel_send_broadcast_data( VALUE self, VALUE data )
582
593
  }
583
594
 
584
595
 
596
+ /*
597
+ * call-seq:
598
+ * channel.send_advanced_transfer( data, packets_per_message=3 )
599
+ *
600
+ * Send the given +data+ as one or more advanced burst packets. The +packets_per_message+
601
+ * may be set to a value between 1 and 3 to control how many 8-byte packets are send with
602
+ * each message.
603
+ *
604
+ */
605
+ static VALUE
606
+ rant_channel_send_advanced_transfer( int argc, VALUE *argv, VALUE self )
607
+ {
608
+ #ifdef HAVE_ANT_SENDADVANCEDBURST
609
+ rant_channel_t *ptr = rant_get_channel( self );
610
+ VALUE data = Qnil, packets = Qnil;
611
+ unsigned char *data_s;
612
+ long data_len;
613
+ unsigned short usNumDataPackets, remainingBytes;
614
+ unsigned char ucStdPcktsPerSerialMsg = DEFAULT_ADV_PACKETS;
615
+
616
+ rb_scan_args( argc, argv, "11", &data, &packets );
617
+ data_len = RSTRING_LEN( data );
618
+ usNumDataPackets = data_len / 8;
619
+ remainingBytes = data_len % 8;
620
+ if ( RTEST(packets) ) {
621
+ ucStdPcktsPerSerialMsg = NUM2CHR(packets);
622
+ }
623
+
624
+ data_s = ALLOC_N( unsigned char, data_len );
625
+ strncpy( (char *)data_s, StringValuePtr(data), data_len );
626
+
627
+ // Pad it to 8-byte alignment
628
+ if ( remainingBytes ) {
629
+ int pad_bytes = (8 - remainingBytes);
630
+ REALLOC_N( data_s, unsigned char, data_len + pad_bytes );
631
+ memset( data_s + data_len, 0, pad_bytes );
632
+
633
+ usNumDataPackets += 1;
634
+ }
635
+
636
+ rant_log_obj( self, "warn", "Sending advanced burst packets (%d-byte messages): %s",
637
+ ucStdPcktsPerSerialMsg * 8, data_s );
638
+ if ( !ANT_SendAdvancedBurst_RTO(ptr->channel_num, data_s, usNumDataPackets,
639
+ ucStdPcktsPerSerialMsg, ADVANCED_BURST_TIMEOUT) )
640
+ {
641
+ rant_log_obj( self, "error", "failed to send advanced burst transfer." );
642
+ }
643
+
644
+ return Qtrue;
645
+ #else
646
+ rb_notimplement();
647
+ #endif
648
+ }
649
+
650
+
585
651
  void
586
652
  init_ant_channel()
587
653
  {
@@ -621,7 +687,7 @@ init_ant_channel()
621
687
  rb_define_method( rant_cAntChannel, "set_channel_search_timeout",
622
688
  rant_channel_set_channel_search_timeout, -1 );
623
689
  rb_define_method( rant_cAntChannel, "set_channel_rf_freq", rant_channel_set_channel_rf_freq, 1 );
624
- rb_define_method( rant_cAntChannel, "set_frequency_agility", rant_channet_set_frequency_agility, 3 );
690
+ rb_define_method( rant_cAntChannel, "set_frequency_agility", rant_channel_set_frequency_agility, 3 );
625
691
 
626
692
  rb_define_method( rant_cAntChannel, "open", rant_channel_open, -1 );
627
693
  rb_define_method( rant_cAntChannel, "close", rant_channel_close, -1 );
@@ -630,6 +696,7 @@ init_ant_channel()
630
696
  rb_define_method( rant_cAntChannel, "send_burst_transfer", rant_channel_send_burst_transfer, 1 );
631
697
  rb_define_method( rant_cAntChannel, "send_acknowledged_data", rant_channel_send_acknowledged_data, 1 );
632
698
  rb_define_method( rant_cAntChannel, "send_broadcast_data", rant_channel_send_broadcast_data, 1 );
699
+ rb_define_method( rant_cAntChannel, "send_advanced_transfer", rant_channel_send_advanced_transfer, -1 );
633
700
 
634
701
  rb_define_method( rant_cAntChannel, "on_event", rant_channel_on_event, -1 );
635
702
 
@@ -18,6 +18,15 @@ have_func( 'ANT_IsInitialized', 'libant.h' )
18
18
  have_func( 'ANT_LibVersion', 'libant.h' )
19
19
  have_func( 'ANT_GetDeviceSerialNumber', 'libant.h' )
20
20
 
21
+ # Look for a custom advanced burst function, as the official SDK has it in the
22
+ # header but doesn't actually implement it.
23
+ have_func( 'ANT_SendAdvancedBurst', 'libant.h' )
24
+
25
+ # Ref: https://bugs.ruby-lang.org/issues/17865
26
+ $CPPFLAGS << " -Wno-compound-token-split-by-macro "
27
+
28
+ $CFLAGS << " -g "
29
+
21
30
  create_header()
22
31
  create_makefile( 'ant_ext' )
23
32
 
@@ -9,7 +9,8 @@ require 'ant/bitvector'
9
9
 
10
10
  # A module that handles response callbacks by logging them.
11
11
  module Ant::ResponseCallbacks
12
- extend Loggability
12
+ extend Loggability,
13
+ Ant::DataUtilities
13
14
 
14
15
  # Loggability API -- send logs to the Ant logger
15
16
  log_to :ant
@@ -49,9 +50,10 @@ module Ant::ResponseCallbacks
49
50
  Ant::Message::MESG_RADIO_TX_POWER_ID => :on_radio_tx_power,
50
51
 
51
52
  Ant::Message::MESG_AUTO_FREQ_CONFIG_ID => :on_auto_freq_config,
53
+ Ant::Message::MESG_CONFIG_ADV_BURST_ID => :on_config_adv_burst_id,
52
54
 
53
55
  # :TODO: There are many other MESG_ constants, but I think most or all of
54
- # them are for the serial protocol.
56
+ # them are only used for the serial protocol.
55
57
  }
56
58
 
57
59
 
@@ -236,6 +238,54 @@ module Ant::ResponseCallbacks
236
238
  end
237
239
 
238
240
 
241
+ ### Handle callback when requesting advanced burst configuration.
242
+ def on_config_adv_burst_id( type, data )
243
+ self.log.debug "Advanced burst config/capabilities: 0x%02x: %p" % [ type, data ]
244
+
245
+ # Advanced burst capabilities
246
+ if type == 0
247
+ max_packet_length, features = data.unpack( 'CV' )
248
+ features = Ant::BitVector.new( features )
249
+
250
+ caps = {
251
+ max_packet_length: max_packet_length,
252
+ frequency_hopping: features.on?( Ant::ADV_BURST_CONFIG_FREQ_HOP )
253
+ }
254
+
255
+ self.log.info "Advanced burst capabilities: %p" % [ caps ]
256
+ Ant.instance_variable_set( :@advanced_burst_capabilities, caps );
257
+
258
+ # Advanced burst current configuration
259
+ elsif type == 1
260
+ enabled, max_packet_length, required, optional, stall_count, retry_count =
261
+ data.unpack( 'CCVVvC' )
262
+ required = Ant::BitVector.new( required )
263
+ optional = Ant::BitVector.new( optional )
264
+
265
+ required_features = []
266
+ required_features << :frequency_hopping if required.on?( Ant::ADV_BURST_CONFIG_FREQ_HOP )
267
+
268
+ optional_features = []
269
+ optional_features << :frequency_hopping if optional.on?( Ant::ADV_BURST_CONFIG_FREQ_HOP )
270
+
271
+ config = {
272
+ enabled: enabled == 1,
273
+ max_packet_length: max_packet_length,
274
+ required_features: required_features,
275
+ optional_features: optional_features,
276
+ stall_count: stall_count,
277
+ retry_count_extension: retry_count
278
+ }
279
+
280
+ self.log.info "Advanced burst configuration: %p" % [ config ]
281
+ Ant.instance_variable_set( :@advanced_burst_config, config );
282
+
283
+ else
284
+ self.log.warn "Unknown advanced burst response type %p." % [ type ]
285
+ end
286
+ end
287
+
288
+
239
289
  ### Handle capabilities response event.
240
290
  def on_capabilities( channel_num, data )
241
291
  std_opts = Ant::BitVector.new( data.bytes[2] )
data/lib/ant.rb CHANGED
@@ -12,7 +12,7 @@ module Ant
12
12
  extend Loggability
13
13
 
14
14
  # Package version
15
- VERSION = '0.3.0'
15
+ VERSION = '0.4.0'
16
16
 
17
17
  # A Range for matching valid ANT device numbers
18
18
  VALID_DEVICE_NUMBERS = ( 0...65535 ).freeze
@@ -26,6 +26,14 @@ module Ant
26
26
  # The valid offsets for the "RF Frequency" setting; this is an offset from 2400Hz.
27
27
  VALID_RF_FREQUENCIES = ( 0...124 ).freeze
28
28
 
29
+ # Default options for advanced burst when it's enabled.
30
+ DEFAULT_ADVANCED_OPTIONS = {
31
+ max_packet_length: 24,
32
+ frequency_hopping: :optional,
33
+ stall_count: 0,
34
+ retry_count: 0
35
+ }
36
+
29
37
 
30
38
  # Loggability API -- set up a logger for the library
31
39
  log_as :ant
@@ -143,5 +151,55 @@ module Ant
143
151
  return offset
144
152
  end
145
153
 
154
+
155
+ ### Enable advanced burst mode with the given +options+.
156
+ def self::enable_advanced_burst( **options )
157
+ options = DEFAULT_ADVANCED_OPTIONS.merge( options )
158
+
159
+ max_packet_length = self.convert_max_packet_length( options[:max_packet_length] )
160
+
161
+ required_fields = self.make_required_fields_config( options )
162
+ optional_fields = self.make_optional_fields_config( options )
163
+
164
+ stall_count = options[:stall_count]
165
+ retry_count = options[:retry_count]
166
+
167
+ self.configure_advanced_burst( true, max_packet_length, required_fields, optional_fields,
168
+ stall_count, retry_count )
169
+ end
170
+
171
+
172
+ ### Validate that the specified +length+ (in bytes) is a valid setting as an
173
+ ### advanced burst max packet length configuration value. Returns the equivalent
174
+ ### configuration value.
175
+ def self::convert_max_packet_length( length )
176
+ case length
177
+ when 8 then return 0x01
178
+ when 16 then return 0x02
179
+ when 24 then return 0x03
180
+ else
181
+ raise ArgumentError,
182
+ "invalid max packet length; expected 8, 16, or 24, got %p" % [ length ]
183
+ end
184
+ end
185
+
186
+
187
+ ### Given an options hash, return a configuration value for required fields.
188
+ def self::make_required_fields_config( **options )
189
+ value = 0
190
+ value |= 0x01 if options[:frequency_hopping] == :required
191
+
192
+ return value
193
+ end
194
+
195
+
196
+ ### Given an options hash, return a configuration value for optional fields.
197
+ def self::make_optional_fields_config( **options )
198
+ value = 0
199
+ value |= 0x01 if options[:frequency_hopping] == :optional
200
+
201
+ return value
202
+ end
203
+
146
204
  end # module Ant
147
205
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ant-wireless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -34,7 +34,7 @@ cert_chain:
34
34
  MCh97sQ/Z/MOusb5+QddBmB+k8EicXyGNl4b5L4XpL7fIQu+Y96TB3JEJlShxFD9
35
35
  k9FjI4d9EP54gS/4
36
36
  -----END CERTIFICATE-----
37
- date: 2021-10-11 00:00:00.000000000 Z
37
+ date: 2021-11-05 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: rake-compiler
metadata.gz.sig CHANGED
Binary file