Module: RubyFit::Helpers
- Included in:
- MessageWriter, Type
- Defined in:
- lib/rubyfit/helpers.rb
Constant Summary collapse
- GARMIN_TIME_OFFSET =
Garmin timestamps start at 12:00:00 01-01-1989, 20 years after the unix epoch
631065600
- DEGREES_TO_SEMICIRCLES =
2**31 / 180.0
Instance Method Summary collapse
-
#bytes2hex(bytes) ⇒ Object
Generates strings of hex bytes (for debugging).
- #bytes2num(bytes, byte_count, unsigned = true, big_endian = true) ⇒ Object
-
#bytes2str(bytes) ⇒ Object
Converts a byte array to a string.
- #deg2semicircles(degrees) ⇒ Object
- #fit2unix_timestamp(timestamp) ⇒ Object
- #make_message_header(opts = {}) ⇒ Object
-
#num2bytes(num, byte_count, big_endian = true) ⇒ Object
Converts a fixnum or bignum into a byte array, optionally truncating or right-filling with 0 to match a certain size.
- #semicircles2deg(degrees) ⇒ Object
-
#str2bytes(str, byte_count) ⇒ Object
Converts an ASCII string into a byte array, truncating or right-filling with 0 to match byte_count.
- #unix2fit_timestamp(timestamp) ⇒ Object
Instance Method Details
#bytes2hex(bytes) ⇒ Object
Generates strings of hex bytes (for debugging)
74 75 76 77 78 79 |
# File 'lib/rubyfit/helpers.rb', line 74 def bytes2hex(bytes) bytes .map{|b| "0x#{b.to_s(16).ljust(2, "0")}"} .each_slice(8) .map{ |s| s.join(", ") } end |
#bytes2num(bytes, byte_count, unsigned = true, big_endian = true) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rubyfit/helpers.rb', line 45 def bytes2num(bytes, byte_count, unsigned = true, big_endian = true) directive = { 1 => "C", 2 => "S", 4 => "L", 8 => "Q" }[byte_count] raise "Unsupported byte count: #{byte_count}" unless directive directive << (big_endian ? ">" : "<") if byte_count > 1 directive.downcase! unless unsigned bytes.pack("C*").unpack(directive).first end |
#bytes2str(bytes) ⇒ Object
Converts a byte array to a string. Omits the last character of the byte array from the result if it is 0
68 69 70 71 |
# File 'lib/rubyfit/helpers.rb', line 68 def bytes2str(bytes) bytes = bytes[0...-1] if bytes.last == 0 bytes.pack("C*") end |
#deg2semicircles(degrees) ⇒ Object
90 91 92 |
# File 'lib/rubyfit/helpers.rb', line 90 def deg2semicircles(degrees) (degrees * DEGREES_TO_SEMICIRCLES).truncate end |
#fit2unix_timestamp(timestamp) ⇒ Object
85 86 87 |
# File 'lib/rubyfit/helpers.rb', line 85 def () + GARMIN_TIME_OFFSET end |
#make_message_header(opts = {}) ⇒ Object
101 102 103 104 105 106 |
# File 'lib/rubyfit/helpers.rb', line 101 def (opts = {}) result = 0 result |= (1 << 6) if opts[:definition] result |= (opts[:local_number] || 0) & 0xF result end |
#num2bytes(num, byte_count, big_endian = true) ⇒ Object
Converts a fixnum or bignum into a byte array, optionally truncating or right-filling with 0 to match a certain size
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/rubyfit/helpers.rb', line 9 def num2bytes(num, byte_count, big_endian = true) raise ArgumentError.new("num must be an integer") unless num.is_a?(Integer) orig_num = num # Convert negative numbers to two's complement (1-byte alignment) if num < 0 num = num.abs if num > 2 ** (byte_count * 8 - 1) STDERR.puts("RubyFit WARNING: Integer underflow for #{orig_num} (#{orig_num.bit_length + 1} bits) when fitting in #{byte_count} bytes (#{byte_count * 8} bits)") end num = 2 ** (byte_count * 8) - num end hex = num.to_s(16) # pack('H*') assumes the high nybble is first, which reverses nybbles in # the most significant byte if it's only one hex char (<= 0xF). Prevent # this by prepending a zero if the hex string is an odd length hex = "0" + hex if hex.length.odd? result = [hex] .pack('H*') .unpack("C*") if result.size > byte_count STDERR.puts("RubyFit WARNING: Truncating #{orig_num} (#{orig_num.bit_length} bits) to fit in #{byte_count} bytes (#{byte_count * 8} bits)") result = result.last(byte_count) elsif result.size < byte_count pad_bytes = [0] * (byte_count - result.size) result.unshift(*pad_bytes) end result.reverse! unless big_endian result end |
#semicircles2deg(degrees) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/rubyfit/helpers.rb', line 94 def semicircles2deg(degrees) result = degrees / DEGREES_TO_SEMICIRCLES result -= 360.0 if result > 180.0 result += 360.0 if result < -180.0 result end |
#str2bytes(str, byte_count) ⇒ Object
Converts an ASCII string into a byte array, truncating or right-filling with 0 to match byte_count
60 61 62 63 64 |
# File 'lib/rubyfit/helpers.rb', line 60 def str2bytes(str, byte_count) str .unpack("C#{byte_count - 1}") # Convert to n-1 bytes .map{|v| v || 0} + [0] # Convert nils to 0 and add null terminator end |
#unix2fit_timestamp(timestamp) ⇒ Object
81 82 83 |
# File 'lib/rubyfit/helpers.rb', line 81 def () - GARMIN_TIME_OFFSET end |