Module: E3DCMqtt::RSCP::DataType
- Defined in:
- lib/e3dc_mqtt/rscp/data_type.rb
Overview
RSCP value types. Each entry knows its byte representation, its fixed length (or nil for variable-length types), and how to pack/unpack a Ruby value.
Constant Summary collapse
- NONE =
0x00- BOOL =
0x01- CHAR8 =
0x02- UCHAR8 =
0x03- INT16 =
0x04- UINT16 =
0x05- INT32 =
0x06- UINT32 =
0x07- INT64 =
0x08- UINT64 =
0x09- FLOAT32 =
0x0A- DOUBLE64 =
0x0B- BITFIELD =
0x0C- CSTRING =
0x0D- CONTAINER =
0x0E- TIMESTAMP =
0x0F- BYTEARRAY =
0x10- ERROR =
0xFF- NAMES =
{ NONE => :none, BOOL => :bool, CHAR8 => :char8, UCHAR8 => :uchar8, INT16 => :int16, UINT16 => :uint16, INT32 => :int32, UINT32 => :uint32, INT64 => :int64, UINT64 => :uint64, FLOAT32 => :float32, DOUBLE64 => :double64, BITFIELD => :bitfield, CSTRING => :cstring, CONTAINER => :container, TIMESTAMP => :timestamp, BYTEARRAY => :bytearray, ERROR => :error }.freeze
- FIXED_LENGTHS =
{ NONE => 0, BOOL => 1, CHAR8 => 1, UCHAR8 => 1, INT16 => 2, UINT16 => 2, INT32 => 4, UINT32 => 4, INT64 => 8, UINT64 => 8, FLOAT32 => 4, DOUBLE64 => 8, BITFIELD => 1, TIMESTAMP => 12, ERROR => 4 }.freeze
- VARIABLE =
Set.new([CSTRING, CONTAINER, BYTEARRAY]).freeze
Class Method Summary collapse
- .fixed_length(type) ⇒ Object
- .name(type) ⇒ Object
-
.pack(type, value) ⇒ Object
Pack a Ruby value into its wire bytes.
- .unpack(type, bytes) ⇒ Object
- .variable?(type) ⇒ Boolean
Class Method Details
.fixed_length(type) ⇒ Object
51 52 53 |
# File 'lib/e3dc_mqtt/rscp/data_type.rb', line 51 def fixed_length(type) FIXED_LENGTHS[type] end |
.name(type) ⇒ Object
47 48 49 |
# File 'lib/e3dc_mqtt/rscp/data_type.rb', line 47 def name(type) NAMES.fetch(type) { raise UnknownDataType, "unknown data type 0x%02x" % type } end |
.pack(type, value) ⇒ Object
Pack a Ruby value into its wire bytes. ‘value` semantics per type:
NONE -> nil
BOOL -> true/false
*INT* / *CHAR -> Integer
FLOAT/DOUBLE -> Float
BITFIELD -> Integer (0..255)
CSTRING -> String (binary-safe UTF-8 bytes written)
BYTEARRAY -> String (binary)
CONTAINER -> Array<Message> (caller handles recursion)
TIMESTAMP -> Time
ERROR -> Integer (uint32 error code)
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 |
# File 'lib/e3dc_mqtt/rscp/data_type.rb', line 70 def pack(type, value) case type when NONE then "".b when BOOL then [value ? 1 : 0].pack("C") when CHAR8 then [value].pack("c") when UCHAR8 then [value].pack("C") when INT16 then [value].pack("s<") when UINT16 then [value].pack("S<") when INT32 then [value].pack("l<") when UINT32 then [value].pack("L<") when INT64 then [value].pack("q<") when UINT64 then [value].pack("Q<") when FLOAT32 then [value].pack("e") when DOUBLE64 then [value].pack("E") when BITFIELD then [value].pack("C") when CSTRING then value.to_s.b when BYTEARRAY then value.to_s.b when TIMESTAMP t = value.utc [t.to_i].pack("q<") + [(t.nsec)].pack("l<") when ERROR then [value].pack("L<") when CONTAINER raise DataTypeMismatch, "CONTAINER must be packed by Message (recursive)" else raise UnknownDataType, "unknown data type 0x%02x" % type end end |
.unpack(type, bytes) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/e3dc_mqtt/rscp/data_type.rb', line 98 def unpack(type, bytes) case type when NONE then nil when BOOL then bytes.unpack1("C") != 0 when CHAR8 then bytes.unpack1("c") when UCHAR8 then bytes.unpack1("C") when INT16 then bytes.unpack1("s<") when UINT16 then bytes.unpack1("S<") when INT32 then bytes.unpack1("l<") when UINT32 then bytes.unpack1("L<") when INT64 then bytes.unpack1("q<") when UINT64 then bytes.unpack1("Q<") when FLOAT32 then bytes.unpack1("e") when DOUBLE64 then bytes.unpack1("E") when BITFIELD then bytes.unpack1("C") when CSTRING s = bytes.dup s.force_encoding(Encoding::UTF_8) s.valid_encoding? ? s : bytes.dup.force_encoding(Encoding::BINARY) when BYTEARRAY then bytes.dup.force_encoding(Encoding::BINARY) when TIMESTAMP secs, nsec = bytes.unpack("q<l<") Time.at(secs, nsec, :nsec).utc when ERROR then bytes.unpack1("L<") when CONTAINER raise DataTypeMismatch, "CONTAINER must be unpacked by Message (recursive)" else raise UnknownDataType, "unknown data type 0x%02x" % type end end |
.variable?(type) ⇒ Boolean
55 56 57 |
# File 'lib/e3dc_mqtt/rscp/data_type.rb', line 55 def variable?(type) VARIABLE.include?(type) end |