openc3 6.9.2 → 6.10.0
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/command_modifiers.yaml +79 -0
- data/data/config/item_modifiers.yaml +5 -0
- data/data/config/parameter_modifiers.yaml +5 -0
- data/data/config/telemetry_modifiers.yaml +79 -0
- data/ext/openc3/ext/packet/packet.c +9 -0
- data/lib/openc3/accessors/accessor.rb +27 -3
- data/lib/openc3/accessors/binary_accessor.rb +21 -4
- data/lib/openc3/accessors/template_accessor.rb +3 -2
- data/lib/openc3/api/cmd_api.rb +7 -3
- data/lib/openc3/api/tlm_api.rb +17 -7
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +19 -13
- data/lib/openc3/io/json_rpc.rb +6 -0
- data/lib/openc3/microservices/decom_microservice.rb +97 -17
- data/lib/openc3/microservices/interface_decom_common.rb +32 -0
- data/lib/openc3/microservices/interface_microservice.rb +3 -75
- data/lib/openc3/microservices/queue_microservice.rb +16 -1
- data/lib/openc3/migrations/20251022000000_remove_unique_id.rb +23 -0
- data/lib/openc3/models/plugin_model.rb +7 -1
- data/lib/openc3/models/queue_model.rb +32 -5
- data/lib/openc3/models/reaction_model.rb +25 -9
- data/lib/openc3/models/target_model.rb +78 -10
- data/lib/openc3/packets/commands.rb +33 -7
- data/lib/openc3/packets/packet.rb +75 -71
- data/lib/openc3/packets/packet_config.rb +78 -29
- data/lib/openc3/packets/packet_item.rb +11 -103
- data/lib/openc3/packets/parsers/packet_item_parser.rb +177 -34
- data/lib/openc3/packets/parsers/xtce_converter.rb +2 -2
- data/lib/openc3/packets/structure.rb +29 -21
- data/lib/openc3/packets/structure_item.rb +31 -19
- data/lib/openc3/packets/telemetry.rb +37 -11
- data/lib/openc3/script/suite_results.rb +2 -2
- data/lib/openc3/subpacketizers/subpacketizer.rb +18 -0
- data/lib/openc3/system/target.rb +3 -32
- data/lib/openc3/tools/table_manager/table_config.rb +9 -1
- data/lib/openc3/tools/table_manager/table_item_parser.rb +2 -2
- data/lib/openc3/top_level.rb +45 -19
- data/lib/openc3/topics/decom_interface_topic.rb +31 -0
- data/lib/openc3/utilities/env_helper.rb +10 -0
- data/lib/openc3/utilities/logger.rb +7 -11
- data/lib/openc3/version.rb +6 -6
- data/tasks/spec.rake +2 -1
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_react/package.json +1 -1
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_vue/package.json +3 -3
- data/templates/widget/package.json +2 -2
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1432f7bc925107320f327e82f47ebe6d6da648d00fc6c6469f4f093e69a8dc96
|
|
4
|
+
data.tar.gz: 5aea790bee69e50decbbf418b295eda17a653305f78661c334531afa94f9d265
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dbb54c3b45300cc626c4497ef71c7069567dad94d6f6c73fb1a7dd7093219531d31ffee8bd175ac08b9fee682ab93a488c796d3bf408365a64027740ed9913a3
|
|
7
|
+
data.tar.gz: a703fe408f123953eccf8e9e2b6fb63306404501456a5463410babb95512c68387440279e0d91e61b674ea3bf72122d3480d0001d994cf943d6b901f1a10cc08
|
|
@@ -96,6 +96,68 @@ APPEND_ARRAY_PARAMETER:
|
|
|
96
96
|
values: .*
|
|
97
97
|
<%= MetaConfigParser.load('_array_params.yaml').to_meta_config_yaml(4) %>
|
|
98
98
|
example: APPEND_ARRAY_PARAMETER ARRAY 64 FLOAT 640 "Array of 10 64bit floats"
|
|
99
|
+
STRUCTURE:
|
|
100
|
+
modifiers:
|
|
101
|
+
<%= MetaConfigParser.load('parameter_modifiers.yaml').to_meta_config_yaml(4) %>
|
|
102
|
+
summary: Adds and flattens a structure (generally a virtual packet) into the current packet. The specific named item is BLOCK type and hidden.
|
|
103
|
+
parameters:
|
|
104
|
+
- name: Name
|
|
105
|
+
required: true
|
|
106
|
+
description: Name of the parameter. Must be unique within the command.
|
|
107
|
+
values: .*
|
|
108
|
+
- name: Bit Offset
|
|
109
|
+
required: true
|
|
110
|
+
description: Bit offset into the command packet of the Most Significant Bit of this parameter.
|
|
111
|
+
May be negative to indicate an offset from the end of the packet.
|
|
112
|
+
Always use a bit offset of 0 for derived parameters.
|
|
113
|
+
values: '[-]?\d+'
|
|
114
|
+
- name: Bit Size
|
|
115
|
+
required: true
|
|
116
|
+
description: Bit size of this parameter. Zero or Negative values may be used
|
|
117
|
+
to indicate that a string fills the packet up to the offset from the end of
|
|
118
|
+
the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then
|
|
119
|
+
this is a derived parameter and the Data Type must be set to 'DERIVED'.
|
|
120
|
+
values: \d+
|
|
121
|
+
- name: Command or telemetry
|
|
122
|
+
required: true
|
|
123
|
+
description: Whether the structure packet is a command or telemetry packet
|
|
124
|
+
values: <%= %w(CMD COMMAND TLM TELEMETRY) %>
|
|
125
|
+
- name: Target Name
|
|
126
|
+
required: true
|
|
127
|
+
description: Target Name of the structure packet
|
|
128
|
+
values: .+
|
|
129
|
+
- name: Packet Name
|
|
130
|
+
required: true
|
|
131
|
+
description: Packet Name of the structure packet
|
|
132
|
+
values: .+
|
|
133
|
+
APPEND_STRUCTURE:
|
|
134
|
+
modifiers:
|
|
135
|
+
<%= MetaConfigParser.load('parameter_modifiers.yaml').to_meta_config_yaml(4) %>
|
|
136
|
+
summary: Adds and flattens a structure (generally a virtual packet) into the current packet. The specific named item is BLOCK type and hidden.
|
|
137
|
+
parameters:
|
|
138
|
+
- name: Name
|
|
139
|
+
required: true
|
|
140
|
+
description: Name of the parameter. Must be unique within the command.
|
|
141
|
+
values: .*
|
|
142
|
+
- name: Bit Size
|
|
143
|
+
required: true
|
|
144
|
+
description: Bit size of this parameter. Zero or Negative values may be used
|
|
145
|
+
to indicate that a string fills the packet up to the offset from the end of
|
|
146
|
+
the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then
|
|
147
|
+
this is a derived parameter and the Data Type must be set to 'DERIVED'.
|
|
148
|
+
values: \d+
|
|
149
|
+
- name: Command or telemetry
|
|
150
|
+
required: true
|
|
151
|
+
description: Whether the structure packet is a command or telemetry packet
|
|
152
|
+
values: <%= %w(CMD COMMAND TLM TELEMETRY) %>
|
|
153
|
+
- name: Target Name
|
|
154
|
+
required: true
|
|
155
|
+
description: Target Name of the structure packet
|
|
156
|
+
values: .+
|
|
157
|
+
- name: Packet Name
|
|
158
|
+
required: true
|
|
159
|
+
description: Packet Name of the structure packet
|
|
160
|
+
values: .+
|
|
99
161
|
SELECT_PARAMETER:
|
|
100
162
|
modifiers:
|
|
101
163
|
<%= MetaConfigParser.load('parameter_modifiers.yaml').to_meta_config_yaml(4) %>
|
|
@@ -176,6 +238,19 @@ ACCESSOR:
|
|
|
176
238
|
description: Additional argument passed to the accessor class constructor
|
|
177
239
|
values: .+
|
|
178
240
|
since: 5.0.10
|
|
241
|
+
SUBPACKETIZER:
|
|
242
|
+
summary: Defines a class used to break up the packet into subpackets before decom
|
|
243
|
+
description: Defines a class used to break up the packet into subpackets before decom. Defaults to nil/None.
|
|
244
|
+
parameters:
|
|
245
|
+
- name: Subpacketizer Class Name
|
|
246
|
+
required: true
|
|
247
|
+
description: The name of the Subpacketizer class
|
|
248
|
+
values: .+
|
|
249
|
+
- name: Argument
|
|
250
|
+
required: false
|
|
251
|
+
description: Additional argument passed to the Subpacketizer class constructor
|
|
252
|
+
values: .+
|
|
253
|
+
since: 6.10.0
|
|
179
254
|
TEMPLATE:
|
|
180
255
|
summary: Defines a template string used to initialize the command before default values are filled in
|
|
181
256
|
description: Generally the template string is formatted in JSON or HTML and then values are filled in with
|
|
@@ -256,6 +331,10 @@ RESTRICTED:
|
|
|
256
331
|
summary: Marks this packet as restricted and will require approval if critical commanding is enabled
|
|
257
332
|
description: Used as one of the two types of critical commands (HAZARDOUS and RESTRICTED)
|
|
258
333
|
since: 5.20.0
|
|
334
|
+
SUBPACKET:
|
|
335
|
+
summary: Marks this packet as as a subpacket which will exclude it from Interface level identification
|
|
336
|
+
description: Used with a SUBPACKETIZER to breakup up packets into subpackets at decom time
|
|
337
|
+
since: 6.10.0
|
|
259
338
|
VALIDATOR:
|
|
260
339
|
summary: Defines a validator class for a command
|
|
261
340
|
description: Validator class is used to validate the command success or failure with both a pre_check and post_check method.
|
|
@@ -176,3 +176,8 @@ LIMITS_RESPONSE:
|
|
|
176
176
|
description: Variable length number of options that will be passed to the
|
|
177
177
|
class constructor
|
|
178
178
|
values: .+
|
|
179
|
+
HIDDEN:
|
|
180
|
+
summary: Hides this item from all the OpenC3 tools
|
|
181
|
+
description: This item will not appear in PacketViewer or Item Choosers.
|
|
182
|
+
It also hides this item from appearing in the Script Runner popup helper
|
|
183
|
+
when writing scripts. The item will also not be included in decom data.
|
|
@@ -167,3 +167,8 @@ OVERFLOW:
|
|
|
167
167
|
description: How OpenC3 treats an overflow value. Only applies to signed and
|
|
168
168
|
unsigned integer data types.
|
|
169
169
|
values: <%= %w(ERROR ERROR_ALLOW_HEX TRUNCATE SATURATE) %>
|
|
170
|
+
HIDDEN:
|
|
171
|
+
summary: Hides this parameter from all the OpenC3 tools
|
|
172
|
+
description: This item will not appear in CmdSender.
|
|
173
|
+
It also hides this item from appearing in the Script Runner popup helper
|
|
174
|
+
when writing scripts. The parameter should not be provided to commands.
|
|
@@ -86,6 +86,68 @@ APPEND_ARRAY_ITEM:
|
|
|
86
86
|
description: Name of the telemety item. Must be unique within the packet.
|
|
87
87
|
values: \'
|
|
88
88
|
<%= MetaConfigParser.load('_array_params.yaml').to_meta_config_yaml(4) %>
|
|
89
|
+
STRUCTURE:
|
|
90
|
+
modifiers:
|
|
91
|
+
<%= MetaConfigParser.load('item_modifiers.yaml').to_meta_config_yaml(4) %>
|
|
92
|
+
summary: Adds and flattens a structure (generally a virtual packet) into the current packet. The specific named item is BLOCK type and hidden.
|
|
93
|
+
parameters:
|
|
94
|
+
- name: Name
|
|
95
|
+
required: true
|
|
96
|
+
description: Name of the parameter. Must be unique within the command.
|
|
97
|
+
values: .*
|
|
98
|
+
- name: Bit Offset
|
|
99
|
+
required: true
|
|
100
|
+
description: Bit offset into the command packet of the Most Significant Bit of this parameter.
|
|
101
|
+
May be negative to indicate an offset from the end of the packet.
|
|
102
|
+
Always use a bit offset of 0 for derived parameters.
|
|
103
|
+
values: '[-]?\d+'
|
|
104
|
+
- name: Bit Size
|
|
105
|
+
required: true
|
|
106
|
+
description: Bit size of this parameter. Zero or Negative values may be used
|
|
107
|
+
to indicate that a string fills the packet up to the offset from the end of
|
|
108
|
+
the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then
|
|
109
|
+
this is a derived parameter and the Data Type must be set to 'DERIVED'.
|
|
110
|
+
values: \d+
|
|
111
|
+
- name: Command or telemetry
|
|
112
|
+
required: true
|
|
113
|
+
description: Whether the structure packet is a command or telemetry packet
|
|
114
|
+
values: <%= %w(CMD COMMAND TLM TELEMETRY) %>
|
|
115
|
+
- name: Target Name
|
|
116
|
+
required: true
|
|
117
|
+
description: Target Name of the structure packet
|
|
118
|
+
values: .+
|
|
119
|
+
- name: Packet Name
|
|
120
|
+
required: true
|
|
121
|
+
description: Packet Name of the structure packet
|
|
122
|
+
values: .+
|
|
123
|
+
APPEND_STRUCTURE:
|
|
124
|
+
modifiers:
|
|
125
|
+
<%= MetaConfigParser.load('item_modifiers.yaml').to_meta_config_yaml(4) %>
|
|
126
|
+
summary: Adds and flattens a structure (generally a virtual packet) into the current packet. The specific named item is BLOCK type and hidden.
|
|
127
|
+
parameters:
|
|
128
|
+
- name: Name
|
|
129
|
+
required: true
|
|
130
|
+
description: Name of the parameter. Must be unique within the command.
|
|
131
|
+
values: .*
|
|
132
|
+
- name: Bit Size
|
|
133
|
+
required: true
|
|
134
|
+
description: Bit size of this parameter. Zero or Negative values may be used
|
|
135
|
+
to indicate that a string fills the packet up to the offset from the end of
|
|
136
|
+
the packet specified by this value. If Bit Offset is 0 and Bit Size is 0 then
|
|
137
|
+
this is a derived parameter and the Data Type must be set to 'DERIVED'.
|
|
138
|
+
values: \d+
|
|
139
|
+
- name: Command or telemetry
|
|
140
|
+
required: true
|
|
141
|
+
description: Whether the structure packet is a command or telemetry packet
|
|
142
|
+
values: <%= %w(CMD COMMAND TLM TELEMETRY) %>
|
|
143
|
+
- name: Target Name
|
|
144
|
+
required: true
|
|
145
|
+
description: Target Name of the structure packet
|
|
146
|
+
values: .+
|
|
147
|
+
- name: Packet Name
|
|
148
|
+
required: true
|
|
149
|
+
description: Packet Name of the structure packet
|
|
150
|
+
values: .+
|
|
89
151
|
SELECT_ITEM:
|
|
90
152
|
modifiers:
|
|
91
153
|
<%= MetaConfigParser.load('item_modifiers.yaml').to_meta_config_yaml(4) %>
|
|
@@ -173,6 +235,19 @@ ACCESSOR:
|
|
|
173
235
|
description: The name of the accessor class
|
|
174
236
|
values: .+
|
|
175
237
|
since: 5.0.10
|
|
238
|
+
SUBPACKETIZER:
|
|
239
|
+
summary: Defines a class used to break up the packet into subpackets before decom
|
|
240
|
+
description: Defines a class used to break up the packet into subpackets before decom. Defaults to nil/None.
|
|
241
|
+
parameters:
|
|
242
|
+
- name: Subpacketizer Class Name
|
|
243
|
+
required: true
|
|
244
|
+
description: The name of the Subpacketizer class
|
|
245
|
+
values: .+
|
|
246
|
+
- name: Argument
|
|
247
|
+
required: false
|
|
248
|
+
description: Additional argument passed to the Subpacketizer class constructor
|
|
249
|
+
values: .+
|
|
250
|
+
since: 6.10.0
|
|
176
251
|
TEMPLATE:
|
|
177
252
|
summary: Defines a template string used to pull telemetry values from a string buffer
|
|
178
253
|
parameters:
|
|
@@ -198,3 +273,7 @@ VIRTUAL:
|
|
|
198
273
|
summary: Marks this packet as virtual and not participating in identification
|
|
199
274
|
description: Used for packet definitions that can be used as structures for items with a given packet.
|
|
200
275
|
since: 5.18.0
|
|
276
|
+
SUBPACKET:
|
|
277
|
+
summary: Marks this packet as as a subpacket which will exclude it from Interface level identification
|
|
278
|
+
description: Used with a SUBPACKETIZER to breakup up packets into subpackets at decom time
|
|
279
|
+
since: 6.10.0
|
|
@@ -64,6 +64,9 @@ static ID id_ivar_packet_time = 0;
|
|
|
64
64
|
static ID id_ivar_ignore_overlap = 0;
|
|
65
65
|
static ID id_ivar_virtual = 0;
|
|
66
66
|
static ID id_ivar_restricted = 0;
|
|
67
|
+
static ID id_ivar_subpacket = 0;
|
|
68
|
+
static ID id_ivar_subpacketizer = 0;
|
|
69
|
+
static ID id_ivar_obfuscated_items = 0;
|
|
67
70
|
|
|
68
71
|
/* Sets the target name this packet is associated with. Unidentified packets
|
|
69
72
|
* will have target name set to nil.
|
|
@@ -291,6 +294,9 @@ static VALUE packet_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
291
294
|
rb_ivar_set(self, id_ivar_ignore_overlap, Qfalse);
|
|
292
295
|
rb_ivar_set(self, id_ivar_virtual, Qfalse);
|
|
293
296
|
rb_ivar_set(self, id_ivar_restricted, Qfalse);
|
|
297
|
+
rb_ivar_set(self, id_ivar_subpacket, Qfalse);
|
|
298
|
+
rb_ivar_set(self, id_ivar_subpacketizer, Qnil);
|
|
299
|
+
rb_ivar_set(self, id_ivar_obfuscated_items, Qnil);
|
|
294
300
|
return self;
|
|
295
301
|
}
|
|
296
302
|
|
|
@@ -335,6 +341,9 @@ void Init_packet(void)
|
|
|
335
341
|
id_ivar_ignore_overlap = rb_intern("@ignore_overlap");
|
|
336
342
|
id_ivar_virtual = rb_intern("@virtual");
|
|
337
343
|
id_ivar_restricted = rb_intern("@restricted");
|
|
344
|
+
id_ivar_subpacket = rb_intern("@subpacket");
|
|
345
|
+
id_ivar_subpacketizer = rb_intern("@subpacketizer");
|
|
346
|
+
id_ivar_obfuscated_items = rb_intern("@obfuscated_items");
|
|
338
347
|
|
|
339
348
|
cPacket = rb_define_class_under(mOpenC3, "Packet", cStructure);
|
|
340
349
|
rb_define_method(cPacket, "initialize", packet_initialize, -1);
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
# if purchased from OpenC3, Inc.
|
|
18
18
|
|
|
19
19
|
require 'json'
|
|
20
|
+
require 'openc3/config/config_parser'
|
|
20
21
|
|
|
21
22
|
module OpenC3
|
|
22
23
|
class Accessor
|
|
@@ -28,11 +29,26 @@ module OpenC3
|
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def read_item(item, buffer)
|
|
31
|
-
|
|
32
|
+
if item.parent_item
|
|
33
|
+
# Structure is used to read items with parent, not accessor
|
|
34
|
+
structure_buffer = read_item(item.parent_item, buffer)
|
|
35
|
+
structure = item.parent_item.structure
|
|
36
|
+
structure.read(item.key, :RAW, structure_buffer)
|
|
37
|
+
else
|
|
38
|
+
self.class.read_item(item, buffer)
|
|
39
|
+
end
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
def write_item(item, value, buffer)
|
|
35
|
-
|
|
43
|
+
if item.parent_item
|
|
44
|
+
# Structure is used to write items with parent, not accessor
|
|
45
|
+
structure_buffer = read_item(item.parent_item, buffer)
|
|
46
|
+
structure = item.parent_item.structure
|
|
47
|
+
structure.write(item.key, value, :RAW, structure_buffer)
|
|
48
|
+
self.class.write_item(item.parent_item, structure_buffer, buffer)
|
|
49
|
+
else
|
|
50
|
+
self.class.write_item(item, value, buffer)
|
|
51
|
+
end
|
|
36
52
|
end
|
|
37
53
|
|
|
38
54
|
def read_items(items, buffer)
|
|
@@ -106,8 +122,16 @@ module OpenC3
|
|
|
106
122
|
def self.convert_to_type(value, item)
|
|
107
123
|
return value if value.nil?
|
|
108
124
|
case item.data_type
|
|
125
|
+
when :ANY
|
|
126
|
+
begin
|
|
127
|
+
value = JSON.parse(value) if value.is_a? String
|
|
128
|
+
rescue Exception
|
|
129
|
+
# Just leave value as is
|
|
130
|
+
end
|
|
131
|
+
when :BOOL
|
|
132
|
+
value = ConfigParser.handle_true_false(value) if value.is_a? String
|
|
109
133
|
when :OBJECT, :ARRAY
|
|
110
|
-
|
|
134
|
+
value = JSON.parse(value) if value.is_a? String
|
|
111
135
|
when :STRING, :BLOCK
|
|
112
136
|
if item.array_size
|
|
113
137
|
value = JSON.parse(value) if value.is_a? String
|
|
@@ -137,8 +137,16 @@ module OpenC3
|
|
|
137
137
|
|
|
138
138
|
def read_item(item, buffer)
|
|
139
139
|
return nil if item.data_type == :DERIVED
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
if item.parent_item
|
|
141
|
+
handle_read_variable_bit_size(item.parent_item, buffer) if item.parent_item.variable_bit_size
|
|
142
|
+
# Structure is used to read items with parent, not accessor
|
|
143
|
+
structure_buffer = read_item(item.parent_item, buffer)
|
|
144
|
+
structure = item.parent_item.structure
|
|
145
|
+
structure.read(item.key, :RAW, structure_buffer)
|
|
146
|
+
else
|
|
147
|
+
handle_read_variable_bit_size(item, buffer) if item.variable_bit_size
|
|
148
|
+
self.class.read_item(item, buffer)
|
|
149
|
+
end
|
|
142
150
|
end
|
|
143
151
|
|
|
144
152
|
def handle_write_variable_bit_size(item, value, buffer)
|
|
@@ -270,8 +278,17 @@ module OpenC3
|
|
|
270
278
|
|
|
271
279
|
def write_item(item, value, buffer)
|
|
272
280
|
return nil if item.data_type == :DERIVED
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
if item.parent_item
|
|
282
|
+
# Structure is used to write items with parent, not accessor
|
|
283
|
+
structure_buffer = read_item(item.parent_item, buffer)
|
|
284
|
+
structure = item.parent_item.structure
|
|
285
|
+
structure.write(item.key, value, :RAW, structure_buffer)
|
|
286
|
+
handle_write_variable_bit_size(item.parent_item, structure_buffer, buffer) if item.parent_item.variable_bit_size
|
|
287
|
+
self.class.write_item(item.parent_item, structure_buffer, buffer)
|
|
288
|
+
else
|
|
289
|
+
handle_write_variable_bit_size(item, value, buffer) if item.variable_bit_size
|
|
290
|
+
self.class.write_item(item, value, buffer)
|
|
291
|
+
end
|
|
275
292
|
end
|
|
276
293
|
|
|
277
294
|
# Note: do not use directly - use instance read_item
|
|
@@ -25,6 +25,7 @@ module OpenC3
|
|
|
25
25
|
@left_char = left_char
|
|
26
26
|
@right_char = right_char
|
|
27
27
|
@configured = false
|
|
28
|
+
@args = [left_char, right_char]
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def configure
|
|
@@ -65,7 +66,7 @@ module OpenC3
|
|
|
65
66
|
values.each_with_index do |value, i|
|
|
66
67
|
item_key = @item_keys[i]
|
|
67
68
|
if item_key == item.key
|
|
68
|
-
return
|
|
69
|
+
return self.class.convert_to_type(value, item)
|
|
69
70
|
end
|
|
70
71
|
end
|
|
71
72
|
end
|
|
@@ -89,7 +90,7 @@ module OpenC3
|
|
|
89
90
|
end
|
|
90
91
|
index = @item_keys.index(item.key)
|
|
91
92
|
if index
|
|
92
|
-
result[item.name] =
|
|
93
|
+
result[item.name] = self.class.convert_to_type(values[index], item)
|
|
93
94
|
else
|
|
94
95
|
raise "Unknown item with key #{item.key} requested"
|
|
95
96
|
end
|
data/lib/openc3/api/cmd_api.rb
CHANGED
|
@@ -545,9 +545,13 @@ module OpenC3
|
|
|
545
545
|
queue = ENV['OPENC3_DEFAULT_QUEUE']
|
|
546
546
|
end
|
|
547
547
|
if queue
|
|
548
|
-
#
|
|
549
|
-
|
|
550
|
-
|
|
548
|
+
# Pass the command components separately for the queue microservice to use the 3-parameter cmd() method
|
|
549
|
+
QueueModel.queue_command(queue,
|
|
550
|
+
target_name: target_name,
|
|
551
|
+
cmd_name: cmd_name,
|
|
552
|
+
cmd_params: cmd_params,
|
|
553
|
+
username: username,
|
|
554
|
+
scope: scope)
|
|
551
555
|
else
|
|
552
556
|
CommandTopic.send_command(command, timeout: timeout, scope: scope)
|
|
553
557
|
end
|
data/lib/openc3/api/tlm_api.rb
CHANGED
|
@@ -221,15 +221,21 @@ module OpenC3
|
|
|
221
221
|
# @param target_name [String] Name of the target
|
|
222
222
|
# @param packet_name [String] Name of the packet
|
|
223
223
|
# @return [Hash] telemetry hash with last telemetry buffer
|
|
224
|
-
def get_tlm_buffer(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
|
|
224
|
+
def get_tlm_buffer(*args, manual: false, scope: $openc3_scope, token: $openc3_token, timeout: 5)
|
|
225
225
|
target_name, packet_name = _extract_target_packet_names('get_tlm_buffer', *args)
|
|
226
226
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
|
|
227
|
-
TargetModel.packet(target_name, packet_name, scope: scope)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if msg_id
|
|
227
|
+
model = TargetModel.packet(target_name, packet_name, scope: scope)
|
|
228
|
+
if model["subpacket"]
|
|
229
|
+
msg_hash = DecomInterfaceTopic.get_tlm_buffer(target_name, packet_name, timeout: timeout, scope: scope)
|
|
231
230
|
msg_hash['buffer'] = msg_hash['buffer'].b
|
|
232
231
|
return msg_hash
|
|
232
|
+
else
|
|
233
|
+
topic = "#{scope}__TELEMETRY__{#{target_name}}__#{packet_name}"
|
|
234
|
+
msg_id, msg_hash = Topic.get_newest_message(topic)
|
|
235
|
+
if msg_id
|
|
236
|
+
msg_hash['buffer'] = msg_hash['buffer'].b
|
|
237
|
+
return msg_hash
|
|
238
|
+
end
|
|
233
239
|
end
|
|
234
240
|
return nil
|
|
235
241
|
end
|
|
@@ -249,7 +255,8 @@ module OpenC3
|
|
|
249
255
|
packet = TargetModel.packet(target_name, packet_name, scope: scope)
|
|
250
256
|
t = _validate_tlm_type(type)
|
|
251
257
|
raise ArgumentError, "Unknown type '#{type}' for #{target_name} #{packet_name}" if t.nil?
|
|
252
|
-
items = packet[
|
|
258
|
+
items = packet["items"].reject { | item | item["hidden"] }
|
|
259
|
+
items = items.map { | item | item['name'].upcase }
|
|
253
260
|
cvt_items = items.map { | item | [target_name, packet_name, item, type] }
|
|
254
261
|
current_values = CvtModel.get_tlm_values(cvt_items, stale_time: stale_time, cache_timeout: cache_timeout, scope: scope)
|
|
255
262
|
items.zip(current_values).map { | item , values | [item, values[0], values[1]]}
|
|
@@ -437,8 +444,11 @@ module OpenC3
|
|
|
437
444
|
# @param packet_name [String] Name of the packet
|
|
438
445
|
# @param item_name [String] Name of the packet
|
|
439
446
|
# @return [Hash] Telemetry packet item hash
|
|
440
|
-
def get_item(*args, manual: false, scope: $openc3_scope, token: $openc3_token)
|
|
447
|
+
def get_item(*args, manual: false, scope: $openc3_scope, token: $openc3_token, cache_timeout: nil)
|
|
441
448
|
target_name, packet_name, item_name = _extract_target_packet_item_names('get_item', *args)
|
|
449
|
+
if packet_name == 'LATEST'
|
|
450
|
+
packet_name = CvtModel.determine_latest_packet_for_item(target_name, item_name, cache_timeout: cache_timeout, scope: scope)
|
|
451
|
+
end
|
|
442
452
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
|
|
443
453
|
TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
|
|
444
454
|
end
|
|
@@ -89,12 +89,10 @@ module OpenC3
|
|
|
89
89
|
begin
|
|
90
90
|
if @telemetry
|
|
91
91
|
target_packets = System.telemetry.packets(target_name)
|
|
92
|
-
|
|
93
|
-
unique_id_mode = target.tlm_unique_id_mode if target
|
|
92
|
+
unique_id_mode = System.telemetry.tlm_unique_id_mode(target_name)
|
|
94
93
|
else
|
|
95
94
|
target_packets = System.commands.packets(target_name)
|
|
96
|
-
|
|
97
|
-
unique_id_mode = target.cmd_unique_id_mode if target
|
|
95
|
+
unique_id_mode = System.commands.cmd_unique_id_mode(target_name)
|
|
98
96
|
end
|
|
99
97
|
rescue RuntimeError
|
|
100
98
|
# No commands/telemetry for this target
|
|
@@ -103,7 +101,7 @@ module OpenC3
|
|
|
103
101
|
|
|
104
102
|
if unique_id_mode
|
|
105
103
|
target_packets.each do |_packet_name, packet|
|
|
106
|
-
if packet.identify?(@data[@discard_leading_bytes..-1])
|
|
104
|
+
if not packet.subpacket and packet.identify?(@data[@discard_leading_bytes..-1]) # identify? handles virtual
|
|
107
105
|
identified_packet = packet
|
|
108
106
|
break
|
|
109
107
|
end
|
|
@@ -111,15 +109,23 @@ module OpenC3
|
|
|
111
109
|
else
|
|
112
110
|
# Do a hash lookup to quickly identify the packet
|
|
113
111
|
if target_packets.length > 0
|
|
114
|
-
packet =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
packet = nil
|
|
113
|
+
target_packets.each do |_packet_name, target_packet|
|
|
114
|
+
next if target_packet.virtual
|
|
115
|
+
next if target_packet.subpacket
|
|
116
|
+
packet = target_packet
|
|
117
|
+
break
|
|
118
|
+
end
|
|
119
|
+
if packet
|
|
120
|
+
key = packet.read_id_values(@data[@discard_leading_bytes..-1])
|
|
121
|
+
if @telemetry
|
|
122
|
+
hash = System.telemetry.config.tlm_id_value_hash[target_name]
|
|
123
|
+
else
|
|
124
|
+
hash = System.commands.config.cmd_id_value_hash[target_name]
|
|
125
|
+
end
|
|
126
|
+
identified_packet = hash[key]
|
|
127
|
+
identified_packet = hash['CATCHALL'.freeze] unless identified_packet
|
|
120
128
|
end
|
|
121
|
-
identified_packet = hash[key]
|
|
122
|
-
identified_packet = hash['CATCHALL'.freeze] unless identified_packet
|
|
123
129
|
end
|
|
124
130
|
end
|
|
125
131
|
|
data/lib/openc3/io/json_rpc.rb
CHANGED
|
@@ -59,6 +59,12 @@ class String
|
|
|
59
59
|
NON_ASCII_PRINTABLE = /[^\x21-\x7e\s]/
|
|
60
60
|
NON_UTF8_PRINTABLE = /[\x00-\x08\x0E-\x1F\x7F]/
|
|
61
61
|
def as_json(_options = nil)
|
|
62
|
+
# If string is ASCII-8BIT (binary) and has non-ASCII bytes (> 127), encode as binary
|
|
63
|
+
# This handles data from hex_to_byte_string and other binary sources
|
|
64
|
+
if self.encoding == Encoding::ASCII_8BIT && self.bytes.any? { |b| b > 127 }
|
|
65
|
+
return self.to_json_raw_object
|
|
66
|
+
end
|
|
67
|
+
|
|
62
68
|
as_utf8 = self.dup.force_encoding('UTF-8')
|
|
63
69
|
if as_utf8.valid_encoding?
|
|
64
70
|
if as_utf8 =~ NON_UTF8_PRINTABLE
|
|
@@ -24,6 +24,7 @@ require 'time'
|
|
|
24
24
|
require 'thread'
|
|
25
25
|
require 'openc3/microservices/microservice'
|
|
26
26
|
require 'openc3/microservices/interface_decom_common'
|
|
27
|
+
require 'openc3/microservices/interface_microservice'
|
|
27
28
|
require 'openc3/topics/telemetry_decom_topic'
|
|
28
29
|
require 'openc3/topics/limits_event_topic'
|
|
29
30
|
|
|
@@ -127,6 +128,10 @@ module OpenC3
|
|
|
127
128
|
handle_build_cmd(msg_hash['build_cmd'], msg_id)
|
|
128
129
|
next
|
|
129
130
|
end
|
|
131
|
+
if msg_hash.key?('get_tlm_buffer')
|
|
132
|
+
handle_get_tlm_buffer(msg_hash['get_tlm_buffer'], msg_id)
|
|
133
|
+
next
|
|
134
|
+
end
|
|
130
135
|
else
|
|
131
136
|
decom_packet(topic, msg_id, msg_hash, redis)
|
|
132
137
|
@metric.set(name: 'decom_total', value: @count, type: 'counter')
|
|
@@ -154,9 +159,12 @@ module OpenC3
|
|
|
154
159
|
@metric.set(name: 'decom_topic_delta_seconds', value: delta, type: 'gauge', unit: 'seconds', help: 'Delta time between data written to stream and decom start')
|
|
155
160
|
|
|
156
161
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
162
|
+
|
|
163
|
+
#######################################
|
|
164
|
+
# Build packet object from topic data
|
|
165
|
+
#######################################
|
|
157
166
|
target_name = msg_hash["target_name"]
|
|
158
167
|
packet_name = msg_hash["packet_name"]
|
|
159
|
-
|
|
160
168
|
packet = System.telemetry.packet(target_name, packet_name)
|
|
161
169
|
packet.stored = ConfigParser.handle_true_false(msg_hash["stored"])
|
|
162
170
|
# Note: Packet time will be recalculated as part of decom so not setting
|
|
@@ -168,29 +176,101 @@ module OpenC3
|
|
|
168
176
|
packet.extra = extra
|
|
169
177
|
end
|
|
170
178
|
packet.buffer = msg_hash["buffer"]
|
|
171
|
-
# Processors are user code points which must be rescued
|
|
172
|
-
# so the TelemetryDecomTopic can write the packet
|
|
173
|
-
begin
|
|
174
|
-
packet.process # Run processors
|
|
175
|
-
rescue Exception => e
|
|
176
|
-
@error_count += 1
|
|
177
|
-
@metric.set(name: 'decom_error_total', value: @error_count, type: 'counter')
|
|
178
|
-
@error = e
|
|
179
|
-
@logger.error e.message
|
|
180
|
-
end
|
|
181
|
-
# Process all the limits and call the limits_change_callback (as necessary)
|
|
182
|
-
# check_limits also can call user code in the limits response
|
|
183
|
-
# but that is rescued separately in the limits_change_callback
|
|
184
|
-
packet.check_limits(System.limits_set)
|
|
185
179
|
|
|
186
|
-
|
|
187
|
-
|
|
180
|
+
################################################################################
|
|
181
|
+
# Break packet into subpackets (if necessary)
|
|
182
|
+
# Subpackets are typically channelized data
|
|
183
|
+
################################################################################
|
|
184
|
+
packet_and_subpackets = packet.subpacketize
|
|
185
|
+
|
|
186
|
+
packet_and_subpackets.each do |packet_or_subpacket|
|
|
187
|
+
if packet_or_subpacket.subpacket
|
|
188
|
+
packet_or_subpacket = handle_subpacket(packet, packet_or_subpacket)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
#####################################################################################
|
|
192
|
+
# Run Processors
|
|
193
|
+
# This must be before the full decom so that processor derived values are available
|
|
194
|
+
#####################################################################################
|
|
195
|
+
begin
|
|
196
|
+
packet_or_subpacket.process # Run processors
|
|
197
|
+
rescue Exception => e
|
|
198
|
+
@error_count += 1
|
|
199
|
+
@metric.set(name: 'decom_error_total', value: @error_count, type: 'counter')
|
|
200
|
+
@error = e
|
|
201
|
+
@logger.error e.message
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
#############################################################################
|
|
205
|
+
# Process all the limits and call the limits_change_callback (as necessary)
|
|
206
|
+
# This must be before the full decom so that limits states are available
|
|
207
|
+
#############################################################################
|
|
208
|
+
packet_or_subpacket.check_limits(System.limits_set)
|
|
209
|
+
|
|
210
|
+
# This is what actually decommutates the packet and updates the CVT
|
|
211
|
+
TelemetryDecomTopic.write_packet(packet_or_subpacket, scope: @scope)
|
|
212
|
+
end
|
|
188
213
|
|
|
189
214
|
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
|
190
215
|
@metric.set(name: 'decom_duration_seconds', value: diff, type: 'gauge', unit: 'seconds')
|
|
191
216
|
end
|
|
192
217
|
end
|
|
193
218
|
|
|
219
|
+
def handle_subpacket(packet, subpacket)
|
|
220
|
+
# Subpacket received time always = packet.received_time
|
|
221
|
+
# Use packet_time appropriately if another timestamp is needed
|
|
222
|
+
subpacket.received_time = packet.received_time
|
|
223
|
+
subpacket.stored = packet.stored
|
|
224
|
+
subpacket.extra = packet.extra
|
|
225
|
+
|
|
226
|
+
if subpacket.stored
|
|
227
|
+
# Stored telemetry does not update the current value table
|
|
228
|
+
identified_subpacket = System.telemetry.identify_and_define_packet(subpacket, @target_names, subpackets: true)
|
|
229
|
+
else
|
|
230
|
+
# Identify and update subpacket
|
|
231
|
+
if subpacket.identified?
|
|
232
|
+
begin
|
|
233
|
+
# Preidentifed subpacket - place it into the current value table
|
|
234
|
+
identified_subpacket = System.telemetry.update!(subpacket.target_name,
|
|
235
|
+
subpacket.packet_name,
|
|
236
|
+
subpacket.buffer)
|
|
237
|
+
rescue RuntimeError
|
|
238
|
+
# Subpacket identified but we don't know about it
|
|
239
|
+
# Clear packet_name and target_name and try to identify
|
|
240
|
+
@logger.warn "#{@name}: Received unknown identified subpacket: #{subpacket.target_name} #{subpacket.packet_name}"
|
|
241
|
+
subpacket.target_name = nil
|
|
242
|
+
subpacket.packet_name = nil
|
|
243
|
+
identified_subpacket = System.telemetry.identify!(subpacket.buffer,
|
|
244
|
+
@target_names, subpackets: true)
|
|
245
|
+
end
|
|
246
|
+
else
|
|
247
|
+
# Packet needs to be identified
|
|
248
|
+
identified_subpacket = System.telemetry.identify!(subpacket.buffer,
|
|
249
|
+
@target_names, subpackets: true)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
if identified_subpacket
|
|
254
|
+
identified_subpacket.received_time = subpacket.received_time
|
|
255
|
+
identified_subpacket.stored = subpacket.stored
|
|
256
|
+
identified_subpacket.extra = subpacket.extra
|
|
257
|
+
subpacket = identified_subpacket
|
|
258
|
+
else
|
|
259
|
+
unknown_subpacket = System.telemetry.update!('UNKNOWN', 'UNKNOWN', subpacket.buffer)
|
|
260
|
+
unknown_subpacket.received_time = subpacket.received_time
|
|
261
|
+
unknown_subpacket.stored = subpacket.stored
|
|
262
|
+
unknown_subpacket.extra = subpacket.extra
|
|
263
|
+
subpacket = unknown_subpacket
|
|
264
|
+
num_bytes_to_print = [InterfaceMicroservice::UNKNOWN_BYTES_TO_PRINT, subpacket.length].min
|
|
265
|
+
data = subpacket.buffer(false)[0..(num_bytes_to_print - 1)]
|
|
266
|
+
prefix = data.each_byte.map { | byte | sprintf("%02X", byte) }.join()
|
|
267
|
+
@logger.warn "#{@name} #{subpacket.target_name} packet length: #{subpacket.length} starting with: #{prefix}"
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
TargetModel.sync_tlm_packet_counts(subpacket, @target_names, scope: @scope)
|
|
271
|
+
return subpacket
|
|
272
|
+
end
|
|
273
|
+
|
|
194
274
|
# Called when an item in any packet changes limits states.
|
|
195
275
|
#
|
|
196
276
|
# @param packet [Packet] Packet which has had an item change limits state
|