Class: BWA::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/bwa/message.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#raw_dataObject (readonly)

Returns the value of attribute raw_data.



79
80
81
# File 'lib/bwa/message.rb', line 79

def raw_data
  @raw_data
end

Class Method Details

.format_duration(hours, minutes) ⇒ Object



74
75
76
# File 'lib/bwa/message.rb', line 74

def format_duration(hours, minutes)
  "#{hours}:#{"%02d" % minutes}"
end

.format_time(hour, minute, twenty_four_hour_time = true) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/bwa/message.rb', line 63

def format_time(hour, minute, twenty_four_hour_time = true)
  if twenty_four_hour_time
    print_hour = "%02d" % hour
  else
    print_hour = hour % 12
    print_hour = 12 if print_hour == 0
    am_pm = (hour >= 12 ? "PM" : "AM")
  end
  "#{print_hour}:#{"%02d" % minute}#{am_pm}"
end

.inherited(klass) ⇒ Object



15
16
17
18
# File 'lib/bwa/message.rb', line 15

def inherited(klass)
  @messages ||= []
  @messages << klass
end

.parse(data) ⇒ Object

Raises:



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/bwa/message.rb', line 20

def parse(data)
  offset = -1
  message_type = length = message_class = nil
  loop do
    offset += 1
    return nil if data.length - offset < 5

    next unless data[offset] == '~'
    length = data[offset + 1].ord
    # impossible message
    next if length < 5

    # don't have enough data for what this message wants;
    # it could be garbage on the line so keep scanning
    next if length + 2 > data.length - offset

    next unless data[offset + length + 1] == '~'

    next unless CRC.checksum(data.slice(offset + 1, length - 1)) == data[offset + length].ord
    break
  end

  puts "discarding invalid data prior to message #{data[0...offset].unpack('H*').first}" unless offset == 0
  #puts "read #{data.slice(offset, length + 2).unpack('H*').first}"

  message_type = data.slice(offset + 2, 3)
  klass = @messages.find { |k| k::MESSAGE_TYPE == message_type }


  return [nil, offset + length + 2] if [
                "\xfe\xbf\x00".force_encoding(Encoding::ASCII_8BIT),
                "\x10\xbf\xe1".force_encoding(Encoding::ASCII_8BIT),
                "\x10\xbf\x07".force_encoding(Encoding::ASCII_8BIT)].include?(message_type)

  raise InvalidMessage.new("Unrecognized message #{message_type.unpack("H*").first}", data) unless klass
  raise InvalidMessage.new("Unrecognized data length (#{length}) for message #{klass}", data) unless length - 5 == klass::MESSAGE_LENGTH

  message = klass.new
  message.parse(data.slice(offset + 5, length - 5))
  message.instance_variable_set(:@raw_data, data.slice(offset, length + 2))
  [message, offset + length + 2]
end

Instance Method Details

#inspectObject



91
92
93
# File 'lib/bwa/message.rb', line 91

def inspect
  "#<#{self.class.name} #{raw_data.unpack("H*").first}>"
end

#parse(_data) ⇒ Object



81
82
# File 'lib/bwa/message.rb', line 81

def parse(_data)
end

#serialize(message = "") ⇒ Object



84
85
86
87
88
89
# File 'lib/bwa/message.rb', line 84

def serialize(message = "")
  length = message.length + 5
  full_message = "#{length.chr}#{self.class::MESSAGE_TYPE}#{message}".force_encoding(Encoding::ASCII_8BIT)
  checksum = CRC.checksum(full_message)
  "\x7e#{full_message}#{checksum.chr}\x7e".force_encoding(Encoding::ASCII_8BIT)
end