Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class TeltonikaParser
- class ParseMessageSegment
- attr_reader :segment
- def initialize(segment)
- @segment = segment
- end
- def call
- {
- timestamp: read_number(0, 8),
- longitude: parse_coord(9),
- latitude: parse_coord(13),
- speed: read_number(22, 2),
- event_code: read_number(24, 1),
- ios: parse_ios
- }
- end
- private
- def parse_coord(offset)
- read_number(offset, 4, true).fdiv(10 ** 7)
- end
- def read_number(offset, bytes_count, signed = false)
- number = segment[offset...offset + bytes_count]
- .reduce { |result, byte| result * 256 + byte }
- if signed
- max_positive_number = (256 ** bytes_count) / 2 - 1;
- if number > max_positive_number
- number -= max_positive_number
- end
- end
- number
- end
- def parse_ios
- ios = {}
- offset = 26
- [1, 2, 4, 8].each do |bytes_count|
- ios_count = segment[offset]
- offset += 1
- ios_count.times do
- ios[segment[offset]] = read_number(offset + 1, bytes_count)
- offset += bytes_count + 1
- end
- end
- ios
- end
- end
- class ParseMessage
- attr_reader :message
- def initialize(message)
- @message = message.split.map { |hex| hex.to_i(16) }
- end
- def call
- result = {
- imei: parse_imei,
- messages: parse_message_segments
- }
- end
- private
- def parse_imei
- message[8..22].reduce("") do |result, n|
- result + n.to_s(16)[1]
- end
- end
- def parse_message_segments
- number_of_segments = message[24]
- segments = extract_segments(number_of_segments)
- segments.map { |s| ParseMessageSegment.new(s).call }
- end
- def extract_segments(number_of_segments)
- segments = []
- offset = 25
- number_of_segments.times do
- segment_end = offset + segment_size(offset)
- segments << message[offset...segment_end]
- end
- segments
- end
- def segment_size(offset)
- 26 + ios_size(offset + 26)
- end
- def ios_size(ios_start)
- offset = ios_start
- one_byte_ios = message[offset]
- offset += one_byte_ios * 2 + 1
- two_byte_ios = message[offset]
- offset += two_byte_ios * 3 + 1
- four_byte_ios = message[offset]
- offset += four_byte_ios * 5 + 1
- eight_byte_ios = message[offset]
- offset += eight_byte_ios * 9 + 1
- offset - ios_start
- end
- end
- def parse(messages)
- if !messages || messages == "" || messages == []
- return []
- end
- messages.map { |message| ParseMessage.new(message).call }
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement