ant-wireless 0.3.0 → 0.4.0

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