Class: Cosmos::TemplateProtocol
- Inherits:
-
TerminatedProtocol
- Object
- Protocol
- BurstProtocol
- TerminatedProtocol
- Cosmos::TemplateProtocol
- Defined in:
- lib/cosmos/interfaces/protocols/template_protocol.rb
Overview
Protocol which delineates packets using delimiter characters. Designed for text based protocols which expect a command and send a response. The protocol handles sending the command and capturing the response.
Instance Attribute Summary
Attributes inherited from Protocol
Instance Method Summary collapse
- #connect_reset ⇒ Object
- #disconnect_reset ⇒ Object
- #handle_error(msg) ⇒ Object
-
#initialize(write_termination_characters, read_termination_characters, ignore_lines = 0, initial_read_delay = nil, response_lines = 1, strip_read_termination = true, discard_leading_bytes = 0, sync_pattern = nil, fill_fields = false, response_timeout = 5.0, response_polling_period = 0.02, raise_exceptions = false, allow_empty_data = nil) ⇒ TemplateProtocol
constructor
A new instance of TemplateProtocol.
- #post_write_interface(packet, data) ⇒ Object
- #read_data(data) ⇒ Object
- #read_packet(packet) ⇒ Object
- #reset ⇒ Object
- #write_packet(packet) ⇒ Object
Methods inherited from TerminatedProtocol
Methods inherited from BurstProtocol
#handle_sync_pattern, #log_discard, #reduce_to_single_packet, #write_data
Methods inherited from Protocol
Constructor Details
#initialize(write_termination_characters, read_termination_characters, ignore_lines = 0, initial_read_delay = nil, response_lines = 1, strip_read_termination = true, discard_leading_bytes = 0, sync_pattern = nil, fill_fields = false, response_timeout = 5.0, response_polling_period = 0.02, raise_exceptions = false, allow_empty_data = nil) ⇒ TemplateProtocol
Returns a new instance of TemplateProtocol.
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 83 84 85 86 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 49 def initialize( write_termination_characters, read_termination_characters, ignore_lines = 0, initial_read_delay = nil, response_lines = 1, strip_read_termination = true, discard_leading_bytes = 0, sync_pattern = nil, fill_fields = false, response_timeout = 5.0, response_polling_period = 0.02, raise_exceptions = false, allow_empty_data = nil ) super( write_termination_characters, read_termination_characters, strip_read_termination, discard_leading_bytes, sync_pattern, fill_fields, allow_empty_data) @response_template = nil @response_packet = nil @response_target_name = nil @response_packets = [] @write_block_queue = Queue.new @ignore_lines = ignore_lines.to_i @response_lines = response_lines.to_i @initial_read_delay = ConfigParser.handle_nil(initial_read_delay) @initial_read_delay = @initial_read_delay.to_f if @initial_read_delay @response_timeout = ConfigParser.handle_nil(response_timeout) @response_timeout = @response_timeout.to_f if @response_timeout @response_polling_period = response_polling_period.to_f @connect_complete_time = nil @raise_exceptions = ConfigParser.handle_true_false(raise_exceptions) end |
Instance Method Details
#connect_reset ⇒ Object
93 94 95 96 97 98 99 100 101 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 93 def connect_reset super() begin @write_block_queue.pop(true) while @write_block_queue.length > 0 rescue end @connect_complete_time = Time.now + @initial_read_delay if @initial_read_delay end |
#disconnect_reset ⇒ Object
103 104 105 106 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 103 def disconnect_reset super() @write_block_queue << nil # Unblock the write block queue end |
#handle_error(msg) ⇒ Object
256 257 258 259 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 256 def handle_error(msg) Logger.error(msg) raise msg if @raise_exceptions end |
#post_write_interface(packet, data) ⇒ Object
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 230 def post_write_interface(packet, data) if @response_template && @response_packet if @response_timeout response_timeout_time = Time.now + @response_timeout else response_timeout_time = nil end # Block the write until the response is received begin @write_block_queue.pop(true) rescue sleep(@response_polling_period) retry if !response_timeout_time retry if response_timeout_time and Time.now < response_timeout_time handle_error("#{@interface ? @interface.name : ""}: Timeout waiting for response") end @response_template = nil @response_packet = nil @response_target_name = nil @response_packets.clear end return super(packet, data) end |
#read_data(data) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 108 def read_data(data) return super(data) if data.length <= 0 # Drop all data until the initial_read_delay is complete. # This gets rid of unused welcome messages, # prompts, and other junk on initial connections if @initial_read_delay and @initial_read_delay_needed and @connect_complete_time return :STOP if Time.now < @connect_complete_time @initial_read_delay_needed = false end super(data) end |
#read_packet(packet) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 122 def read_packet(packet) if @response_template && @response_packet # If lines make it this far they are part of a response @response_packets << packet return :STOP if @response_packets.length < (@ignore_lines + @response_lines) @ignore_lines.times do @response_packets.shift end response_string = '' @response_lines.times do response = @response_packets.shift response_string << response.buffer end # Grab the response packet specified in the command result_packet = System.telemetry.packet(@response_target_name, @response_packet).clone result_packet.received_time = nil result_packet.id_items.each do |item| result_packet.write_item(item, item.id_value, :RAW) end # Convert the response template into a Regexp response_item_names = [] response_template = @response_template.clone response_template_items = @response_template.scan(/<.*?>/) response_template_items.each do |item| response_item_names << item[1..-2] response_template.gsub!(item, "(.*)") end response_regexp = Regexp.new(response_template) # Scan the response for the variables in brackets <VARIABLE> # Write the packet value with each of the values received response_values = response_string.scan(response_regexp)[0] if !response_values || (response_values.length != response_item_names.length) handle_error("#{@interface ? @interface.name : ""}: Unexpected response: #{response_string}") else response_values.each_with_index do |value, i| result_packet.write(response_item_names[i], value) rescue => error handle_error("#{@interface ? @interface.name : ""}: Could not write value #{value} due to #{error.}") break end end @response_packets.clear # Release the write if @response_template && @response_packet @write_block_queue << nil end return result_packet else return packet end end |
#reset ⇒ Object
88 89 90 91 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 88 def reset super() @initial_read_delay_needed = true end |
#write_packet(packet) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/cosmos/interfaces/protocols/template_protocol.rb', line 182 def write_packet(packet) # Make sure we are past the initial data dropping period if @initial_read_delay and @initial_read_delay_needed and @connect_complete_time and Time.now < @connect_complete_time delay_needed = @connect_complete_time - Time.now sleep(delay_needed) if delay_needed > 0 end # First grab the response template and response packet (if there is one) begin @response_template = packet.read("RSP_TEMPLATE").strip @response_packet = packet.read("RSP_PACKET").strip @response_target_name = packet.target_name # If the template or packet are empty set them to nil. This allows for # the user to remove the RSP_TEMPLATE and RSP_PACKET values and avoid # any response timeouts if @response_template.empty? || @response_packet.empty? @response_template = nil @response_packet = nil @response_target_name = nil end rescue # If there is no response template we set to nil @response_template = nil @response_packet = nil @response_target_name = nil end # Grab the command template because that is all we eventually send @template = packet.read("CMD_TEMPLATE") # Create a new packet to populate with the template raw_packet = Packet.new(nil, nil) raw_packet.buffer = @template raw_packet = super(raw_packet) return raw_packet if Symbol === raw_packet data = raw_packet.buffer(false) # Scan the template for variables in brackets <VARIABLE> # Read these values from the packet and substitute them in the template # and in the @response_packet name @template.scan(/<(.*?)>/).each do |variable| value = packet.read(variable[0], :RAW).to_s data.gsub!("<#{variable[0]}>", value) @response_packet.gsub!("<#{variable[0]}>", value) if @response_packet end return raw_packet end |