Module: MaxCube::Messages::TCP::Parser::MessageL

Defined in:
lib/maxcube/messages/tcp/type/l.rb

Overview

Device list message.

Constant Summary

LENGTHS =
[6, 11, 12].freeze
KEYS =

Mandatory hash keys.

%i[devices].freeze

Instance Method Summary collapse

Instance Method Details

#parse_tcp_l(body) ⇒ Object (private)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/maxcube/messages/tcp/type/l.rb', line 15

def parse_tcp_l(body)
  @io = StringIO.new(decode(body), 'rb')

  hash = { devices: [] }
  until @io.eof?
    subhash = parse_tcp_l_submsg_1

    temperature_msb = parse_tcp_l_submsg_2(subhash) if @length > 6
    parse_tcp_l_submsg_3(subhash, temperature_msb) if @length > 11

    hash[:devices] << subhash
  end

  hash
end

#parse_tcp_l_submsg_1Object (private)



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
62
63
64
65
# File 'lib/maxcube/messages/tcp/type/l.rb', line 33

def parse_tcp_l_submsg_1
  @length = read(1, true)
  unless LENGTHS.include?(@length)
    raise InvalidMessageBody
      .new(@msg_type, "invalid length of submessage (#{@length}):" \
                      " should be in #{LENGTHS}")
  end
  subhash = {
    length: @length,
    rf_address: read(3, true),
    unknown: read(1),
  }
  flags = read(2, true)
  @mode = device_mode(flags & 0x3)
  subhash[:flags] = {
    value: flags,
    mode: @mode,
    dst_setting_active: !((flags & 0x8) >> 3).zero?,
    gateway_known: !((flags & 0x10) >> 4).zero?,
    panel_locked: !((flags & 0x20) >> 5).zero?,
    link_error: !((flags & 0x40) >> 6).zero?,
    low_battery: !((flags & 0x80) >> 7).zero?,
    status_initialized: !((flags & 0x200) >> 9).zero?,
    is_answer: !((flags & 0x400) >> 10).zero?,
    error: !((flags & 0x800) >> 11).zero?,
    valid_info: !((flags & 0x1000) >> 12).zero?,
  }

  subhash
rescue IOError
  raise InvalidMessageBody
    .new(@msg_type, 'unexpected EOF reached at submessage 1st part')
end

#parse_tcp_l_submsg_2(subhash) ⇒ Object (private)



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/maxcube/messages/tcp/type/l.rb', line 67

def parse_tcp_l_submsg_2(subhash)
  subhash[:valve_opening] = read(1, true)

  temperature = read(1, true)
  # This bit may be used later
  temperature_msb = temperature >> 7
  subhash[:temperature] = (temperature & 0x3f).to_f / 2

  date_until = read(2, true)
  year = (date_until & 0x1f) + 2000
  month = ((date_until & 0x80) >> 7) | ((date_until & 0xe000) >> 12)
  day = (date_until & 0x1f00) >> 8

  time_until = read(1, true)
  hours = time_until / 2
  minutes = (time_until % 2) * 30
  # Sometimes when device is in 'auto' mode,
  # this field can contain 'actual_temperature' instead
  # (but never if it is already contained in next byte)
  # !It seems that 'date' is used for 'vacation' mode,
  # but it is not sure ...
  begin
    subhash[:datetime_until] = Time.new(year, month, day,
                                        hours, minutes)
  rescue ArgumentError
    if @mode != :auto || @length > 11
      raise InvalidMessageBody
        .new(@msg_type, "unrecognized message part: #{date_until}" \
                       " (it does not seem to be 'date until'" \
                       " nor 'actual temperature')")
    end
    subhash[:actual_temperature] = date_until.to_f / 10
  end

  temperature_msb
rescue IOError
  raise InvalidMessageBody
    .new(@msg_type,
         'unexpected EOF reached at submessage 2nd part')
end

#parse_tcp_l_submsg_3(subhash, temperature_msb) ⇒ Object (private)



108
109
110
111
112
113
114
115
# File 'lib/maxcube/messages/tcp/type/l.rb', line 108

def parse_tcp_l_submsg_3(subhash, temperature_msb)
  subhash[:actual_temperature] = ((temperature_msb << 8) |
                                  read(1, true)).to_f / 10
rescue IOError
  raise InvalidMessageBody
    .new(@msg_type,
         'unexpected EOF reached at submessage 3rd part')
end