cosmos 4.0.1-universal-java-1.8 → 4.0.2-universal-java-1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/config/_id_items.yaml +1 -1
- data/data/config/_id_params.yaml +1 -1
- data/data/config/_items.yaml +1 -1
- data/data/config/_params.yaml +1 -1
- data/data/config/cmd_tlm_server.yaml +14 -0
- data/data/config/command.yaml +2 -0
- data/data/config/command_modifiers.yaml +18 -0
- data/data/config/item_modifiers.yaml +39 -0
- data/data/config/param_item_modifiers.yaml +5 -0
- data/data/config/parameter_modifiers.yaml +36 -0
- data/data/config/protocols.yaml +22 -6
- data/data/config/system.yaml +17 -0
- data/data/config/target.yaml +9 -0
- data/data/config/telemetry.yaml +7 -0
- data/data/config/telemetry_modifiers.yaml +13 -0
- data/data/config/tlm_viewer.yaml +5 -0
- data/data/crc.txt +20 -20
- data/demo/config/data/crc.txt +3 -3
- data/demo/config/targets/INST/screens/hs.txt +1 -1
- data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +5 -10
- data/demo/config/targets/SYSTEM/lib/limits_groups.rb +33 -17
- data/lib/cosmos/core_ext/string.rb +1 -1
- data/lib/cosmos/gui/utilities/script_module_gui.rb +3 -3
- data/lib/cosmos/interfaces/protocols/length_protocol.rb +1 -1
- data/lib/cosmos/interfaces/protocols/template_protocol.rb +37 -6
- data/lib/cosmos/interfaces/udp_interface.rb +3 -3
- data/lib/cosmos/packets/packet_config.rb +1 -0
- data/lib/cosmos/packets/parsers/format_string_parser.rb +1 -0
- data/lib/cosmos/packets/parsers/limits_parser.rb +1 -0
- data/lib/cosmos/packets/parsers/state_parser.rb +3 -0
- data/lib/cosmos/packets/telemetry.rb +1 -1
- data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +1 -1
- data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +4 -3
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/screen.rb +3 -3
- data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +5 -10
- data/lib/cosmos/tools/tlm_viewer/widgets/limits_widget.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +3 -1
- data/lib/cosmos/top_level.rb +2 -4
- data/lib/cosmos/utilities/csv.rb +1 -1
- data/lib/cosmos/version.rb +4 -4
- data/spec/interfaces/protocols/template_protocol_spec.rb +119 -15
- data/spec/interfaces/udp_interface_spec.rb +8 -2
- data/spec/packets/packet_config_spec.rb +11 -0
- data/spec/packets/parsers/format_string_parser_spec.rb +11 -0
- data/spec/packets/parsers/limits_parser_spec.rb +21 -10
- data/spec/packets/parsers/packet_item_parser_spec.rb +5 -5
- data/spec/packets/parsers/state_parser_spec.rb +33 -0
- data/spec/tools/cmd_tlm_server/limits_groups_background_task_spec.rb +4 -4
- metadata +2 -2
@@ -30,6 +30,12 @@ module Cosmos
|
|
30
30
|
# @param discard_leading_bytes (see TerminatedProtocol#initialize)
|
31
31
|
# @param sync_pattern (see TerminatedProtocol#initialize)
|
32
32
|
# @param fill_fields (see TerminatedProtocol#initialize)
|
33
|
+
# @param response_timeout [Float] Number of seconds to wait before timing out
|
34
|
+
# when waiting for a response
|
35
|
+
# @param response_polling_period [Float] Number of seconds to wait between polling
|
36
|
+
# for a response
|
37
|
+
# @param raise_exceptions [String] Whether to raise exceptions when errors
|
38
|
+
# occur in the protocol like unexpected responses or response timeouts.
|
33
39
|
def initialize(
|
34
40
|
write_termination_characters,
|
35
41
|
read_termination_characters,
|
@@ -41,7 +47,8 @@ module Cosmos
|
|
41
47
|
sync_pattern = nil,
|
42
48
|
fill_fields = false,
|
43
49
|
response_timeout = 5.0,
|
44
|
-
response_polling_period = 0.02
|
50
|
+
response_polling_period = 0.02,
|
51
|
+
raise_exceptions = false
|
45
52
|
)
|
46
53
|
super(
|
47
54
|
write_termination_characters,
|
@@ -62,6 +69,7 @@ module Cosmos
|
|
62
69
|
@response_timeout = @response_timeout.to_f if @response_timeout
|
63
70
|
@response_polling_period = response_polling_period.to_f
|
64
71
|
@connect_complete_time = nil
|
72
|
+
@raise_exceptions = ConfigParser.handle_true_false(raise_exceptions)
|
65
73
|
end
|
66
74
|
|
67
75
|
def reset
|
@@ -128,9 +136,17 @@ module Cosmos
|
|
128
136
|
# Scan the response for the variables in brackets <VARIABLE>
|
129
137
|
# Write the packet value with each of the values received
|
130
138
|
response_values = response_string.scan(response_regexp)[0]
|
131
|
-
|
132
|
-
|
133
|
-
|
139
|
+
if !response_values || (response_values.length != response_item_names.length)
|
140
|
+
handle_error("#{@interface.name}: Unexpected response: #{response_string}")
|
141
|
+
else
|
142
|
+
response_values.each_with_index do |value, i|
|
143
|
+
begin
|
144
|
+
result_packet.write(response_item_names[i], value)
|
145
|
+
rescue => error
|
146
|
+
handle_error("#{@interface.name}: Could not write value #{value} due to #{error.message}")
|
147
|
+
break
|
148
|
+
end
|
149
|
+
end
|
134
150
|
end
|
135
151
|
|
136
152
|
@response_packets.clear
|
@@ -157,6 +173,13 @@ module Cosmos
|
|
157
173
|
begin
|
158
174
|
@response_template = packet.read("RSP_TEMPLATE").strip
|
159
175
|
@response_packet = packet.read("RSP_PACKET").strip
|
176
|
+
# If the template or packet are empty set them to nil. This allows for
|
177
|
+
# the user to remove the RSP_TEMPLATE and RSP_PACKET values and avoid
|
178
|
+
# any response timeouts
|
179
|
+
if @response_template.empty? || @response_packet.empty?
|
180
|
+
@response_template = nil
|
181
|
+
@response_packet = nil
|
182
|
+
end
|
160
183
|
rescue
|
161
184
|
# If there is no response template we set to nil
|
162
185
|
@response_template = nil
|
@@ -174,8 +197,11 @@ module Cosmos
|
|
174
197
|
data = raw_packet.buffer(false)
|
175
198
|
# Scan the template for variables in brackets <VARIABLE>
|
176
199
|
# Read these values from the packet and substitute them in the template
|
200
|
+
# and in the @response_packet name
|
177
201
|
@template.scan(/<(.*?)>/).each do |variable|
|
178
|
-
|
202
|
+
value = packet.read(variable[0], :RAW).to_s
|
203
|
+
data.gsub!("<#{variable[0]}>", value)
|
204
|
+
@response_packet.gsub!("<#{variable[0]}>", value) if @response_packet
|
179
205
|
end
|
180
206
|
|
181
207
|
return raw_packet
|
@@ -196,7 +222,7 @@ module Cosmos
|
|
196
222
|
sleep(@response_polling_period)
|
197
223
|
retry if !response_timeout_time
|
198
224
|
retry if response_timeout_time and Time.now < response_timeout_time
|
199
|
-
|
225
|
+
handle_error("#{@interface.name}: Timeout waiting for response")
|
200
226
|
end
|
201
227
|
|
202
228
|
@response_template = nil
|
@@ -205,5 +231,10 @@ module Cosmos
|
|
205
231
|
end
|
206
232
|
return super(packet, data)
|
207
233
|
end
|
234
|
+
|
235
|
+
def handle_error(msg)
|
236
|
+
Logger.error(msg)
|
237
|
+
raise msg if @raise_exceptions
|
238
|
+
end
|
208
239
|
end
|
209
240
|
end
|
@@ -42,7 +42,7 @@ module Cosmos
|
|
42
42
|
@hostname = ConfigParser.handle_nil(hostname)
|
43
43
|
if @hostname
|
44
44
|
@hostname = @hostname.to_s
|
45
|
-
@hostname = '127.0.0.1' if @hostname.casecmp('LOCALHOST')
|
45
|
+
@hostname = '127.0.0.1' if @hostname.casecmp('LOCALHOST').zero?
|
46
46
|
end
|
47
47
|
@write_dest_port = ConfigParser.handle_nil(write_dest_port)
|
48
48
|
@write_dest_port = write_dest_port.to_i if @write_dest_port
|
@@ -51,7 +51,7 @@ module Cosmos
|
|
51
51
|
@write_src_port = ConfigParser.handle_nil(write_src_port)
|
52
52
|
@write_src_port = @write_src_port.to_i if @write_src_port
|
53
53
|
@interface_address = ConfigParser.handle_nil(interface_address)
|
54
|
-
if @interface_address && @interface_address.casecmp('LOCALHOST')
|
54
|
+
if @interface_address && @interface_address.casecmp('LOCALHOST').zero?
|
55
55
|
@interface_address = '127.0.0.1'
|
56
56
|
end
|
57
57
|
@ttl = ttl.to_i
|
@@ -61,7 +61,7 @@ module Cosmos
|
|
61
61
|
@read_timeout = ConfigParser.handle_nil(read_timeout)
|
62
62
|
@read_timeout = @read_timeout.to_f if @read_timeout
|
63
63
|
@bind_address = ConfigParser.handle_nil(bind_address)
|
64
|
-
if @bind_address && @bind_address.casecmp('LOCALHOST')
|
64
|
+
if @bind_address && @bind_address.casecmp('LOCALHOST').zero?
|
65
65
|
@bind_address = '127.0.0.1'
|
66
66
|
end
|
67
67
|
@write_socket = nil
|
@@ -1283,6 +1283,7 @@ module Cosmos
|
|
1283
1283
|
|
1284
1284
|
# Define the units of the current telemetry item
|
1285
1285
|
when 'UNITS'
|
1286
|
+
raise parser.error("Items with STATE can't define UNITS") if @current_item.states
|
1286
1287
|
usage = "UNITS <FULL UNITS NAME> <ABBREVIATED UNITS NAME>"
|
1287
1288
|
parser.verify_num_parameters(2, 2, usage)
|
1288
1289
|
@current_item.units_full = params[0]
|
@@ -14,6 +14,7 @@ module Cosmos
|
|
14
14
|
# @param parser [ConfigParser] Configuration parser
|
15
15
|
# @param item [Packet] The current item
|
16
16
|
def self.parse(parser, item)
|
17
|
+
raise parser.error("Items with STATE can't define FORMAT_STRING") if item.states
|
17
18
|
@parser = FormatStringParser.new(parser)
|
18
19
|
@parser.verify_parameters()
|
19
20
|
@parser.create_format_string(item)
|
@@ -18,6 +18,7 @@ module Cosmos
|
|
18
18
|
# @param warnings [Array<String>] Array of string warnings which will be
|
19
19
|
# appended with any warnings found when parsing the limits
|
20
20
|
def self.parse(parser, packet, cmd_or_tlm, item, warnings)
|
21
|
+
raise parser.error("Items with STATE can't define LIMITS") if item.states
|
21
22
|
@parser = LimitsParser.new(parser)
|
22
23
|
@parser.verify_parameters(cmd_or_tlm)
|
23
24
|
@parser.create_limits(packet, item, warnings)
|
@@ -20,6 +20,9 @@ module Cosmos
|
|
20
20
|
# @param warnings [Array<String>] Array of string warnings which will be
|
21
21
|
# appended with any warnings found when parsing the limits
|
22
22
|
def self.parse(parser, packet, cmd_or_tlm, item, warnings)
|
23
|
+
raise parser.error("Items with LIMITS can't define STATE") if item.limits.values
|
24
|
+
raise parser.error("Items with FORMAT_STRING can't define STATE") if item.format_string
|
25
|
+
raise parser.error("Items with UNITS can't define STATE") if item.units
|
23
26
|
@parser = StateParser.new(parser)
|
24
27
|
@parser.verify_parameters(cmd_or_tlm)
|
25
28
|
@parser.create_state(packet, cmd_or_tlm, item, warnings)
|
@@ -166,7 +166,7 @@ module Cosmos
|
|
166
166
|
# @param packet_name (see #packet) The packet name. LATEST is supported.
|
167
167
|
# @return [Array<PacketItem>] The telemetry item names for the given target and packet name
|
168
168
|
def item_names(target_name, packet_name)
|
169
|
-
if LATEST_PACKET_NAME.casecmp(packet_name)
|
169
|
+
if LATEST_PACKET_NAME.casecmp(packet_name).zero?
|
170
170
|
target_upcase = target_name.to_s.upcase
|
171
171
|
target_latest_data = @config.latest_data[target_upcase]
|
172
172
|
raise "Telemetry Target '#{target_upcase}' does not exist" unless target_latest_data
|
@@ -568,7 +568,7 @@ module Cosmos
|
|
568
568
|
end
|
569
569
|
|
570
570
|
# Finds the given filename by looking in the system sequences path as
|
571
|
-
# well as in each target's sequences directory. If the file can
|
571
|
+
# well as in each target's sequences directory. If the file can't be
|
572
572
|
# found an Error dialog is created.
|
573
573
|
# @param filename [String] Filename to locate
|
574
574
|
def find_sequence(filename)
|
@@ -18,9 +18,10 @@ module Cosmos
|
|
18
18
|
FUTURE_TIME = Time.new("3000")
|
19
19
|
PAST_TIME = Time.new("1900")
|
20
20
|
|
21
|
-
def initialize(initial_delay = 0)
|
21
|
+
def initialize(initial_delay = 0, task_delay = 0.5)
|
22
22
|
super()
|
23
23
|
@initial_delay = Float(initial_delay)
|
24
|
+
@task_delay = Float(task_delay)
|
24
25
|
@name = "Limits Groups"
|
25
26
|
@groups = get_limits_groups()
|
26
27
|
# Initialize all the group names as instance variables
|
@@ -87,9 +88,9 @@ module Cosmos
|
|
87
88
|
check_methods.each {|method| self.send(method.intern) }
|
88
89
|
now = Time.now
|
89
90
|
@status = "#{now.formatted}: Checking groups took #{now - start}s"
|
90
|
-
sleep_time =
|
91
|
+
sleep_time = @task_delay - (now - start)
|
91
92
|
sleep_time = 0 if sleep_time < 0
|
92
|
-
broken = @sleeper.sleep(sleep_time)
|
93
|
+
broken = @sleeper.sleep(sleep_time)
|
93
94
|
break if broken
|
94
95
|
end
|
95
96
|
end
|
@@ -428,7 +428,7 @@ module Cosmos
|
|
428
428
|
# Build the index into the hash of the form "TARGET_NAME PACKET_NAME"
|
429
429
|
# Note that + is used to create a new object and then << is used to concatenate
|
430
430
|
# to the new object.
|
431
|
-
if packet_name.casecmp(Telemetry::LATEST_PACKET_NAME)
|
431
|
+
if packet_name.casecmp(Telemetry::LATEST_PACKET_NAME).zero?
|
432
432
|
packets = System.telemetry.latest_packets(target_name, data_object.item_name)
|
433
433
|
packets.each do |packet|
|
434
434
|
index = (packet.target_name + ' ') << packet.packet_name
|
@@ -329,7 +329,7 @@ module Cosmos
|
|
329
329
|
end
|
330
330
|
|
331
331
|
unless @widgets.invalid.empty?
|
332
|
-
Qt::MessageBox.information(self, "Screen #{@full_name}", "
|
332
|
+
Qt::MessageBox.information(self, "Screen #{@full_name}", "In #{filename}, the following telemetry items could not be created: \n" + @widgets.invalid.join("\n"))
|
333
333
|
end
|
334
334
|
|
335
335
|
# Process all settings before we show the screen
|
@@ -383,8 +383,8 @@ module Cosmos
|
|
383
383
|
System.telemetry.packet_and_item(*parameters[0..2])
|
384
384
|
widget = klass.new(layout_stack[-1], *parameters)
|
385
385
|
end
|
386
|
-
rescue
|
387
|
-
@widgets.invalid << parameters.join(" ")
|
386
|
+
rescue => err
|
387
|
+
@widgets.invalid << "#{parser.line_number}: #{parameters.join(" ").strip} due to #{err.message}"
|
388
388
|
return nil
|
389
389
|
end
|
390
390
|
else
|
@@ -12,25 +12,20 @@ require 'cosmos'
|
|
12
12
|
require 'cosmos/tools/tlm_viewer/widgets/formatvalue_widget'
|
13
13
|
|
14
14
|
module Cosmos
|
15
|
-
|
16
|
-
# FormatfontvalueWidget class
|
17
|
-
#
|
18
15
|
# This class implements a value with configurable font values. The font
|
19
16
|
# can also be updated after it is created.
|
20
17
|
# It inherits from the FormatvalueWidget class.
|
21
18
|
class FormatfontvalueWidget < FormatvalueWidget
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def initialize(parent_layout, target_name, packet_name, item_name, format_string,
|
20
|
+
value_type = :CONVERTED, characters = 12, font_name = 'arial',
|
21
|
+
font_size = 100, font_weight = Qt::Font::Normal, font_italics = false)
|
25
22
|
super(parent_layout, target_name, packet_name, item_name, format_string, value_type, characters)
|
26
|
-
setFont(Cosmos.getFont(font_name, font_size.to_i, font_weight,
|
23
|
+
setFont(Cosmos.getFont(font_name, font_size.to_i, font_weight, font_italics))
|
27
24
|
setFixedWidth(self.fontMetrics.width('X') * characters.to_i + 10)
|
28
25
|
end
|
29
26
|
|
30
27
|
def font=(font)
|
31
28
|
setFont(font)
|
32
29
|
end
|
33
|
-
|
34
30
|
end
|
35
|
-
|
36
|
-
end # module Cosmos
|
31
|
+
end
|
@@ -20,7 +20,7 @@ module Cosmos
|
|
20
20
|
|
21
21
|
def initialize(parent_layout, target_name, packet_name, item_name, value_type, width, height)
|
22
22
|
super(target_name, packet_name, item_name, value_type)
|
23
|
-
@value_type
|
23
|
+
raise "Invalid value_type #{@value_type} for LimitsWidget" if @value_type == :RAW
|
24
24
|
@width = width.to_i
|
25
25
|
@height = height.to_i
|
26
26
|
@value = 0
|
@@ -17,11 +17,13 @@ module Cosmos
|
|
17
17
|
include Widget
|
18
18
|
include LayoutWidget
|
19
19
|
|
20
|
-
def initialize(parent_layout, num_columns,
|
20
|
+
def initialize(parent_layout, num_columns, horizontal_spacing = 0, vertical_spacing = 0)
|
21
21
|
super()
|
22
22
|
@num_columns = num_columns.to_i
|
23
23
|
@row = 0
|
24
24
|
@column = 0
|
25
|
+
setHorizontalSpacing(horizontal_spacing.to_i)
|
26
|
+
setVerticalSpacing(vertical_spacing.to_i)
|
25
27
|
parent_layout.addLayout(self) if parent_layout
|
26
28
|
end
|
27
29
|
|
data/lib/cosmos/top_level.rb
CHANGED
@@ -607,8 +607,7 @@ module Cosmos
|
|
607
607
|
#
|
608
608
|
# @param class_name_or_class_filename [String] The name of the class or the file which contains the
|
609
609
|
# Ruby class to require
|
610
|
-
# @param log_error [Boolean] Whether to log an error if we can
|
611
|
-
# the class
|
610
|
+
# @param log_error [Boolean] Whether to log an error if we can't require the class
|
612
611
|
def self.require_class(class_name_or_class_filename, log_error = true)
|
613
612
|
if class_name_or_class_filename.downcase[-3..-1] == '.rb' or (class_name_or_class_filename[0] == class_name_or_class_filename[0].downcase)
|
614
613
|
class_filename = class_name_or_class_filename
|
@@ -627,8 +626,7 @@ module Cosmos
|
|
627
626
|
# Requires a file with a standard error message if it fails
|
628
627
|
#
|
629
628
|
# @param filename [String] The name of the file to require
|
630
|
-
# @param log_error [Boolean] Whether to log an error if we can
|
631
|
-
# the class
|
629
|
+
# @param log_error [Boolean] Whether to log an error if we can't require the class
|
632
630
|
def self.require_file(filename, log_error = true)
|
633
631
|
begin
|
634
632
|
require filename
|
data/lib/cosmos/utilities/csv.rb
CHANGED
data/lib/cosmos/version.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
COSMOS_VERSION = '4.0.
|
3
|
+
COSMOS_VERSION = '4.0.2'
|
4
4
|
module Cosmos
|
5
5
|
module Version
|
6
6
|
MAJOR = '4'
|
7
7
|
MINOR = '0'
|
8
|
-
PATCH = '
|
9
|
-
BUILD = '
|
8
|
+
PATCH = '2'
|
9
|
+
BUILD = 'e9da0b19c0c72edef48b0717440a06c0da1d5690'
|
10
10
|
end
|
11
|
-
VERSION = '4.0.
|
11
|
+
VERSION = '4.0.2'
|
12
12
|
end
|
@@ -12,6 +12,7 @@ require 'spec_helper'
|
|
12
12
|
require 'cosmos/interfaces/protocols/template_protocol'
|
13
13
|
require 'cosmos/interfaces/interface'
|
14
14
|
require 'cosmos/streams/stream'
|
15
|
+
require 'cosmos/utilities/logger'
|
15
16
|
|
16
17
|
module Cosmos
|
17
18
|
describe TemplateProtocol do
|
@@ -33,7 +34,7 @@ module Cosmos
|
|
33
34
|
|
34
35
|
describe "initialize" do
|
35
36
|
it "initializes attributes" do
|
36
|
-
@interface.add_protocol(TemplateProtocol,
|
37
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD), :READ_WRITE)
|
37
38
|
expect(@interface.read_protocols[0].instance_variable_get(:@data)).to eq ''
|
38
39
|
end
|
39
40
|
end
|
@@ -41,7 +42,7 @@ module Cosmos
|
|
41
42
|
describe "connect" do
|
42
43
|
it "supports an initial read delay" do
|
43
44
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
44
|
-
@interface.add_protocol(TemplateProtocol,
|
45
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD 0 2), :READ_WRITE)
|
45
46
|
time = Time.now
|
46
47
|
@interface.connect
|
47
48
|
expect(@interface.read_protocols[0].instance_variable_get(:@connect_complete_time)).to be >= time + 2.0
|
@@ -51,7 +52,7 @@ module Cosmos
|
|
51
52
|
describe "disconnect" do
|
52
53
|
it "unblocks writes waiting for responses" do
|
53
54
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
54
|
-
@interface.add_protocol(TemplateProtocol,
|
55
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD), :READ_WRITE)
|
55
56
|
packet = Packet.new('TGT', 'CMD')
|
56
57
|
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
57
58
|
packet.get_item("CMD_TEMPLATE").default = "SOUR:VOLT"
|
@@ -72,7 +73,7 @@ module Cosmos
|
|
72
73
|
describe "read_data" do
|
73
74
|
it "ignores all data during the connect period" do
|
74
75
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
75
|
-
@interface.add_protocol(TemplateProtocol,
|
76
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD 0 1.5), :READ_WRITE)
|
76
77
|
start = Time.now
|
77
78
|
@interface.connect
|
78
79
|
$read_buffer = "\x31\x30\xAB\xCD"
|
@@ -85,7 +86,7 @@ module Cosmos
|
|
85
86
|
describe "write" do
|
86
87
|
it "waits before writing during the initial delay period" do
|
87
88
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
88
|
-
@interface.add_protocol(TemplateProtocol,
|
89
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD 0 1.5), :READ_WRITE)
|
89
90
|
packet = Packet.new('TGT', 'CMD')
|
90
91
|
packet.append_item("VOLTAGE", 16, :UINT)
|
91
92
|
packet.get_item("VOLTAGE").default = 1
|
@@ -102,7 +103,7 @@ module Cosmos
|
|
102
103
|
|
103
104
|
it "works without a response" do
|
104
105
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
105
|
-
@interface.add_protocol(TemplateProtocol,
|
106
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD), :READ_WRITE)
|
106
107
|
packet = Packet.new('TGT', 'CMD')
|
107
108
|
packet.append_item("VOLTAGE", 16, :UINT)
|
108
109
|
packet.get_item("VOLTAGE").default = 1
|
@@ -115,9 +116,9 @@ module Cosmos
|
|
115
116
|
expect($write_buffer).to eql("SOUR:VOLT 1, (@2)\xAB\xCD")
|
116
117
|
end
|
117
118
|
|
118
|
-
it "
|
119
|
+
it "logs an error if it doesn't receive a response" do
|
119
120
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
120
|
-
@interface.add_protocol(TemplateProtocol,
|
121
|
+
@interface.add_protocol(TemplateProtocol, %w(0xA 0xA 0 nil 1 true 0 nil false 1.5), :READ_WRITE)
|
121
122
|
@interface.target_names = ['TGT']
|
122
123
|
packet = Packet.new('TGT', 'CMD')
|
123
124
|
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
@@ -129,23 +130,61 @@ module Cosmos
|
|
129
130
|
packet.restore_defaults
|
130
131
|
@interface.connect
|
131
132
|
start = Time.now
|
132
|
-
|
133
|
+
logger = class_double("Cosmos::Logger").as_stubbed_const(:transfer_nested_constants => true)
|
134
|
+
expect(logger).to receive(:error).with("StreamInterface: Timeout waiting for response")
|
135
|
+
@interface.write(packet)
|
133
136
|
expect(Time.now - start).to be_within(0.1).of(1.5)
|
134
137
|
end
|
135
138
|
|
139
|
+
it "disconnects if it doesn't receive a response" do
|
140
|
+
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
141
|
+
@interface.add_protocol(TemplateProtocol, %w(0xA 0xA 0 nil 1 true 0 nil false 1.5 0.02 true), :READ_WRITE)
|
142
|
+
@interface.target_names = ['TGT']
|
143
|
+
packet = Packet.new('TGT', 'CMD')
|
144
|
+
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
145
|
+
packet.get_item("CMD_TEMPLATE").default = "GO"
|
146
|
+
packet.append_item("RSP_TEMPLATE", 1024, :STRING)
|
147
|
+
packet.get_item("RSP_TEMPLATE").default = "<VOLTAGE>"
|
148
|
+
packet.append_item("RSP_PACKET", 1024, :STRING)
|
149
|
+
packet.get_item("RSP_PACKET").default = "DATA"
|
150
|
+
packet.restore_defaults
|
151
|
+
@interface.connect
|
152
|
+
start = Time.now
|
153
|
+
expect { @interface.write(packet) }.to raise_error(/Timeout waiting for response/)
|
154
|
+
expect(Time.now - start).to be_within(0.1).of(1.5)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "doesn't expect responses for empty response fields" do
|
158
|
+
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
159
|
+
@interface.add_protocol(TemplateProtocol, %w(0xA 0xA 0 nil 1 true 0 nil false nil), :READ_WRITE)
|
160
|
+
@interface.target_names = ['TGT']
|
161
|
+
packet = Packet.new('TGT', 'CMD')
|
162
|
+
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
163
|
+
packet.get_item("CMD_TEMPLATE").default = "GO"
|
164
|
+
packet.append_item("RSP_TEMPLATE", 1024, :STRING)
|
165
|
+
packet.get_item("RSP_TEMPLATE").default = ""
|
166
|
+
packet.append_item("RSP_PACKET", 1024, :STRING)
|
167
|
+
packet.get_item("RSP_PACKET").default = ""
|
168
|
+
packet.restore_defaults
|
169
|
+
@interface.connect
|
170
|
+
start = Time.now
|
171
|
+
logger = class_double("Cosmos::Logger").as_stubbed_const(:transfer_nested_constants => true)
|
172
|
+
expect(logger).to_not receive(:error)
|
173
|
+
@interface.write(packet)
|
174
|
+
end
|
175
|
+
|
136
176
|
it "processes responses" do
|
137
177
|
rsp_pkt = Packet.new('TGT', 'READ_VOLTAGE')
|
138
178
|
rsp_pkt.append_item("VOLTAGE", 16, :UINT)
|
139
179
|
allow(System).to receive_message_chain(:telemetry, :packet).and_return(rsp_pkt)
|
140
180
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
141
|
-
@interface.add_protocol(TemplateProtocol,
|
142
|
-
#@interface.add_protocol(TemplateProtocol, ['0xABCD','0xABCD'], :READ_WRITE)
|
181
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD 0 nil 1 true 0 nil false nil nil), :READ_WRITE)
|
143
182
|
@interface.target_names = ['TGT']
|
144
183
|
packet = Packet.new('TGT', 'CMD')
|
145
184
|
packet.append_item("VOLTAGE", 16, :UINT)
|
146
185
|
packet.get_item("VOLTAGE").default = 11
|
147
186
|
packet.append_item("CHANNEL", 16, :UINT)
|
148
|
-
packet.get_item("CHANNEL").default =
|
187
|
+
packet.get_item("CHANNEL").default = 1
|
149
188
|
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
150
189
|
packet.get_item("CMD_TEMPLATE").default = "SOUR:VOLT <VOLTAGE>, (@<CHANNEL>)"
|
151
190
|
packet.append_item("RSP_TEMPLATE", 1024, :STRING)
|
@@ -158,16 +197,81 @@ module Cosmos
|
|
158
197
|
$read_buffer = "\x31\x30\xAB\xCD" # ASCII 31, 30 is '10'
|
159
198
|
Thread.new { sleep(0.5); read_result = @interface.read }
|
160
199
|
@interface.write(packet)
|
161
|
-
|
200
|
+
sleep 0.55
|
201
|
+
expect($write_buffer).to eql("SOUR:VOLT 11, (@1)\xAB\xCD")
|
162
202
|
expect(read_result.read("VOLTAGE")).to eq 10
|
163
203
|
end
|
164
204
|
|
205
|
+
it "handles templates with more values than the response" do
|
206
|
+
rsp_pkt = Packet.new('TGT', 'READ_VOLTAGE')
|
207
|
+
rsp_pkt.append_item("VOLTAGE", 16, :UINT)
|
208
|
+
allow(System).to receive_message_chain(:telemetry, :packet).and_return(rsp_pkt)
|
209
|
+
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
210
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD 0 nil 1 true 0 nil false nil), :READ_WRITE)
|
211
|
+
@interface.target_names = ['TGT']
|
212
|
+
packet = Packet.new('TGT', 'CMD')
|
213
|
+
packet.append_item("VOLTAGE", 16, :UINT)
|
214
|
+
packet.get_item("VOLTAGE").default = 12
|
215
|
+
packet.append_item("CHANNEL", 16, :UINT)
|
216
|
+
packet.get_item("CHANNEL").default = 2
|
217
|
+
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
218
|
+
packet.get_item("CMD_TEMPLATE").default = "SOUR:VOLT <VOLTAGE>, (@<CHANNEL>)"
|
219
|
+
packet.append_item("RSP_TEMPLATE", 1024, :STRING)
|
220
|
+
packet.get_item("RSP_TEMPLATE").default = "<VOLTAGE>;<CURRENT>"
|
221
|
+
packet.append_item("RSP_PACKET", 1024, :STRING)
|
222
|
+
packet.get_item("RSP_PACKET").default = "READ_VOLTAGE"
|
223
|
+
packet.restore_defaults
|
224
|
+
@interface.connect
|
225
|
+
read_result = nil
|
226
|
+
$read_buffer = "\x31\x30\xAB\xCD" # ASCII 31, 30 is '10'
|
227
|
+
Thread.new { sleep(0.5); read_result = @interface.read }
|
228
|
+
logger = class_double("Cosmos::Logger").as_stubbed_const(:transfer_nested_constants => true)
|
229
|
+
expect(logger).to receive(:error) do |arg|
|
230
|
+
expect(arg).to match(/Unexpected response: 10/)
|
231
|
+
end
|
232
|
+
@interface.write(packet)
|
233
|
+
sleep 0.55
|
234
|
+
expect($write_buffer).to eql("SOUR:VOLT 12, (@2)\xAB\xCD")
|
235
|
+
end
|
236
|
+
|
237
|
+
it "handles responses with more values than the template" do
|
238
|
+
rsp_pkt = Packet.new('TGT', 'READ_VOLTAGE')
|
239
|
+
rsp_pkt.append_item("VOLTAGE", 16, :UINT)
|
240
|
+
allow(System).to receive_message_chain(:telemetry, :packet).and_return(rsp_pkt)
|
241
|
+
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
242
|
+
@interface.add_protocol(TemplateProtocol, %w(0xABCD 0xABCD 0 nil 1 true 0 nil false nil), :READ_WRITE)
|
243
|
+
@interface.target_names = ['TGT']
|
244
|
+
packet = Packet.new('TGT', 'CMD')
|
245
|
+
packet.append_item("VOLTAGE", 16, :UINT)
|
246
|
+
packet.get_item("VOLTAGE").default = 12
|
247
|
+
packet.append_item("CHANNEL", 16, :UINT)
|
248
|
+
packet.get_item("CHANNEL").default = 2
|
249
|
+
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|
250
|
+
packet.get_item("CMD_TEMPLATE").default = "SOUR:VOLT <VOLTAGE>, (@<CHANNEL>)"
|
251
|
+
packet.append_item("RSP_TEMPLATE", 1024, :STRING)
|
252
|
+
packet.get_item("RSP_TEMPLATE").default = "<VOLTAGE>"
|
253
|
+
packet.append_item("RSP_PACKET", 1024, :STRING)
|
254
|
+
packet.get_item("RSP_PACKET").default = "READ_VOLTAGE"
|
255
|
+
packet.restore_defaults
|
256
|
+
@interface.connect
|
257
|
+
read_result = nil
|
258
|
+
$read_buffer = "\x31\x30\x3B\x31\x31\xAB\xCD" # ASCII is '10;11'
|
259
|
+
Thread.new { sleep(0.5); read_result = @interface.read }
|
260
|
+
logger = class_double("Cosmos::Logger").as_stubbed_const(:transfer_nested_constants => true)
|
261
|
+
expect(logger).to receive(:error) do |arg|
|
262
|
+
expect(arg).to match(/Could not write value 10;11/)
|
263
|
+
end
|
264
|
+
@interface.write(packet)
|
265
|
+
sleep 0.55
|
266
|
+
expect($write_buffer).to eql("SOUR:VOLT 12, (@2)\xAB\xCD")
|
267
|
+
end
|
268
|
+
|
165
269
|
it "ignores response lines" do
|
166
270
|
rsp_pkt = Packet.new('TGT', 'READ_VOLTAGE')
|
167
271
|
rsp_pkt.append_item("VOLTAGE", 16, :UINT)
|
168
272
|
allow(System).to receive_message_chain(:telemetry, :packet).and_return(rsp_pkt)
|
169
273
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
170
|
-
@interface.add_protocol(TemplateProtocol,
|
274
|
+
@interface.add_protocol(TemplateProtocol, %w(0xAD 0xA 1), :READ_WRITE)
|
171
275
|
@interface.target_names = ['TGT']
|
172
276
|
packet = Packet.new('TGT', 'CMD')
|
173
277
|
packet.append_item("VOLTAGE", 16, :UINT)
|
@@ -196,7 +300,7 @@ module Cosmos
|
|
196
300
|
rsp_pkt.append_item("STRING", 512, :STRING)
|
197
301
|
allow(System).to receive_message_chain(:telemetry, :packet).and_return(rsp_pkt)
|
198
302
|
@interface.instance_variable_set(:@stream, TemplateStream.new)
|
199
|
-
@interface.add_protocol(TemplateProtocol,
|
303
|
+
@interface.add_protocol(TemplateProtocol, %w(0xAD 0xA 0 nil 2), :READ_WRITE)
|
200
304
|
@interface.target_names = ['TGT']
|
201
305
|
packet = Packet.new('TGT', 'CMD')
|
202
306
|
packet.append_item("CMD_TEMPLATE", 1024, :STRING)
|