Module: Denko::Message

Defined in:
lib/denko/message.rb

Constant Summary collapse

BYTE_MAX =
255
VAL_MIN =
0
VAL_MAX =
9999

Class Method Summary collapse

Class Method Details

.encode(command: nil, pin: nil, value: nil, aux_message: nil) ⇒ Object

Raises:

  • (ArgumentError)


7
8
9
10
11
12
13
14
15
16
17
18
19
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
# File 'lib/denko/message.rb', line 7

def self.encode(command: nil, pin: nil, value: nil, aux_message: nil)
  # Start building message backwards with aux_message first.
  if aux_message
    # Convert it to String.
    aux_message = aux_message.to_s

    # Validate aux_message before escaping characters.
    raise ArgumentError, 'aux_message is limited to 528 characters' if aux_message.length > 784

    # Escape \ and \n.
    aux_message = aux_message.gsub("\\","\\\\\\\\").gsub("\n", "\\\n")

    # Start message with aux_message.
    message = ".#{aux_message}"
  else
    # Or start with empty message.
    message = ""
  end

  # Prepend value
  if value
    # Validate value
    if (value.class != Integer || value < VAL_MIN || value > VAL_MAX)
      raise ArgumentError, "value must be integer in range #{VAL_MIN} to #{VAL_MAX}"
    end

    message = ".#{value}#{message}"
  elsif !message.empty?
    message = ".#{message}"
  end

  # Prepend pin
  if pin
    # Validate pin
    if (pin.class != Integer || pin < 0 || pin > BYTE_MAX)
      raise ArgumentError, 'pin must be integer in range 0 to 255'
    end

    message = ".#{pin}#{message}"
  elsif !message.empty?
    message = ".#{message}"
  end

  # Validate command
  raise ArgumentError, 'command missing from message' unless command
  if command.class != Integer || command < 0 || command > BYTE_MAX
    raise ArgumentError, 'command must be Integer in range 0 to 255'
  end

  # Prepend command and append newline.
  message = "#{command}#{message}\n"
end

.pack(type, data, min: nil, max: nil) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/denko/message.rb', line 60

def self.pack(type, data, min: nil, max: nil)
  # Always pack as little endian.
  template =  case type
              when :uint64  then 'Q<*'
              when :uint32  then 'L<*'
              when :uint16  then 'S<*'
              when :uint8   then 'C*'
              else raise ArgumentError, "unsupported pack format '#{type}'"
              end

  # Can pass a single integer to get packed if we always [] then flatten.
  str = [data].flatten.pack(template)

  # Enforce min and max.
  if min && str.length < min
    raise ArgumentError, "too few bytes given (expected at least #{min})"
  end
  if max && str.length > max
    raise ArgumentError, "too many bytes given (expected at most #{max})"
  end

  str
end