Class: SDN::Message
- Inherits:
-
Object
- Object
- SDN::Message
- Includes:
- Helpers
- Defined in:
- lib/sdn/message.rb,
lib/sdn/message/get.rb,
lib/sdn/message/set.rb,
lib/sdn/message/post.rb,
lib/sdn/message/control.rb,
lib/sdn/message/helpers.rb,
lib/sdn/message/ilt2/get.rb,
lib/sdn/message/ilt2/set.rb,
lib/sdn/message/ilt2/post.rb,
lib/sdn/message/ilt2/master_control.rb
Overview
Base type for all SDN protocol frames and message-specific serializers/parsers.
Direct Known Subclasses
ILT2::GetMotorIP, ILT2::PostIRConfig, ILT2::PostLockStatus, ILT2::PostMotorIP, ILT2::PostMotorPosition, ILT2::SetLockStatus, ILT2::SetMotorIP, ILT2::SetMotorPosition
Defined Under Namespace
Modules: Helpers, ILT2 Classes: Ack, GetGroupAddr, GetMotorDirection, GetMotorIP, GetMotorLimits, GetMotorPosition, GetMotorRollingSpeed, GetMotorStatus, GetNetworkLock, GetNodeAddr, GetNodeAppVersion, GetNodeLabel, GetNodeSerialNumber, GetNodeStackVersion, Lock, Move, MoveOf, MoveTo, Nack, PostGroupAddr, PostMotorDirection, PostMotorIP, PostMotorLimits, PostMotorPosition, PostMotorRollingSpeed, PostMotorStatus, PostNetworkLock, PostNodeAddr, PostNodeAppVersion, PostNodeLabel, PostNodeSerialNumber, PostNodeStackVersion, SetFactoryDefault, SetGroupAddr, SetMotorDirection, SetMotorIP, SetMotorLimits, SetMotorRollingSpeed, SetNetworkLock, SetNodeLabel, SimpleRequest, Stop, UnknownMessage, Wink
Instance Attribute Summary collapse
-
#ack_requested ⇒ true, false
Whether this message requests an acknowledgement.
-
#dest ⇒ (Integer, Integer, Integer)
Destination address for the message.
-
#node_type ⇒ Symbol, Integer
Message sender node type.
-
#src ⇒ (Integer, Integer, Integer)
Source address for the message.
Class Method Summary collapse
-
.expected_response?(message) ⇒ true, false
Determines whether a received message satisfies the expected response for this request type.
-
.parse(data) ⇒ (SDN::Message, Integer)
Attempts to parse the first valid SDN message from a byte stream.
Instance Method Summary collapse
- #==(other) ⇒ true, false
-
#initialize(node_type: nil, ack_requested: false, src: nil, dest: nil) ⇒ Message
constructor
Builds a message envelope with optional addressing and acknowledgement behavior.
- #inspect ⇒ String (also: #to_s)
-
#parse(params) ⇒ void
Parses protocol-specific parameter bytes into this message instance.
-
#serialize ⇒ String
Serializes the message to a packed SDN frame.
Methods included from Helpers
#checksum, #from_number, #from_string, #group_address?, #node_type_from_number, #node_type_to_number, #node_type_to_string, #parse_address, #print_address, #to_number, #to_string, #transform_param
Constructor Details
#initialize(node_type: nil, ack_requested: false, src: nil, dest: nil) ⇒ Message
Builds a message envelope with optional addressing and acknowledgement behavior.
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/sdn/message.rb', line 128 def initialize(node_type: nil, ack_requested: false, src: nil, dest: nil) @node_type = node_type || 0 @ack_requested = ack_requested if src.nil? && !dest.nil? && group_address?(dest) src = dest dest = nil end @src = src || [0, 0, 1] @dest = dest || [0, 0, 0] end |
Instance Attribute Details
#ack_requested ⇒ true, false
Whether this message requests an acknowledgement.
110 111 112 |
# File 'lib/sdn/message.rb', line 110 def ack_requested @ack_requested end |
#dest ⇒ (Integer, Integer, Integer)
Destination address for the message.
120 121 122 |
# File 'lib/sdn/message.rb', line 120 def dest @dest end |
#node_type ⇒ Symbol, Integer
Message sender node type.
105 106 107 |
# File 'lib/sdn/message.rb', line 105 def node_type @node_type end |
#src ⇒ (Integer, Integer, Integer)
Source address for the message.
115 116 117 |
# File 'lib/sdn/message.rb', line 115 def src @src end |
Class Method Details
.expected_response?(message) ⇒ true, false
Determines whether a received message satisfies the expected response for this request type.
26 27 28 29 30 31 32 |
# File 'lib/sdn/message.rb', line 26 def expected_response?() if /::Get([A-Za-z]+)/.match?(name) .class.name == name.sub("::Get", "::Post") # rubocop:disable Style/ClassEqualityComparison else .is_a?(Ack) || .is_a?(Nack) end end |
.parse(data) ⇒ (SDN::Message, Integer)
Attempts to parse the first valid SDN message from a byte stream.
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/sdn/message.rb', line 39 def parse(data) offset = -1 msg = length = ack_requested = = nil # we loop here scanning for a valid message loop do offset += 1 # give these weird messages a chance result = ILT2::MasterControl.parse(data) return result if result return [nil, 0] if data.length - offset < 11 msg = to_number(data[offset]) length = to_number(data[offset + 1]) ack_requested = length & 0x80 == 0x80 length &= 0x7f # impossible message next if length < 11 || length > 43 # don't have enough data for what this message wants; # it could be garbage on the line so keep scanning next if length > data.length - offset = [msg] || UnknownMessage calculated_sum = checksum(data.slice(offset, length - 2)) read_sum = data.slice(offset + length - 2, 2) next unless read_sum == calculated_sum break end node_type = node_type_from_number(to_number(data[offset + 2])) src = transform_param(data.slice(offset + 3, 3)) dest = transform_param(data.slice(offset + 6, 3)) begin result = .new(node_type:, ack_requested:, src:, dest:) result.parse(data.slice(offset + 9, length - 11)) result.msg = msg if == UnknownMessage rescue ArgumentError => e SDN.logger.warn "Discarding illegal message of type #{.name}: #{e}" result = nil end [result, offset + length] end |
Instance Method Details
#==(other) ⇒ true, false
167 168 169 |
# File 'lib/sdn/message.rb', line 167 def ==(other) serialize == other.serialize end |
#inspect ⇒ String Also known as: to_s
172 173 174 175 176 177 178 179 180 |
# File 'lib/sdn/message.rb', line 172 def inspect format("#<%s @node_type=%s, @ack_requested=%s, @src=%s, @dest=%s%s>", self.class.name, node_type_to_string(node_type), ack_requested, print_address(src), print_address(dest), class_inspect) end |
#parse(params) ⇒ void
This method returns an undefined value.
Parses protocol-specific parameter bytes into this message instance.
146 147 148 149 150 151 152 |
# File 'lib/sdn/message.rb', line 146 def parse(params) return unless self.class.const_defined?(:PARAMS_LENGTH) && params.length != self.class.const_get(:PARAMS_LENGTH) raise MalformedMessage, "unrecognized params for #{self.class.name}: #{params.map do |b| format("%02x", b) end}" end |
#serialize ⇒ String
Serializes the message to a packed SDN frame.
157 158 159 160 161 162 163 164 |
# File 'lib/sdn/message.rb', line 157 def serialize result = transform_param(node_type_to_number(node_type)) + transform_param(src) + transform_param(dest) + params length = result.length + 4 length |= 0x80 if ack_requested result = transform_param(self.class.const_get(:MSG)) + transform_param(length) + result result.concat(checksum(result)) result.pack("C*") end |