Class: RubyFit::MessageWriter
- Inherits:
-
Object
- Object
- RubyFit::MessageWriter
- Extended by:
- Helpers
- Defined in:
- lib/rubyfit/message_writer.rb
Constant Summary collapse
- FIT_PROTOCOL_VERSION =
major 1, minor 0
0x10
- FIT_PROFILE_VERSION =
major 1, minor 52
1 * 100 + 52
- MESSAGE_DEFINITIONS =
{ file_id: { id: 0, fields: { serial_number: { id: 3, type: RubyFit::Type.uint32z, required: true }, time_created: { id: 4, type: RubyFit::Type., required: true }, manufacturer: { id: 1, type: RubyFit::Type.uint16 }, # See FIT_MANUFACTURER_* product: { id: 2, type: RubyFit::Type.uint16 }, type: { id: 0, type: RubyFit::Type.enum, required: true }, # See FIT_FILE_* } }, course: { id: 31, fields: { name: { id: 5, type: RubyFit::Type.string(16), required: true }, } }, lap: { id: 19, fields: { timestamp: { id: 253, type: RubyFit::Type., required: true}, start_time: { id: 2, type: RubyFit::Type., required: true}, total_elapsed_time: { id: 7, type: RubyFit::Type.duration, required: true }, total_timer_time: { id: 8, type: RubyFit::Type.duration, required: true }, start_y: { id: 3, type: RubyFit::Type.semicircles }, start_x: { id: 4, type: RubyFit::Type.semicircles }, end_y: { id: 5, type: RubyFit::Type.semicircles }, end_x: { id: 6, type: RubyFit::Type.semicircles }, total_distance: { id: 9, type: RubyFit::Type.centimeters }, }, }, course_point: { id: 32, fields: { timestamp: { id: 1, type: RubyFit::Type., required: true }, y: { id: 2, type: RubyFit::Type.semicircles, required: true }, x: { id: 3, type: RubyFit::Type.semicircles, required: true }, distance: { id: 4, type: RubyFit::Type.centimeters }, name: { id: 6, type: RubyFit::Type.string(16) }, message_index: { id: 254, type: RubyFit::Type.uint16 }, type: { id: 5, type: RubyFit::Type.enum, values: RubyFit::MessageConstants::COURSE_POINT_TYPE, required: true } }, }, record: { id: 20, fields: { timestamp: { id: 253, type: RubyFit::Type., required: true }, y: { id: 0, type: RubyFit::Type.semicircles, required: true }, x: { id: 1, type: RubyFit::Type.semicircles, required: true }, distance: { id: 5, type: RubyFit::Type.centimeters }, elevation: { id: 2, type: RubyFit::Type.altitude }, } }, event: { id: 21, fields: { timestamp: { id: 253, type: RubyFit::Type., required: true }, event: { id: 0, type: RubyFit::Type.enum, values: RubyFit::MessageConstants::EVENT, required: true }, event_type: { id: 1, type: RubyFit::Type.enum, values: RubyFit::MessageConstants::EVENT_TYPE, required: true }, event_group: { id: 4, type: RubyFit::Type.uint8 }, } } }
Constants included from Helpers
Helpers::DEGREES_TO_SEMICIRCLES, Helpers::GARMIN_TIME_OFFSET
Class Method Summary collapse
- .crc(crc_value) ⇒ Object
- .data_message(type, local_num, values) ⇒ Object
- .data_message_size(type) ⇒ Object
- .definition_message(type, local_num) ⇒ Object
- .definition_message_size(type) ⇒ Object
- .file_header(data_byte_count = 0) ⇒ Object
-
.header_byte(local_number, definition) ⇒ Object
Internal.
- .pack_bytes {|bytes| ... } ⇒ Object
Methods included from Helpers
bytes2hex, bytes2num, bytes2str, deg2semicircles, fit2unix_timestamp, make_message_header, num2bytes, semicircles2deg, str2bytes, unix2fit_timestamp
Class Method Details
.crc(crc_value) ⇒ Object
141 142 143 144 145 |
# File 'lib/rubyfit/message_writer.rb', line 141 def self.crc(crc_value) pack_bytes do |bytes| bytes.push(*num2bytes(crc_value, 2, false)) # Little endian end end |
.data_message(type, local_num, values) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/rubyfit/message_writer.rb', line 93 def self.(type, local_num, values) pack_bytes do |bytes| = MESSAGE_DEFINITIONS[type] bytes << header_byte(local_num, false) [:fields].each do |field, info| field_type = info[:type] value = values[field] if info[:required] && value.nil? raise ArgumentError.new("Missing required field '#{field}' in #{type} data message values") end if info[:values] value = info[:values][value] if value.nil? raise ArgumentError.new("Invalid value for '#{field}' in #{type} data message values") end end value_bytes = value ? field_type.val2bytes(value) : field_type.default_bytes bytes.push(*value_bytes) end end end |
.data_message_size(type) ⇒ Object
123 124 125 126 127 |
# File 'lib/rubyfit/message_writer.rb', line 123 def self.(type) = MESSAGE_DEFINITIONS[type] raise ArgumentError.new("Unknown message type '#{type}'") unless 1 + [:fields].values.map{|info| info[:type].byte_count}.reduce(&:+) end |
.definition_message(type, local_num) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/rubyfit/message_writer.rb', line 75 def self.(type, local_num) pack_bytes do |bytes| = MESSAGE_DEFINITIONS[type] bytes << header_byte(local_num, true) bytes << 0x00 # Reserved uint8 bytes << 0x01 # Big endian bytes.push(*num2bytes([:id], 2)) # Global message ID bytes << [:fields].size # Field count [:fields].each do |field, info| type = info[:type] bytes << info[:id] bytes << type.byte_count bytes << type.fit_id end end end |
.definition_message_size(type) ⇒ Object
117 118 119 120 121 |
# File 'lib/rubyfit/message_writer.rb', line 117 def self.(type) = MESSAGE_DEFINITIONS[type] raise ArgumentError.new("Unknown message type '#{type}'") unless 6 + [:fields].count * 3 end |
.file_header(data_byte_count = 0) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/rubyfit/message_writer.rb', line 129 def self.file_header(data_byte_count = 0) pack_bytes do |bytes| bytes << 14 # Header size bytes << FIT_PROTOCOL_VERSION # Protocol version bytes.push(*num2bytes(FIT_PROFILE_VERSION, 2).reverse) # Profile version (little endian) bytes.push(*num2bytes(data_byte_count, 4).reverse) # Data size (little endian) bytes.push(*str2bytes(".FIT", 5).take(4)) # Data Type ASCII, no terminator crc = 0 #RubyFit::CRC.update_crc(0, bytes2str(bytes)) bytes.push(*num2bytes(crc, 2).reverse) # Header CRC (little endian) end end |
.header_byte(local_number, definition) ⇒ Object
Internal
149 150 151 |
# File 'lib/rubyfit/message_writer.rb', line 149 def self.header_byte(local_number, definition) local_number & 0xF | (definition ? 0x40 : 0x00) end |
.pack_bytes {|bytes| ... } ⇒ Object
153 154 155 156 157 |
# File 'lib/rubyfit/message_writer.rb', line 153 def self.pack_bytes bytes = [] yield bytes bytes.pack("C*") end |