openc3 5.18.0 → 5.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -4
- data/bin/cstol_converter +14 -14
- data/bin/openc3cli +189 -7
- data/data/config/_interfaces.yaml +1 -1
- data/data/config/command_modifiers.yaml +55 -0
- data/data/config/interface_modifiers.yaml +1 -1
- data/data/config/param_item_modifiers.yaml +1 -1
- data/data/config/parameter_modifiers.yaml +1 -1
- data/data/config/plugins.yaml +6 -2
- data/data/config/screen.yaml +2 -2
- data/data/config/table_manager.yaml +2 -2
- data/data/config/tool.yaml +4 -1
- data/data/config/widgets.yaml +3 -3
- data/ext/openc3/ext/config_parser/config_parser.c +1 -1
- data/ext/openc3/ext/packet/packet.c +1 -1
- data/ext/openc3/ext/platform/platform.c +3 -3
- data/ext/openc3/ext/structure/structure.c +56 -76
- data/lib/openc3/accessors/binary_accessor.rb +4 -4
- data/lib/openc3/accessors/form_accessor.rb +2 -2
- data/lib/openc3/accessors/http_accessor.rb +1 -1
- data/lib/openc3/accessors/json_accessor.rb +6 -4
- data/lib/openc3/accessors/template_accessor.rb +6 -9
- data/lib/openc3/accessors/xml_accessor.rb +1 -1
- data/lib/openc3/api/cmd_api.rb +35 -11
- data/lib/openc3/api/limits_api.rb +1 -1
- data/lib/openc3/config/config_parser.rb +1 -1
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +7 -7
- data/lib/openc3/core_ext/array.rb +5 -5
- data/lib/openc3/core_ext/exception.rb +9 -2
- data/lib/openc3/core_ext/string.rb +2 -2
- data/lib/openc3/interfaces/http_server_interface.rb +1 -0
- data/lib/openc3/interfaces/interface.rb +1 -1
- data/lib/openc3/interfaces/linc_interface.rb +3 -3
- data/lib/openc3/io/json_api.rb +11 -6
- data/lib/openc3/io/json_rpc.rb +1 -1
- data/lib/openc3/logs/buffered_packet_log_writer.rb +3 -3
- data/lib/openc3/logs/log_writer.rb +7 -8
- data/lib/openc3/logs/packet_log_writer.rb +7 -7
- data/lib/openc3/logs/text_log_writer.rb +4 -4
- data/lib/openc3/microservices/decom_microservice.rb +19 -4
- data/lib/openc3/microservices/interface_microservice.rb +41 -3
- data/lib/openc3/microservices/reaction_microservice.rb +2 -2
- data/lib/openc3/microservices/trigger_group_microservice.rb +3 -3
- data/lib/openc3/migrations/20240915000000_activity_uuid.rb +28 -0
- data/lib/openc3/models/activity_model.rb +109 -80
- data/lib/openc3/models/auth_model.rb +31 -2
- data/lib/openc3/models/cvt_model.rb +11 -5
- data/lib/openc3/models/gem_model.rb +8 -8
- data/lib/openc3/models/plugin_model.rb +3 -3
- data/lib/openc3/models/reducer_model.rb +2 -2
- data/lib/openc3/models/scope_model.rb +1 -1
- data/lib/openc3/models/sorted_model.rb +4 -4
- data/lib/openc3/models/target_model.rb +3 -3
- data/lib/openc3/models/tool_config_model.rb +1 -1
- data/lib/openc3/models/tool_model.rb +4 -4
- data/lib/openc3/models/widget_model.rb +11 -5
- data/lib/openc3/operators/operator.rb +5 -3
- data/lib/openc3/packets/command_validator.rb +48 -0
- data/lib/openc3/packets/commands.rb +6 -14
- data/lib/openc3/packets/packet.rb +31 -15
- data/lib/openc3/packets/packet_config.rb +10 -9
- data/lib/openc3/packets/parsers/packet_parser.rb +3 -3
- data/lib/openc3/packets/structure.rb +21 -13
- data/lib/openc3/packets/structure_item.rb +33 -47
- data/lib/openc3/packets/telemetry.rb +6 -27
- data/lib/openc3/script/api_shared.rb +7 -5
- data/lib/openc3/script/calendar.rb +2 -2
- data/lib/openc3/script/commands.rb +6 -4
- data/lib/openc3/script/metadata.rb +2 -2
- data/lib/openc3/script/suite.rb +17 -17
- data/lib/openc3/streams/serial_stream.rb +2 -3
- data/lib/openc3/streams/stream.rb +2 -2
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +10 -10
- data/lib/openc3/tools/table_manager/table_manager_core.rb +11 -11
- data/lib/openc3/tools/table_manager/table_parser.rb +2 -3
- data/lib/openc3/topics/command_decom_topic.rb +2 -1
- data/lib/openc3/topics/command_topic.rb +3 -3
- data/lib/openc3/topics/decom_interface_topic.rb +2 -2
- data/lib/openc3/topics/telemetry_decom_topic.rb +1 -1
- data/lib/openc3/utilities/authorization.rb +2 -1
- data/lib/openc3/utilities/cli_generator.rb +15 -8
- data/lib/openc3/utilities/cosmos_rails_formatter.rb +60 -0
- data/lib/openc3/utilities/crc.rb +6 -6
- data/lib/openc3/utilities/local_mode.rb +2 -1
- data/lib/openc3/utilities/logger.rb +44 -34
- data/lib/openc3/utilities/metric.rb +1 -2
- data/lib/openc3/utilities/quaternion.rb +18 -18
- data/lib/openc3/utilities/target_file.rb +4 -4
- data/lib/openc3/version.rb +5 -5
- data/lib/openc3/win32/win32_main.rb +2 -2
- data/templates/tool_angular/package.json +21 -21
- data/templates/tool_react/package.json +10 -10
- data/templates/tool_svelte/package.json +11 -11
- data/templates/tool_svelte/src/services/openc3-api.js +17 -17
- data/templates/tool_vue/package.json +9 -9
- data/templates/widget/package.json +6 -7
- metadata +5 -2
@@ -73,9 +73,11 @@ module OpenC3
|
|
73
73
|
def self.handle_config(parser, keyword, parameters, plugin: nil, needs_dependencies: false, scope:)
|
74
74
|
case keyword
|
75
75
|
when 'WIDGET'
|
76
|
-
parser.verify_num_parameters(1,
|
76
|
+
parser.verify_num_parameters(1, 3, "WIDGET <Name> <Label> <Select Items (true/false)>")
|
77
77
|
# Label is optional and if it doesn't exist nil is fine
|
78
|
-
|
78
|
+
# Select Items is optional and if it doesn't exist nil is fine
|
79
|
+
items = ConfigParser.handle_true_false_nil(parameters[2])
|
80
|
+
return self.new(name: parameters[0], plugin: plugin, label: parameters[1], items: items, needs_dependencies: needs_dependencies, scope: scope)
|
79
81
|
else
|
80
82
|
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Widget: #{keyword} #{parameters.join(" ")}")
|
81
83
|
end
|
@@ -87,6 +89,7 @@ module OpenC3
|
|
87
89
|
updated_at: nil,
|
88
90
|
plugin: nil,
|
89
91
|
label: nil,
|
92
|
+
items: false,
|
90
93
|
needs_dependencies: false,
|
91
94
|
disable_erb: nil,
|
92
95
|
scope:
|
@@ -96,6 +99,8 @@ module OpenC3
|
|
96
99
|
@filename = @full_name + '.umd.min.js'
|
97
100
|
@bucket_key = 'widgets/' + @full_name + '/' + @filename
|
98
101
|
@label = label
|
102
|
+
# Ensure items is a boolean because it could be nil
|
103
|
+
@items = items ? true : false
|
99
104
|
@needs_dependencies = needs_dependencies
|
100
105
|
@disable_erb = disable_erb
|
101
106
|
end
|
@@ -106,8 +111,9 @@ module OpenC3
|
|
106
111
|
'updated_at' => @updated_at,
|
107
112
|
'plugin' => @plugin,
|
108
113
|
'label' => @label,
|
114
|
+
'items' => @items,
|
109
115
|
'needs_dependencies' => @needs_dependencies,
|
110
|
-
'disable_erb' => @disable_erb
|
116
|
+
'disable_erb' => @disable_erb,
|
111
117
|
}
|
112
118
|
end
|
113
119
|
|
@@ -155,8 +161,8 @@ module OpenC3
|
|
155
161
|
bucket = Bucket.getClient()
|
156
162
|
bucket.delete_object(bucket: ENV['OPENC3_TOOLS_BUCKET'], key: @bucket_key)
|
157
163
|
bucket.delete_object(bucket: ENV['OPENC3_TOOLS_BUCKET'], key: @bucket_key + '.map')
|
158
|
-
rescue Exception =>
|
159
|
-
Logger.error("Error undeploying widget model #{@name} in scope #{@scope} due to #{
|
164
|
+
rescue Exception => e
|
165
|
+
Logger.error("Error undeploying widget model #{@name} in scope #{@scope} due to #{e}")
|
160
166
|
end
|
161
167
|
end
|
162
168
|
end
|
@@ -105,7 +105,7 @@ module OpenC3
|
|
105
105
|
def cmd_line
|
106
106
|
# In ProcessManager processes, the process_definition is the actual thing run
|
107
107
|
# e.g. OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "load", ...])
|
108
|
-
# However, if the MicroserviceOperator is spawning the
|
108
|
+
# However, if the MicroserviceOperator is spawning the processes it sets
|
109
109
|
# process_definition = ["ruby", "plugin_microservice.rb"]
|
110
110
|
# which then calls exec(*@config["cmd"]) to actually run
|
111
111
|
# So check if the @config['cmd'] is defined to give the user more info in the log
|
@@ -195,12 +195,14 @@ module OpenC3
|
|
195
195
|
if @process
|
196
196
|
stdout = @process.io.stdout.extract
|
197
197
|
if stdout.length > 0
|
198
|
-
|
198
|
+
message = "STDOUT #{stdout.length} bytes from #{cmd_line()}:"
|
199
|
+
STDOUT.puts Logger.build_log_data(Logger::INFO_LEVEL, message, user: nil, type: OpenC3::Logger::LOG, url: nil).as_json(:allow_nan => true).to_json(:allow_nan => true)
|
199
200
|
STDOUT.puts stdout
|
200
201
|
end
|
201
202
|
stderr = @process.io.stderr.extract
|
202
203
|
if stderr.length > 0
|
203
|
-
|
204
|
+
message = "STDERR #{stderr.length} bytes from #{cmd_line()}:"
|
205
|
+
STDERR.puts Logger.build_log_data(Logger::ERROR_LEVEL, message, user: nil, type: OpenC3::Logger::LOG, url: nil).as_json(:allow_nan => true).to_json(:allow_nan => true)
|
204
206
|
STDERR.puts stderr
|
205
207
|
end
|
206
208
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2024 OpenC3, Inc.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# This file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
# This file implements a class to handle command validation
|
20
|
+
|
21
|
+
require 'openc3/api/api'
|
22
|
+
|
23
|
+
module OpenC3
|
24
|
+
# This class defines methods which are called when a command is sent.
|
25
|
+
# This class must be subclassed and the pre_check or
|
26
|
+
# post_check methods implemented. Do NOT use this class directly.
|
27
|
+
class CommandValidator
|
28
|
+
attr_reader :args
|
29
|
+
include Api
|
30
|
+
|
31
|
+
def initialize(command = nil)
|
32
|
+
@command = command
|
33
|
+
@args = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def pre_check(command)
|
37
|
+
# Return true to indicate Success, false to indicate Failure,
|
38
|
+
# and nil to indicate Unknown. The second value is the optional message.
|
39
|
+
return [true, nil]
|
40
|
+
end
|
41
|
+
|
42
|
+
def post_check(command)
|
43
|
+
# Return true to indicate Success, false to indicate Failure,
|
44
|
+
# and nil to indicate Unknown. The second value is the optional message.
|
45
|
+
return [true, nil]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -30,7 +30,7 @@ module OpenC3
|
|
30
30
|
#
|
31
31
|
# This should not be confused with the Api module which implements the JSON
|
32
32
|
# API that is used by tools when accessing the Server. The Api module always
|
33
|
-
# provides Ruby
|
33
|
+
# provides Ruby primitives where the PacketConfig class can return actual
|
34
34
|
# Packet or PacketItem objects. While there are some overlapping methods between
|
35
35
|
# the two, these are separate interfaces into the system.
|
36
36
|
class Commands
|
@@ -115,7 +115,7 @@ module OpenC3
|
|
115
115
|
target = System.targets[target_name]
|
116
116
|
if target and target.cmd_unique_id_mode
|
117
117
|
# Iterate through the packets and see if any represent the buffer
|
118
|
-
target_packets.each do |
|
118
|
+
target_packets.each do |_packet_name, packet|
|
119
119
|
if packet.identify?(packet_data)
|
120
120
|
identified_packet = packet
|
121
121
|
break
|
@@ -147,7 +147,7 @@ module OpenC3
|
|
147
147
|
end
|
148
148
|
|
149
149
|
# Returns a copy of the specified command packet with the parameters
|
150
|
-
#
|
150
|
+
# initialized to the given params values.
|
151
151
|
#
|
152
152
|
# @param target_name (see #packet)
|
153
153
|
# @param packet_name (see #packet)
|
@@ -195,7 +195,7 @@ module OpenC3
|
|
195
195
|
items = packet.read_all(:FORMATTED)
|
196
196
|
raw = false
|
197
197
|
end
|
198
|
-
items.delete_if { |item_name,
|
198
|
+
items.delete_if { |item_name, _item_value| ignored_parameters.include?(item_name) }
|
199
199
|
return build_cmd_output_string(packet.target_name, packet.packet_name, items, raw)
|
200
200
|
end
|
201
201
|
|
@@ -207,7 +207,7 @@ module OpenC3
|
|
207
207
|
end
|
208
208
|
target_name = 'UNKNOWN' unless target_name
|
209
209
|
cmd_name = 'UNKNOWN' unless cmd_name
|
210
|
-
output_string << target_name + ' ' + cmd_name
|
210
|
+
output_string << (target_name + ' ' + cmd_name)
|
211
211
|
if cmd_params.nil? or cmd_params.empty?
|
212
212
|
output_string << '")'
|
213
213
|
else
|
@@ -247,7 +247,7 @@ module OpenC3
|
|
247
247
|
params << "#{key} #{value}"
|
248
248
|
end
|
249
249
|
params = params.join(", ")
|
250
|
-
output_string << ' with ' + params + '")'
|
250
|
+
output_string << (' with ' + params + '")')
|
251
251
|
end
|
252
252
|
return output_string
|
253
253
|
end
|
@@ -291,14 +291,6 @@ module OpenC3
|
|
291
291
|
cmd_pkt_hazardous?(build_cmd(target_name, packet_name, params, false, false, false))
|
292
292
|
end
|
293
293
|
|
294
|
-
def clear_counters
|
295
|
-
@config.commands.each do |target_name, target_packets|
|
296
|
-
target_packets.each do |packet_name, packet|
|
297
|
-
packet.received_count = 0
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
294
|
def all
|
303
295
|
@config.commands
|
304
296
|
end
|
@@ -104,6 +104,9 @@ module OpenC3
|
|
104
104
|
# @return [Boolean] Whether to ignore overlapping items
|
105
105
|
attr_accessor :ignore_overlap
|
106
106
|
|
107
|
+
# @return [Validator] Instance of class used to validate commands
|
108
|
+
attr_accessor :validator
|
109
|
+
|
107
110
|
# @return [Boolean] If this packet should be used for identification
|
108
111
|
attr_reader :virtual
|
109
112
|
|
@@ -111,7 +114,7 @@ module OpenC3
|
|
111
114
|
VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED, :WITH_UNITS]
|
112
115
|
|
113
116
|
if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
|
114
|
-
# Creates a new packet by
|
117
|
+
# Creates a new packet by initializing the attributes.
|
115
118
|
#
|
116
119
|
# @param target_name [String] Name of the target this packet is associated with
|
117
120
|
# @param packet_name [String] Name of the packet
|
@@ -122,7 +125,7 @@ module OpenC3
|
|
122
125
|
# subclass of PacketItem)
|
123
126
|
def initialize(target_name = nil, packet_name = nil, default_endianness = :BIG_ENDIAN, description = nil, buffer = nil, item_class = PacketItem)
|
124
127
|
super(default_endianness, buffer, item_class)
|
125
|
-
#
|
128
|
+
# Explicitly call the defined setter methods
|
126
129
|
self.target_name = target_name
|
127
130
|
self.packet_name = packet_name
|
128
131
|
self.description = description
|
@@ -148,6 +151,7 @@ module OpenC3
|
|
148
151
|
@packet_time = nil
|
149
152
|
@ignore_overlap = false
|
150
153
|
@virtual = false
|
154
|
+
@validator = nil
|
151
155
|
end
|
152
156
|
|
153
157
|
# Sets the target name this packet is associated with. Unidentified packets
|
@@ -325,7 +329,7 @@ module OpenC3
|
|
325
329
|
synchronize() do
|
326
330
|
begin
|
327
331
|
internal_buffer_equals(buffer)
|
328
|
-
rescue RuntimeError
|
332
|
+
rescue RuntimeError => e
|
329
333
|
Logger.instance.error "#{@target_name} #{@packet_name} received with actual packet length of #{buffer.length} but defined length of #{@defined_length}"
|
330
334
|
end
|
331
335
|
@read_conversion_cache.clear if @read_conversion_cache
|
@@ -511,20 +515,20 @@ module OpenC3
|
|
511
515
|
|
512
516
|
# Define an item in the packet. This creates a new instance of the
|
513
517
|
# item_class as given in the constructor and adds it to the items hash. It
|
514
|
-
# also resizes the buffer to
|
518
|
+
# also resizes the buffer to accommodate the new item.
|
515
519
|
#
|
516
520
|
# @param name [String] Name of the item. Used by the items hash to retrieve
|
517
521
|
# the item.
|
518
522
|
# @param bit_offset [Integer] Bit offset of the item in the raw buffer
|
519
523
|
# @param bit_size [Integer] Bit size of the item in the raw buffer
|
520
524
|
# @param data_type [Symbol] Type of data contained by the item. This is
|
521
|
-
#
|
525
|
+
# dependent on the item_class but by default see StructureItem.
|
522
526
|
# @param array_size [Integer] Set to a non nil value if the item is to
|
523
527
|
# represented as an array.
|
524
528
|
# @param endianness [Symbol] Endianness of this item. By default the
|
525
|
-
# endianness as set in the
|
529
|
+
# endianness as set in the constructor is used.
|
526
530
|
# @param overflow [Symbol] How to handle value overflows. This is
|
527
|
-
#
|
531
|
+
# dependent on the item_class but by default see StructureItem.
|
528
532
|
# @param format_string [String] String to pass to Kernel#sprintf
|
529
533
|
# @param read_conversion [Conversion] Conversion to apply when reading the
|
530
534
|
# item from the packet buffer
|
@@ -540,7 +544,7 @@ module OpenC3
|
|
540
544
|
end
|
541
545
|
|
542
546
|
# Add an item to the packet by adding it to the items hash. It also
|
543
|
-
# resizes the buffer to
|
547
|
+
# resizes the buffer to accommodate the new item.
|
544
548
|
#
|
545
549
|
# @param item [PacketItem] Item to add to the packet
|
546
550
|
# @return [PacketItem] The same packet item
|
@@ -553,7 +557,7 @@ module OpenC3
|
|
553
557
|
|
554
558
|
# Define an item at the end of the packet. This creates a new instance of the
|
555
559
|
# item_class as given in the constructor and adds it to the items hash. It
|
556
|
-
# also resizes the buffer to
|
560
|
+
# also resizes the buffer to accommodate the new item.
|
557
561
|
#
|
558
562
|
# @param name (see #define_item)
|
559
563
|
# @param bit_size (see #define_item)
|
@@ -1064,9 +1068,12 @@ module OpenC3
|
|
1064
1068
|
if @accessor.class.to_s != 'OpenC3::BinaryAccessor'
|
1065
1069
|
config << " ACCESSOR #{@accessor.class} #{@accessor.args.map { |a| a.to_s.quote_if_necessary }.join(" ")}\n"
|
1066
1070
|
end
|
1071
|
+
if @validator
|
1072
|
+
config << " VALIDATOR #{@validator.class} #{@validator.args.map { |a| a.to_s.quote_if_necessary }.join(" ")}\n"
|
1073
|
+
end
|
1067
1074
|
# TODO: Add TEMPLATE_ENCODED so this can always be done inline regardless of content
|
1068
1075
|
if @template
|
1069
|
-
config << " TEMPLATE '#{@template}'"
|
1076
|
+
config << " TEMPLATE '#{@template}'\n"
|
1070
1077
|
end
|
1071
1078
|
config << " ALLOW_SHORT\n" if @short_buffer_allowed
|
1072
1079
|
config << " HAZARDOUS #{@hazardous_description.to_s.quote_if_necessary}\n" if @hazardous
|
@@ -1106,21 +1113,21 @@ module OpenC3
|
|
1106
1113
|
end
|
1107
1114
|
|
1108
1115
|
if @response
|
1109
|
-
config << " RESPONSE #{@response[0].to_s.quote_if_necessary} #{@response[1].to_s.quote_if_necessary}"
|
1116
|
+
config << " RESPONSE #{@response[0].to_s.quote_if_necessary} #{@response[1].to_s.quote_if_necessary}\n"
|
1110
1117
|
end
|
1111
1118
|
if @error_response
|
1112
|
-
config << " ERROR_RESPONSE #{@error_response[0].to_s.quote_if_necessary} #{@error_response[1].to_s.quote_if_necessary}"
|
1119
|
+
config << " ERROR_RESPONSE #{@error_response[0].to_s.quote_if_necessary} #{@error_response[1].to_s.quote_if_necessary}\n"
|
1113
1120
|
end
|
1114
1121
|
if @screen
|
1115
|
-
config << " SCREEN #{@screen[0].to_s.quote_if_necessary} #{@screen[1].to_s.quote_if_necessary}"
|
1122
|
+
config << " SCREEN #{@screen[0].to_s.quote_if_necessary} #{@screen[1].to_s.quote_if_necessary}\n"
|
1116
1123
|
end
|
1117
1124
|
if @related_items
|
1118
1125
|
@related_items.each do |target_name, packet_name, item_name|
|
1119
|
-
config << " RELATED_ITEM #{target_name.to_s.quote_if_necessary} #{packet_name.to_s.quote_if_necessary} #{item_name.to_s.quote_if_necessary}"
|
1126
|
+
config << " RELATED_ITEM #{target_name.to_s.quote_if_necessary} #{packet_name.to_s.quote_if_necessary} #{item_name.to_s.quote_if_necessary}\n"
|
1120
1127
|
end
|
1121
1128
|
end
|
1122
1129
|
if @ignore_overlap
|
1123
|
-
config << " IGNORE_OVERLAP"
|
1130
|
+
config << " IGNORE_OVERLAP\n"
|
1124
1131
|
end
|
1125
1132
|
config
|
1126
1133
|
end
|
@@ -1140,6 +1147,7 @@ module OpenC3
|
|
1140
1147
|
config['virtual'] = true if @virtual
|
1141
1148
|
config['accessor'] = @accessor.class.to_s
|
1142
1149
|
config['accessor_args'] = @accessor.args
|
1150
|
+
config['validator'] = @validator.class.to_s if @validator
|
1143
1151
|
config['template'] = Base64.encode64(@template) if @template
|
1144
1152
|
config['config_name'] = self.config_name
|
1145
1153
|
|
@@ -1205,6 +1213,14 @@ module OpenC3
|
|
1205
1213
|
Logger.instance.error "#{packet.target_name} #{packet.packet_name} accessor of #{hash['accessor']} could not be found due to #{e}"
|
1206
1214
|
end
|
1207
1215
|
end
|
1216
|
+
if hash['validator']
|
1217
|
+
begin
|
1218
|
+
validator = OpenC3::const_get(hash['validator'])
|
1219
|
+
packet.validator = validator.new(packet)
|
1220
|
+
rescue => e
|
1221
|
+
Logger.instance.error "#{packet.target_name} #{packet.packet_name} validator of #{hash['validator']} could not be found due to #{e}"
|
1222
|
+
end
|
1223
|
+
end
|
1208
1224
|
packet.template = Base64.decode64(hash['template']) if hash['template']
|
1209
1225
|
packet.meta = hash['meta']
|
1210
1226
|
# Can't convert processors
|
@@ -220,7 +220,7 @@ module OpenC3
|
|
220
220
|
'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
|
221
221
|
'APPEND_ARRAY_PARAMETER', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META',\
|
222
222
|
'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED', 'VIRTUAL', 'ACCESSOR', 'TEMPLATE', 'TEMPLATE_FILE',\
|
223
|
-
'RESPONSE', 'ERROR_RESPONSE', 'SCREEN', 'RELATED_ITEM', 'IGNORE_OVERLAP'
|
223
|
+
'RESPONSE', 'ERROR_RESPONSE', 'SCREEN', 'RELATED_ITEM', 'IGNORE_OVERLAP', 'VALIDATOR'
|
224
224
|
raise parser.error("No current packet for #{keyword}") unless @current_packet
|
225
225
|
|
226
226
|
process_current_packet(parser, keyword, params)
|
@@ -409,7 +409,7 @@ module OpenC3
|
|
409
409
|
else # DELETE
|
410
410
|
@current_packet.delete_item(params[0])
|
411
411
|
end
|
412
|
-
rescue # Rescue the default
|
412
|
+
rescue # Rescue the default exception to provide a nicer error message
|
413
413
|
raise parser.error("#{params[0]} not found in #{@current_cmd_or_tlm.downcase} packet #{@current_packet.target_name} #{@current_packet.packet_name}", usage)
|
414
414
|
end
|
415
415
|
|
@@ -480,22 +480,23 @@ module OpenC3
|
|
480
480
|
@current_packet.disabled = true
|
481
481
|
@current_packet.virtual = true
|
482
482
|
|
483
|
-
when 'ACCESSOR'
|
484
|
-
usage = "#{keyword} <
|
483
|
+
when 'ACCESSOR', 'VALIDATOR'
|
484
|
+
usage = "#{keyword} <Class name> <Optional parameters> ..."
|
485
485
|
parser.verify_num_parameters(1, nil, usage)
|
486
486
|
begin
|
487
|
+
keyword_equals = "#{keyword.downcase}=".to_sym
|
487
488
|
if @language == 'ruby'
|
488
489
|
klass = OpenC3.require_class(params[0])
|
489
490
|
if params.length > 1
|
490
|
-
@current_packet.
|
491
|
+
@current_packet.public_send(keyword_equals, klass.new(@current_packet, *params[1..-1]))
|
491
492
|
else
|
492
|
-
@current_packet.
|
493
|
+
@current_packet.public_send(keyword_equals, klass.new(@current_packet))
|
493
494
|
end
|
494
495
|
else
|
495
496
|
if params.length > 1
|
496
|
-
@current_packet.
|
497
|
+
@current_packet.public_send(keyword_equals, PythonProxy.new(keyword.capitalize, params[0], @current_packet, *params[1..-1]))
|
497
498
|
else
|
498
|
-
@current_packet.
|
499
|
+
@current_packet.public_send(keyword_equals, PythonProxy.new(keyword.capitalize, params[0], @current_packet))
|
499
500
|
end
|
500
501
|
end
|
501
502
|
rescue Exception => e
|
@@ -675,7 +676,7 @@ module OpenC3
|
|
675
676
|
raise parser.error("#{keyword} only applies to command parameters")
|
676
677
|
end
|
677
678
|
|
678
|
-
# Update the
|
679
|
+
# Update the minimum value for the current command parameter
|
679
680
|
when 'MINIMUM_VALUE'
|
680
681
|
if @current_cmd_or_tlm == TELEMETRY
|
681
682
|
raise parser.error("#{keyword} only applies to command parameters")
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/packets/packet'
|
@@ -30,7 +30,7 @@ module OpenC3
|
|
30
30
|
# used instead of this parameter.
|
31
31
|
# @param commands [Hash] Hash of the currently defined commands
|
32
32
|
# @param warnings [Array<String>] Any warning strings generated while
|
33
|
-
# parsing this command will be
|
33
|
+
# parsing this command will be appended to this array
|
34
34
|
def self.parse_command(parser, target_name, commands, warnings)
|
35
35
|
parser = PacketParser.new(parser)
|
36
36
|
parser.verify_parameters()
|
@@ -48,7 +48,7 @@ module OpenC3
|
|
48
48
|
# used to perform lookups when the packet and item are known but the
|
49
49
|
# packet is not.
|
50
50
|
# @param warnings [Array<String>] Any warning strings generated while
|
51
|
-
# parsing this command will be
|
51
|
+
# parsing this command will be appended to this array
|
52
52
|
def self.parse_telemetry(parser, target_name, telemetry, latest_data, warnings)
|
53
53
|
parser = PacketParser.new(parser)
|
54
54
|
parser.verify_parameters()
|
@@ -188,21 +188,21 @@ module OpenC3
|
|
188
188
|
|
189
189
|
# Define an item in the structure. This creates a new instance of the
|
190
190
|
# item_class as given in the constructor and adds it to the items hash. It
|
191
|
-
# also resizes the buffer to
|
191
|
+
# also resizes the buffer to accommodate the new item.
|
192
192
|
#
|
193
193
|
# @param name [String] Name of the item. Used by the items hash to retrieve
|
194
194
|
# the item.
|
195
195
|
# @param bit_offset [Integer] Bit offset of the item in the raw buffer
|
196
196
|
# @param bit_size [Integer] Bit size of the item in the raw buffer
|
197
197
|
# @param data_type [Symbol] Type of data contained by the item. This is
|
198
|
-
#
|
198
|
+
# dependent on the item_class but by default see StructureItem.
|
199
199
|
# @param array_size [Integer] Set to a non nil value if the item is to
|
200
200
|
# represented as an array.
|
201
201
|
# @param endianness [Symbol] Endianness of this item. By default the
|
202
|
-
# endianness as set in the
|
202
|
+
# endianness as set in the constructor is used.
|
203
203
|
# @param overflow [Symbol] How to handle value overflows. This is
|
204
|
-
#
|
205
|
-
# @return [StrutureItem] The
|
204
|
+
# dependent on the item_class but by default see StructureItem.
|
205
|
+
# @return [StrutureItem] The structure item defined
|
206
206
|
def define_item(name, bit_offset, bit_size, data_type, array_size = nil, endianness = @default_endianness, overflow = :ERROR)
|
207
207
|
# Create the item
|
208
208
|
item = @item_class.new(name, bit_offset, bit_size, data_type, endianness, array_size, overflow)
|
@@ -210,10 +210,10 @@ module OpenC3
|
|
210
210
|
end
|
211
211
|
|
212
212
|
# Adds the given item to the items hash. It also resizes the buffer to
|
213
|
-
#
|
213
|
+
# accommodate the new item.
|
214
214
|
#
|
215
215
|
# @param item [StructureItem] The structure item to add
|
216
|
-
# @return [StrutureItem] The
|
216
|
+
# @return [StrutureItem] The structure item defined
|
217
217
|
def define(item)
|
218
218
|
# Handle Overwriting Existing Item
|
219
219
|
if @items[item.name]
|
@@ -289,7 +289,7 @@ module OpenC3
|
|
289
289
|
|
290
290
|
# Define an item at the end of the structure. This creates a new instance of the
|
291
291
|
# item_class as given in the constructor and adds it to the items hash. It
|
292
|
-
# also resizes the buffer to
|
292
|
+
# also resizes the buffer to accommodate the new item.
|
293
293
|
#
|
294
294
|
# @param name (see #define_item)
|
295
295
|
# @param bit_size (see #define_item)
|
@@ -307,7 +307,7 @@ module OpenC3
|
|
307
307
|
end
|
308
308
|
|
309
309
|
# Adds an item at the end of the structure. It adds the item to the items
|
310
|
-
# hash and resizes the buffer to
|
310
|
+
# hash and resizes the buffer to accommodate the new item.
|
311
311
|
#
|
312
312
|
# @param item (see #define)
|
313
313
|
# @return (see #define)
|
@@ -493,7 +493,7 @@ module OpenC3
|
|
493
493
|
# further modifications to the buffer have no effect on the structure
|
494
494
|
# items.
|
495
495
|
#
|
496
|
-
# @param buffer [String] Buffer of data to back the
|
496
|
+
# @param buffer [String] Buffer of data to back the structure items
|
497
497
|
def buffer=(buffer)
|
498
498
|
synchronize() do
|
499
499
|
internal_buffer_equals(buffer)
|
@@ -507,8 +507,8 @@ module OpenC3
|
|
507
507
|
# buffer of data
|
508
508
|
def clone
|
509
509
|
structure = super()
|
510
|
-
# Use instance_variable_set since we have
|
511
|
-
# additional work that isn't
|
510
|
+
# Use instance_variable_set since we have overridden buffer= to do
|
511
|
+
# additional work that isn't necessary here
|
512
512
|
structure.instance_variable_set("@buffer".freeze, @buffer.clone) if @buffer
|
513
513
|
# Need to update reference packet in the Accessor
|
514
514
|
structure.accessor.packet = structure
|
@@ -617,9 +617,17 @@ module OpenC3
|
|
617
617
|
# Anything with a negative bit offset should be left alone
|
618
618
|
if item.original_bit_offset >= 0
|
619
619
|
item.bit_offset = item.original_bit_offset + adjustment
|
620
|
-
|
620
|
+
|
621
|
+
# May need to update adjustment with variable length items
|
622
|
+
# Note legacy variable length does not push anything
|
623
|
+
if item.data_type != :DERIVED and item.variable_bit_size # Not DERIVED and New Variable Length
|
624
|
+
# Calculate the actual current size of this variable length item
|
621
625
|
new_bit_size = calculate_total_bit_size(item)
|
626
|
+
|
622
627
|
if item.original_bit_size != new_bit_size
|
628
|
+
# Bit size has changed from original - so we need to adjust everything after this item
|
629
|
+
# This includes items that may have the same bit_offset as the variable length item because it
|
630
|
+
# started out at zero bit_size
|
623
631
|
adjustment += (new_bit_size - item.original_bit_size)
|
624
632
|
end
|
625
633
|
end
|
@@ -95,6 +95,9 @@ module OpenC3
|
|
95
95
|
# @return [Hash] Variable bit size information
|
96
96
|
attr_reader :variable_bit_size
|
97
97
|
|
98
|
+
# @return [Integer] Incrementing value that shows relative order items are created
|
99
|
+
attr_reader :create_index
|
100
|
+
|
98
101
|
# Create a StructureItem by setting all the attributes. It
|
99
102
|
# calls all the setter routines to do the attribute verification and then
|
100
103
|
# verifies the overall integrity.
|
@@ -238,73 +241,56 @@ module OpenC3
|
|
238
241
|
verify_overall() if @structure_item_constructed
|
239
242
|
end
|
240
243
|
|
241
|
-
def create_index
|
242
|
-
@create_index.to_i
|
243
|
-
end
|
244
|
-
|
245
244
|
if RUBY_ENGINE != 'ruby' or ENV['OPENC3_NO_EXT']
|
246
|
-
# Comparison Operator based on bit_offset
|
247
|
-
# with different names or bit sizes are equal if they have the same bit
|
248
|
-
# offset.
|
245
|
+
# Comparison Operator primarily based on bit_offset
|
249
246
|
def <=>(other)
|
250
247
|
return nil unless other.kind_of?(StructureItem)
|
251
248
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
#
|
256
|
-
if
|
257
|
-
|
258
|
-
# This allows derived items with bit_size of 0 to be listed first
|
259
|
-
# Compare based on bit size then create index
|
260
|
-
if @bit_size == other_bit_size
|
261
|
-
if @create_index
|
262
|
-
if @create_index <= other.create_index
|
263
|
-
return -1
|
264
|
-
else
|
265
|
-
return 1
|
266
|
-
end
|
267
|
-
else
|
268
|
-
return 0
|
269
|
-
end
|
270
|
-
elsif @bit_size < other_bit_size
|
249
|
+
other_original_bit_offset = other.original_bit_offset
|
250
|
+
|
251
|
+
# Derived items should be first in the list with multiple derived sorted
|
252
|
+
# by create_index
|
253
|
+
if @data_type == :DERIVED
|
254
|
+
if other.data_type != :DERIVED
|
271
255
|
return -1
|
272
256
|
else
|
273
|
-
|
257
|
+
if @create_index <= other.create_index
|
258
|
+
return -1
|
259
|
+
else
|
260
|
+
return 1
|
261
|
+
end
|
274
262
|
end
|
263
|
+
elsif other.data_type == :DERIVED
|
264
|
+
return 1
|
275
265
|
end
|
276
266
|
|
277
|
-
# Handle
|
278
|
-
if ((@
|
267
|
+
# Handle non-derived items
|
268
|
+
if ((@original_bit_offset >= 0) && (other_original_bit_offset >= 0)) || ((@original_bit_offset < 0) && (other_original_bit_offset < 0))
|
279
269
|
# Both Have Same Sign
|
280
|
-
if @
|
281
|
-
|
282
|
-
|
270
|
+
if @original_bit_offset == other_original_bit_offset
|
271
|
+
# New Variable Bit Size items are before regular items
|
272
|
+
if @variable_bit_size
|
273
|
+
if not other.variable_bit_size
|
283
274
|
return -1
|
284
|
-
else
|
285
|
-
return 1
|
286
275
|
end
|
276
|
+
# If both variable_bit_size use create index
|
277
|
+
elsif other.variable_bit_size
|
278
|
+
return 1
|
279
|
+
end
|
280
|
+
|
281
|
+
if @create_index <= other.create_index
|
282
|
+
return -1
|
287
283
|
else
|
288
|
-
return
|
284
|
+
return 1
|
289
285
|
end
|
290
|
-
elsif @
|
286
|
+
elsif @original_bit_offset <= other_original_bit_offset
|
291
287
|
return -1
|
292
288
|
else
|
293
289
|
return 1
|
294
290
|
end
|
295
291
|
else
|
296
292
|
# Different Signs
|
297
|
-
if @
|
298
|
-
if @create_index
|
299
|
-
if @create_index < other.create_index
|
300
|
-
return -1
|
301
|
-
else
|
302
|
-
return 1
|
303
|
-
end
|
304
|
-
else
|
305
|
-
return 0
|
306
|
-
end
|
307
|
-
elsif @bit_offset < other_bit_offset
|
293
|
+
if @original_bit_offset < other_original_bit_offset
|
308
294
|
return 1
|
309
295
|
else
|
310
296
|
return -1
|