Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 2.82 KB | None | 0 0
  1. class TeltonikaParser
  2.   class ParseMessageSegment
  3.     attr_reader :segment
  4.  
  5.     def initialize(segment)
  6.       @segment = segment
  7.     end
  8.  
  9.     def call
  10.       {
  11.         timestamp: read_number(0, 8),
  12.         longitude: parse_coord(9),
  13.         latitude: parse_coord(13),
  14.         speed: read_number(22, 2),
  15.         event_code: read_number(24, 1),
  16.         ios: parse_ios
  17.       }
  18.     end
  19.  
  20.     private
  21.  
  22.       def parse_coord(offset)
  23.         read_number(offset, 4, true).fdiv(10 ** 7)
  24.       end
  25.  
  26.       def read_number(offset, bytes_count, signed = false)
  27.         number = segment[offset...offset + bytes_count]
  28.           .reduce { |result, byte| result * 256 + byte }
  29.  
  30.         if signed
  31.           max_positive_number = (256 ** bytes_count) / 2 - 1;
  32.           if number > max_positive_number
  33.             number -= max_positive_number
  34.           end
  35.         end
  36.  
  37.         number
  38.       end
  39.  
  40.       def parse_ios
  41.         ios = {}
  42.         offset = 26
  43.         [1, 2, 4, 8].each do |bytes_count|
  44.           ios_count = segment[offset]
  45.           offset += 1
  46.           ios_count.times do
  47.             ios[segment[offset]] = read_number(offset + 1, bytes_count)
  48.             offset += bytes_count + 1
  49.           end
  50.         end
  51.         ios
  52.       end
  53.   end
  54.  
  55.   class ParseMessage
  56.     attr_reader :message
  57.  
  58.     def initialize(message)
  59.       @message = message.split.map { |hex| hex.to_i(16) }
  60.     end
  61.  
  62.     def call
  63.       result = {
  64.         imei: parse_imei,
  65.         messages: parse_message_segments
  66.       }
  67.     end
  68.  
  69.     private
  70.  
  71.       def parse_imei
  72.         message[8..22].reduce("") do |result, n|
  73.           result + n.to_s(16)[1]
  74.         end
  75.       end
  76.  
  77.       def parse_message_segments
  78.         number_of_segments = message[24]
  79.         segments = extract_segments(number_of_segments)
  80.         segments.map { |s| ParseMessageSegment.new(s).call }
  81.       end
  82.  
  83.       def extract_segments(number_of_segments)
  84.         segments = []
  85.         offset = 25
  86.         number_of_segments.times do
  87.           segment_end = offset + segment_size(offset)
  88.           segments << message[offset...segment_end]
  89.         end
  90.         segments
  91.       end
  92.  
  93.       def segment_size(offset)
  94.         26 + ios_size(offset + 26)
  95.       end
  96.  
  97.       def ios_size(ios_start)
  98.         offset = ios_start
  99.         one_byte_ios = message[offset]
  100.         offset += one_byte_ios * 2 + 1
  101.         two_byte_ios = message[offset]
  102.         offset += two_byte_ios * 3 + 1
  103.         four_byte_ios = message[offset]
  104.         offset += four_byte_ios * 5 + 1
  105.         eight_byte_ios = message[offset]
  106.         offset += eight_byte_ios * 9 + 1
  107.         offset - ios_start
  108.       end
  109.   end
  110.  
  111.   def parse(messages)
  112.     if !messages || messages == "" || messages == []
  113.       return []
  114.     end
  115.  
  116.     messages.map { |message| ParseMessage.new(message).call }
  117.   end
  118. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement