openc3 5.11.3 → 5.12.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.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/bin/openc3cli +26 -12
- data/data/config/_id_items.yaml +6 -4
- data/data/config/_id_params.yaml +9 -6
- data/data/config/_items.yaml +6 -4
- data/data/config/_params.yaml +3 -2
- data/data/config/interface_modifiers.yaml +1 -1
- data/data/config/microservice.yaml +10 -1
- data/data/config/plugins.yaml +13 -3
- data/data/config/target.yaml +9 -0
- data/data/config/target_config.yaml +12 -0
- data/data/config/tool.yaml +12 -3
- data/lib/openc3/api/api.rb +1 -1
- data/lib/openc3/api/cmd_api.rb +24 -24
- data/lib/openc3/api/config_api.rb +12 -12
- data/lib/openc3/api/limits_api.rb +4 -3
- data/lib/openc3/api/settings_api.rb +5 -2
- data/lib/openc3/api/tlm_api.rb +7 -10
- data/lib/openc3/conversions/unix_time_conversion.rb +8 -6
- data/lib/openc3/interfaces/tcpip_server_interface.rb +0 -7
- data/lib/openc3/io/json_drb.rb +3 -2
- data/lib/openc3/io/json_rpc.rb +6 -6
- data/lib/openc3/logs/buffered_packet_log_writer.rb +4 -2
- data/lib/openc3/logs/packet_log_writer.rb +22 -7
- data/lib/openc3/microservices/cleanup_microservice.rb +8 -1
- data/lib/openc3/microservices/decom_microservice.rb +1 -1
- data/lib/openc3/microservices/interface_microservice.rb +2 -2
- data/lib/openc3/microservices/microservice.rb +5 -2
- data/lib/openc3/microservices/reaction_microservice.rb +1 -0
- data/lib/openc3/microservices/timeline_microservice.rb +7 -5
- data/lib/openc3/migrations/20231022000000_tlm_viewer_config.rb +22 -0
- data/lib/openc3/models/activity_model.rb +21 -3
- data/lib/openc3/models/cvt_model.rb +2 -1
- data/lib/openc3/models/gem_model.rb +4 -1
- data/lib/openc3/models/interface_model.rb +11 -5
- data/lib/openc3/models/metadata_model.rb +11 -0
- data/lib/openc3/models/microservice_model.rb +16 -3
- data/lib/openc3/models/model.rb +18 -0
- data/lib/openc3/models/note_model.rb +11 -0
- data/lib/openc3/models/plugin_model.rb +18 -0
- data/lib/openc3/models/python_package_model.rb +104 -0
- data/lib/openc3/models/scope_model.rb +2 -0
- data/lib/openc3/models/sorted_model.rb +17 -8
- data/lib/openc3/models/target_model.rb +53 -18
- data/lib/openc3/models/tool_config_model.rb +9 -3
- data/lib/openc3/models/tool_model.rb +22 -7
- data/lib/openc3/models/widget_model.rb +19 -3
- data/lib/openc3/operators/microservice_operator.rb +2 -0
- data/lib/openc3/packets/limits.rb +6 -18
- data/lib/openc3/packets/packet.rb +1 -0
- data/lib/openc3/packets/parsers/format_string_parser.rb +4 -4
- data/lib/openc3/packets/parsers/limits_parser.rb +4 -4
- data/lib/openc3/packets/parsers/limits_response_parser.rb +5 -5
- data/lib/openc3/packets/parsers/processor_parser.rb +4 -4
- data/lib/openc3/packets/parsers/state_parser.rb +3 -3
- data/lib/openc3/script/api_shared.rb +50 -32
- data/lib/openc3/script/calendar.rb +109 -0
- data/lib/openc3/script/commands.rb +1 -8
- data/lib/openc3/script/{gems.rb → packages.rb} +20 -16
- data/lib/openc3/script/script.rb +49 -38
- data/lib/openc3/system/system.rb +2 -0
- data/lib/openc3/system/target.rb +10 -1
- data/lib/openc3/top_level.rb +2 -2
- data/lib/openc3/utilities/aws_bucket.rb +3 -2
- data/lib/openc3/utilities/bucket_file_cache.rb +1 -1
- data/lib/openc3/utilities/local_mode.rb +3 -1
- data/lib/openc3/utilities/logger.rb +1 -1
- data/lib/openc3/utilities/ruby_lex_utils.rb +0 -8
- data/lib/openc3/version.rb +6 -6
- data/templates/tool_angular/package.json +14 -14
- data/templates/tool_angular/yarn.lock +282 -129
- data/templates/tool_react/package.json +11 -11
- data/templates/tool_react/yarn.lock +353 -300
- data/templates/tool_svelte/package.json +12 -12
- data/templates/tool_svelte/src/services/openc3-api.js +16 -60
- data/templates/tool_svelte/yarn.lock +338 -212
- data/templates/tool_vue/package.json +9 -9
- data/templates/tool_vue/yarn.lock +55 -41
- data/templates/widget/package.json +10 -10
- data/templates/widget/yarn.lock +59 -45
- metadata +36 -5
data/lib/openc3/api/tlm_api.rb
CHANGED
@@ -67,22 +67,19 @@ module OpenC3
|
|
67
67
|
# @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
|
68
68
|
# @return [Object] The telemetry value formatted as requested
|
69
69
|
def tlm(*args, type: :CONVERTED, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
70
|
-
target_name, packet_name, item_name =
|
70
|
+
target_name, packet_name, item_name = _tlm_process_args(args, 'tlm', cache_timeout: cache_timeout, scope: scope)
|
71
71
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
72
72
|
CvtModel.get_item(target_name, packet_name, item_name, type: type.intern, cache_timeout: cache_timeout, scope: scope)
|
73
73
|
end
|
74
74
|
|
75
|
-
# @deprecated Use tlm with type: :RAW
|
76
75
|
def tlm_raw(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
77
76
|
tlm(*args, type: :RAW, cache_timeout: cache_timeout, scope: scope, token: token)
|
78
77
|
end
|
79
78
|
|
80
|
-
# @deprecated Use tlm with type: :FORMATTED
|
81
79
|
def tlm_formatted(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
82
80
|
tlm(*args, type: :FORMATTED, cache_timeout: cache_timeout, scope: scope, token: token)
|
83
81
|
end
|
84
82
|
|
85
|
-
# @deprecated Use tlm with type: :WITH_UNITS
|
86
83
|
def tlm_with_units(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
87
84
|
tlm(*args, type: :WITH_UNITS, cache_timeout: cache_timeout, scope: scope, token: token)
|
88
85
|
end
|
@@ -108,7 +105,7 @@ module OpenC3
|
|
108
105
|
# @param args [String|Array<String>] See the description for calling style
|
109
106
|
# @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
|
110
107
|
def set_tlm(*args, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
|
111
|
-
target_name, packet_name, item_name, value =
|
108
|
+
target_name, packet_name, item_name, value = _set_tlm_process_args(args, __method__, scope: scope)
|
112
109
|
authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
113
110
|
CvtModel.set_item(target_name, packet_name, item_name, value, type: type.intern, scope: scope)
|
114
111
|
end
|
@@ -169,7 +166,7 @@ module OpenC3
|
|
169
166
|
# description).
|
170
167
|
# @param type [Symbol] Telemetry type, :ALL (default), :RAW, :CONVERTED, :FORMATTED, :WITH_UNITS
|
171
168
|
def override_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
|
172
|
-
target_name, packet_name, item_name, value =
|
169
|
+
target_name, packet_name, item_name, value = _set_tlm_process_args(args, __method__, scope: scope)
|
173
170
|
authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
174
171
|
CvtModel.override(target_name, packet_name, item_name, value, type: type.intern, scope: scope)
|
175
172
|
end
|
@@ -194,7 +191,7 @@ module OpenC3
|
|
194
191
|
# @param type [Symbol] Telemetry type, :ALL (default), :RAW, :CONVERTED, :FORMATTED, :WITH_UNITS
|
195
192
|
# Also takes :ALL which means to normalize all telemetry types
|
196
193
|
def normalize_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
|
197
|
-
target_name, packet_name, item_name =
|
194
|
+
target_name, packet_name, item_name = _tlm_process_args(args, __method__, scope: scope)
|
198
195
|
authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
199
196
|
CvtModel.normalize(target_name, packet_name, item_name, type: type.intern, scope: scope)
|
200
197
|
end
|
@@ -389,7 +386,7 @@ module OpenC3
|
|
389
386
|
# Get the transmit counts for telemetry packets
|
390
387
|
#
|
391
388
|
# @param target_packets [Array<Array<String, String>>] Array of arrays containing target_name, packet_name
|
392
|
-
# @return [Numeric]
|
389
|
+
# @return [Array<Numeric>] Receive count for the telemetry packets
|
393
390
|
def get_tlm_cnts(target_packets, scope: $openc3_scope, token: $openc3_token)
|
394
391
|
authorize(permission: 'system', scope: scope, token: token)
|
395
392
|
counts = []
|
@@ -430,7 +427,7 @@ module OpenC3
|
|
430
427
|
return nil
|
431
428
|
end
|
432
429
|
|
433
|
-
def
|
430
|
+
def _tlm_process_args(args, method_name, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
434
431
|
case args.length
|
435
432
|
when 1
|
436
433
|
target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
|
@@ -456,7 +453,7 @@ module OpenC3
|
|
456
453
|
return [target_name, packet_name, item_name]
|
457
454
|
end
|
458
455
|
|
459
|
-
def
|
456
|
+
def _set_tlm_process_args(args, method_name, scope: $openc3_scope, token: $openc3_token)
|
460
457
|
case args.length
|
461
458
|
when 1
|
462
459
|
target_name, packet_name, item_name, value = extract_fields_from_set_tlm_text(args[0])
|
@@ -31,30 +31,32 @@ module OpenC3
|
|
31
31
|
# represents the number of seconds since the UNIX time epoch
|
32
32
|
# @param microseconds_item_name [String] The telemetry item in the packet
|
33
33
|
# which represents microseconds
|
34
|
-
def initialize(seconds_item_name, microseconds_item_name = nil)
|
34
|
+
def initialize(seconds_item_name, microseconds_item_name = nil, seconds_type = 'RAW', microseconds_type = 'RAW')
|
35
35
|
super()
|
36
36
|
@seconds_item_name = seconds_item_name
|
37
37
|
@microseconds_item_name = microseconds_item_name
|
38
38
|
@converted_type = :RUBY_TIME
|
39
39
|
@converted_bit_size = 0
|
40
|
+
@seconds_type = seconds_type.to_sym
|
41
|
+
@microseconds_type = microseconds_type.to_sym
|
40
42
|
end
|
41
43
|
|
42
44
|
# @param (see Conversion#call)
|
43
45
|
# @return [Float] Packet time in seconds since UNIX epoch
|
44
46
|
def call(value, packet, buffer)
|
45
47
|
if @microseconds_item_name
|
46
|
-
return Time.at(packet.read(@seconds_item_name,
|
48
|
+
return Time.at(packet.read(@seconds_item_name, @seconds_type, buffer), packet.read(@microseconds_item_name, @microseconds_type, buffer)).sys
|
47
49
|
else
|
48
|
-
return Time.at(packet.read(@seconds_item_name,
|
50
|
+
return Time.at(packet.read(@seconds_item_name, @seconds_type, buffer), 0).sys
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
54
|
# @return [String] The name of the class followed by the time conversion
|
53
55
|
def to_s
|
54
56
|
if @microseconds_item_name
|
55
|
-
return "Time.at(packet.read('#{@seconds_item_name}',
|
57
|
+
return "Time.at(packet.read('#{@seconds_item_name}', :#{@seconds_type}, buffer), packet.read('#{@microseconds_item_name}', :#{@microseconds_type}, buffer)).sys"
|
56
58
|
else
|
57
|
-
return "Time.at(packet.read('#{@seconds_item_name}',
|
59
|
+
return "Time.at(packet.read('#{@seconds_item_name}', :#{@seconds_type}, buffer), 0).sys"
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
@@ -66,7 +68,7 @@ module OpenC3
|
|
66
68
|
|
67
69
|
def as_json(*a)
|
68
70
|
result = super(*a)
|
69
|
-
result['params'] = [@seconds_item_name, @microseconds_item_name]
|
71
|
+
result['params'] = [@seconds_item_name, @microseconds_item_name, @seconds_type, @microseconds_type]
|
70
72
|
result
|
71
73
|
end
|
72
74
|
end # class UnixTimeConversion
|
@@ -500,13 +500,6 @@ module OpenC3
|
|
500
500
|
write_to_clients(:write_raw, data) if data
|
501
501
|
end
|
502
502
|
|
503
|
-
def interface_disconnect(interface_info)
|
504
|
-
Logger.info "#{@name}: Tcpip server lost write connection to "\
|
505
|
-
"#{interface_info.hostname}(#{interface_info.host_ip}):#{interface_info.port}"
|
506
|
-
interface_info.interface.disconnect
|
507
|
-
interface_info.interface.stream_log_pair.stop if interface_info.interface.stream_log_pair
|
508
|
-
end
|
509
|
-
|
510
503
|
def write_thread_hook(packet)
|
511
504
|
packet # By default just return the packet
|
512
505
|
end
|
data/lib/openc3/io/json_drb.rb
CHANGED
@@ -28,7 +28,8 @@ require 'drb/drb'
|
|
28
28
|
require 'set'
|
29
29
|
require 'openc3/io/json_rpc'
|
30
30
|
require 'openc3/io/json_drb_rack'
|
31
|
-
require '
|
31
|
+
require 'rackup'
|
32
|
+
require 'puma'
|
32
33
|
|
33
34
|
# Add methods to the Puma::Launcher and Puma::Single class so we can tell
|
34
35
|
# if the server has been started.
|
@@ -150,7 +151,7 @@ module OpenC3
|
|
150
151
|
}
|
151
152
|
|
152
153
|
# The run call will block until the server is stopped.
|
153
|
-
|
154
|
+
Rackup::Handler::Puma.run(JsonDrbRack.new(self), server_config) do |server|
|
154
155
|
@server_mutex.synchronize do
|
155
156
|
@server = server
|
156
157
|
end
|
data/lib/openc3/io/json_rpc.rb
CHANGED
@@ -36,9 +36,9 @@ end
|
|
36
36
|
|
37
37
|
class Struct #:nodoc:
|
38
38
|
def as_json(options = nil)
|
39
|
-
|
40
|
-
self.each_pair { |k, v|
|
41
|
-
|
39
|
+
hash = {}
|
40
|
+
self.each_pair { |k, v| hash[k.to_s] = v.as_json(options) }
|
41
|
+
hash
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -115,9 +115,9 @@ end
|
|
115
115
|
|
116
116
|
class Hash
|
117
117
|
def as_json(options = nil) #:nodoc:
|
118
|
-
|
119
|
-
self.each {
|
120
|
-
|
118
|
+
hash = {}
|
119
|
+
self.each {|k,v| hash[k.to_s] = v.as_json(options) }
|
120
|
+
hash
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -44,7 +44,8 @@ module OpenC3
|
|
44
44
|
cycle_hour = nil,
|
45
45
|
cycle_minute = nil,
|
46
46
|
enforce_time_order = true,
|
47
|
-
buffer_depth = 60 # Default assumes 1 minute of 1Hz data
|
47
|
+
buffer_depth = 60, # Default assumes 1 minute of 1Hz data
|
48
|
+
scope: $openc3_scope
|
48
49
|
)
|
49
50
|
super(
|
50
51
|
remote_log_directory,
|
@@ -54,7 +55,8 @@ module OpenC3
|
|
54
55
|
cycle_size,
|
55
56
|
cycle_hour,
|
56
57
|
cycle_minute,
|
57
|
-
enforce_time_order
|
58
|
+
enforce_time_order,
|
59
|
+
scope: scope
|
58
60
|
)
|
59
61
|
@buffer_depth = Integer(buffer_depth)
|
60
62
|
@buffer = []
|
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'openc3/logs/log_writer'
|
24
24
|
require 'openc3/logs/packet_log_constants'
|
25
|
+
require 'openc3/models/target_model'
|
25
26
|
require 'cbor'
|
26
27
|
|
27
28
|
module OpenC3
|
@@ -52,7 +53,8 @@ module OpenC3
|
|
52
53
|
cycle_size = 1_000_000_000,
|
53
54
|
cycle_hour = nil,
|
54
55
|
cycle_minute = nil,
|
55
|
-
enforce_time_order = true
|
56
|
+
enforce_time_order = true,
|
57
|
+
scope: $openc3_scope
|
56
58
|
)
|
57
59
|
super(
|
58
60
|
remote_log_directory,
|
@@ -73,6 +75,9 @@ module OpenC3
|
|
73
75
|
@target_indexes = {}
|
74
76
|
@next_target_index = 0
|
75
77
|
@data_format = :CBOR # Default to CBOR for improved compression
|
78
|
+
@target_id_cache = {}
|
79
|
+
@packet_id_cache = {}
|
80
|
+
@scope = scope
|
76
81
|
end
|
77
82
|
|
78
83
|
# Write a packet to the log file.
|
@@ -171,8 +176,14 @@ module OpenC3
|
|
171
176
|
@tlm_packet_table[target_name] = target_table
|
172
177
|
end
|
173
178
|
id = nil
|
174
|
-
|
175
|
-
|
179
|
+
unless ENV['OPENC3_NO_STORE']
|
180
|
+
id = @target_id_cache[target_name]
|
181
|
+
unless id
|
182
|
+
target = TargetModel.get(name: target_name, scope: @scope)
|
183
|
+
id = target["id"] if target
|
184
|
+
@target_id_cache[target_name] = id
|
185
|
+
end
|
186
|
+
end
|
176
187
|
write_entry(:TARGET_DECLARATION, cmd_or_tlm, target_name, packet_name, nil, nil, nil, id)
|
177
188
|
end
|
178
189
|
|
@@ -187,10 +198,14 @@ module OpenC3
|
|
187
198
|
|
188
199
|
id = nil
|
189
200
|
begin
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
id
|
201
|
+
unless ENV['OPENC3_NO_STORE']
|
202
|
+
cache_key = "#{cmd_or_tlm}__#{target_name}__#{packet_name}"
|
203
|
+
id = @packet_id_cache[cache_key]
|
204
|
+
unless id
|
205
|
+
target_model_packet = TargetModel.packet(target_name, packet_name, type: cmd_or_tlm, scope: @scope)
|
206
|
+
id = target_model_packet["config_name"] if target_model_packet
|
207
|
+
@packet_id_cache[cache_key] = id
|
208
|
+
end
|
194
209
|
end
|
195
210
|
rescue
|
196
211
|
# No packet def
|
@@ -49,7 +49,14 @@ module OpenC3
|
|
49
49
|
if oldest_list.length > 0
|
50
50
|
@state = 'DELETING_OBJECTS'
|
51
51
|
oldest_list.each_slice(1000) do |slice|
|
52
|
-
|
52
|
+
# The delete_objects function utilizes an MD5 hash when verifying the checksums, which is not
|
53
|
+
# FIPS compliant (https://github.com/aws/aws-sdk-ruby/issues/2645).
|
54
|
+
# delete_object does NOT require an MD5 hash and will work on FIPS compliant systems. It is
|
55
|
+
# probably less performant, but we can instead delete each item one at a time.
|
56
|
+
# bucket.delete_objects(bucket: ENV['OPENC3_LOGS_BUCKET'], keys: slice)
|
57
|
+
slice.each do |item|
|
58
|
+
bucket.delete_object(bucket: ENV['OPENC3_LOGS_BUCKET'], key: item)
|
59
|
+
end
|
53
60
|
@logger.debug("Cleanup deleted #{slice.length} log files")
|
54
61
|
@delete_count += slice.length
|
55
62
|
@metric.set(name: 'cleanup_delete_total', value: @delete_count, type: 'counter')
|
@@ -34,7 +34,7 @@ module OpenC3
|
|
34
34
|
# Should only be one target, but there might be multiple decom microservices for a given target
|
35
35
|
# First Decom microservice has no number in the name
|
36
36
|
if @name =~ /__DECOM__/
|
37
|
-
@topics << "#{scope}__DECOMINTERFACE__{#{@target_names[0]}}"
|
37
|
+
@topics << "#{@scope}__DECOMINTERFACE__{#{@target_names[0]}}"
|
38
38
|
end
|
39
39
|
Topic.update_topic_offsets(@topics)
|
40
40
|
System.telemetry.limits_change_callback = method(:limits_change_callback)
|
@@ -348,13 +348,13 @@ module OpenC3
|
|
348
348
|
def initialize(name)
|
349
349
|
@mutex = Mutex.new
|
350
350
|
super(name)
|
351
|
+
@interface_or_router = self.class.name.to_s.split("Microservice")[0].upcase.split("::")[-1]
|
351
352
|
if @interface_or_router == 'INTERFACE'
|
352
353
|
@metric.set(name: 'interface_tlm_total', value: @count, type: 'counter')
|
353
354
|
else
|
354
355
|
@metric.set(name: 'router_cmd_total', value: @count, type: 'counter')
|
355
356
|
end
|
356
357
|
|
357
|
-
@interface_or_router = self.class.name.to_s.split("Microservice")[0].upcase.split("::")[-1]
|
358
358
|
@scope = name.split("__")[0]
|
359
359
|
interface_name = name.split("__")[2]
|
360
360
|
if @interface_or_router == 'INTERFACE'
|
@@ -553,7 +553,7 @@ module OpenC3
|
|
553
553
|
unknown_packet.extra = packet.extra
|
554
554
|
packet = unknown_packet
|
555
555
|
json_hash = CvtModel.build_json_from_packet(packet)
|
556
|
-
CvtModel.set(json_hash, target_name: packet.target_name, packet_name: packet.packet_name, scope: scope)
|
556
|
+
CvtModel.set(json_hash, target_name: packet.target_name, packet_name: packet.packet_name, scope: @scope)
|
557
557
|
num_bytes_to_print = [UNKNOWN_BYTES_TO_PRINT, packet.length].min
|
558
558
|
data = packet.buffer(false)[0..(num_bytes_to_print - 1)]
|
559
559
|
prefix = data.each_byte.map { | byte | sprintf("%02X", byte) }.join()
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2023, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -79,7 +79,7 @@ module OpenC3
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def initialize(name, is_plugin: false)
|
82
|
-
|
82
|
+
@shutdown_complete = false
|
83
83
|
raise "Microservice must be named" unless name
|
84
84
|
|
85
85
|
@name = name
|
@@ -120,6 +120,7 @@ module OpenC3
|
|
120
120
|
# Get configuration for any targets
|
121
121
|
@target_names = @config["target_names"]
|
122
122
|
@target_names ||= []
|
123
|
+
# NOTE: setup_targets doesn't do anything if @target_names is empty
|
123
124
|
System.setup_targets(@target_names, @temp_dir, scope: @scope) unless is_plugin
|
124
125
|
|
125
126
|
# Use at_exit to shutdown cleanly no matter how we die
|
@@ -199,6 +200,7 @@ module OpenC3
|
|
199
200
|
end
|
200
201
|
|
201
202
|
def shutdown
|
203
|
+
return if @shutdown_complete
|
202
204
|
@logger.info("Shutting down microservice: #{@name}")
|
203
205
|
@cancel_thread = true
|
204
206
|
@microservice_status_sleeper.cancel if @microservice_status_sleeper
|
@@ -206,6 +208,7 @@ module OpenC3
|
|
206
208
|
FileUtils.remove_entry(@temp_dir) if File.exist?(@temp_dir)
|
207
209
|
@metric.shutdown
|
208
210
|
@logger.info("Shutting down microservice complete: #{@name}")
|
211
|
+
@shutdown_complete = true
|
209
212
|
end
|
210
213
|
end
|
211
214
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2023, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -43,6 +43,7 @@ module OpenC3
|
|
43
43
|
|
44
44
|
def get_token(username)
|
45
45
|
if ENV['OPENC3_API_CLIENT'].nil?
|
46
|
+
ENV['OPENC3_API_PASSWORD'] ||= ENV['OPENC3_SERVICE_PASSWORD']
|
46
47
|
return OpenC3Authentication.new().token
|
47
48
|
else
|
48
49
|
# Check for offline access token
|
@@ -125,7 +126,8 @@ module OpenC3
|
|
125
126
|
|
126
127
|
def clear_expired(activity)
|
127
128
|
begin
|
128
|
-
ActivityModel.range_destroy(name: @timeline_name, scope: @scope, min: activity.start, max: activity.stop)
|
129
|
+
num = ActivityModel.range_destroy(name: @timeline_name, scope: @scope, min: activity.start, max: activity.stop)
|
130
|
+
@logger.info "#{@timeline_name} clear_expired removed #{num} items from #{activity.start} to #{activity.stop}"
|
129
131
|
activity.add_event(status: 'completed')
|
130
132
|
rescue StandardError => e
|
131
133
|
@logger.error "#{@timeline_name} clear_expired failed > #{activity.as_json(:allow_nan => true)} #{e.message}"
|
@@ -231,15 +233,15 @@ module OpenC3
|
|
231
233
|
@logger.info "#{@timeline_name} timeine manager exiting"
|
232
234
|
end
|
233
235
|
|
234
|
-
# Add task to remove events older than 7
|
236
|
+
# Add task to remove events older than 7 days
|
235
237
|
def add_expire_activity
|
236
238
|
now = Time.now.to_i
|
237
239
|
@expire = now + 3_000
|
238
240
|
activity = ActivityModel.new(
|
239
241
|
name: @timeline_name,
|
240
242
|
scope: @scope,
|
241
|
-
start:
|
242
|
-
stop: (now -
|
243
|
+
start: 0,
|
244
|
+
stop: (now - 86_400 * 7),
|
243
245
|
kind: 'EXPIRE',
|
244
246
|
data: {}
|
245
247
|
)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'openc3/utilities/migration'
|
2
|
+
require 'openc3/models/tool_config_model'
|
3
|
+
|
4
|
+
module OpenC3
|
5
|
+
class TlmViewerConfig < Migration
|
6
|
+
def self.run
|
7
|
+
ScopeModel.names.each do |scope|
|
8
|
+
# Get all existing ToolConfigModels and change keys from tlm_viewer to telemetry_viewer
|
9
|
+
names = ToolConfigModel.list_configs('tlm_viewer')
|
10
|
+
names.each do |name|
|
11
|
+
config = ToolConfigModel.load_config('tlm_viewer', name)
|
12
|
+
ToolConfigModel.save_config('telemetry_viewer', name, config)
|
13
|
+
ToolConfigModel.delete_config('tlm_viewer', name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
unless ENV['OPENC3_NO_MIGRATE']
|
21
|
+
OpenC3::TlmViewerConfig.run
|
22
|
+
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2023, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -94,13 +94,31 @@ module OpenC3
|
|
94
94
|
# Remove one member from a sorted set.
|
95
95
|
# @return [Integer] count of the members removed
|
96
96
|
def self.destroy(name:, scope:, score:)
|
97
|
-
Store.zremrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", score, score)
|
97
|
+
result = Store.zremrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", score, score)
|
98
|
+
notification = {
|
99
|
+
# start / stop to match SortedModel
|
100
|
+
'data' => JSON.generate({'start' => score}),
|
101
|
+
'kind' => 'deleted',
|
102
|
+
'type' => 'activity',
|
103
|
+
'timeline' => name
|
104
|
+
}
|
105
|
+
TimelineTopic.write_activity(notification, scope: scope)
|
106
|
+
return result
|
98
107
|
end
|
99
108
|
|
100
109
|
# Remove members from min to max of the sorted set.
|
101
110
|
# @return [Integer] count of the members removed
|
102
111
|
def self.range_destroy(name:, scope:, min:, max:)
|
103
|
-
Store.zremrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", min, max)
|
112
|
+
result = Store.zremrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", min, max)
|
113
|
+
notification = {
|
114
|
+
# start / stop to match SortedModel
|
115
|
+
'data' => JSON.generate({'start' => min, 'stop' => max}),
|
116
|
+
'kind' => 'deleted',
|
117
|
+
'type' => 'activity',
|
118
|
+
'timeline' => name
|
119
|
+
}
|
120
|
+
TimelineTopic.write_activity(notification, scope: scope)
|
121
|
+
return result
|
104
122
|
end
|
105
123
|
|
106
124
|
# @return [ActivityModel] Model generated from the passed JSON
|
@@ -237,10 +237,11 @@ module OpenC3
|
|
237
237
|
end
|
238
238
|
|
239
239
|
tgt_pkt_key = "#{scope}__tlm__#{target_name}__#{packet_name}"
|
240
|
-
@@override_cache[tgt_pkt_key] = [Time.now, hash]
|
241
240
|
if hash.empty?
|
241
|
+
@@override_cache.delete(tgt_pkt_key)
|
242
242
|
Store.hdel("#{scope}__override__#{target_name}", packet_name)
|
243
243
|
else
|
244
|
+
@@override_cache[tgt_pkt_key] = [Time.now, hash]
|
244
245
|
Store.hset("#{scope}__override__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
|
245
246
|
end
|
246
247
|
end
|
@@ -27,6 +27,7 @@ require 'rubygems'
|
|
27
27
|
require 'rubygems/uninstaller'
|
28
28
|
require 'tempfile'
|
29
29
|
require 'openc3/utilities/process_manager'
|
30
|
+
require 'openc3/api/api'
|
30
31
|
require 'pathname'
|
31
32
|
|
32
33
|
module OpenC3
|
@@ -35,6 +36,8 @@ module OpenC3
|
|
35
36
|
# and destroy to allow interaction with gem files from the PluginModel and
|
36
37
|
# the GemsController.
|
37
38
|
class GemModel
|
39
|
+
include Api
|
40
|
+
|
38
41
|
def self.names
|
39
42
|
result = Pathname.new("#{ENV['GEM_HOME']}/gems").children.select { |c| c.directory? }.collect { |p| File.basename(p) + '.gem' }
|
40
43
|
return result.sort
|
@@ -53,7 +56,7 @@ module OpenC3
|
|
53
56
|
FileUtils.cp(gem_file_path, "#{ENV['GEM_HOME']}/cache/#{File.basename(gem_file_path)}")
|
54
57
|
if gem_install
|
55
58
|
Logger.info "Installing gem: #{gem_filename}"
|
56
|
-
result = OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "geminstall", gem_filename, scope], "
|
59
|
+
result = OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "geminstall", gem_filename, scope], "package_install", gem_filename, Time.now + 3600.0, scope: scope)
|
57
60
|
return result.name
|
58
61
|
end
|
59
62
|
else
|
@@ -145,7 +145,13 @@ module OpenC3
|
|
145
145
|
unless @cmd
|
146
146
|
type = self.class._get_type
|
147
147
|
microservice_name = "#{@scope}__#{type}__#{@name}"
|
148
|
-
|
148
|
+
if config_params[0] and File.extname(config_params[0]) == '.py'
|
149
|
+
work_dir.sub!('openc3/lib', 'openc3/python')
|
150
|
+
@cmd = ["python", "#{type.downcase}_microservice.py", microservice_name]
|
151
|
+
else
|
152
|
+
# If there are no config_params we assume ruby
|
153
|
+
@cmd = ["ruby", "#{type.downcase}_microservice.rb", microservice_name]
|
154
|
+
end
|
149
155
|
end
|
150
156
|
@work_dir = work_dir
|
151
157
|
@ports = ports
|
@@ -417,7 +423,7 @@ module OpenC3
|
|
417
423
|
# Respawn the microservice
|
418
424
|
type = self.class._get_type
|
419
425
|
microservice_name = "#{@scope}__#{type}__#{@name}"
|
420
|
-
microservice = MicroserviceModel.get_model(name: microservice_name, scope: scope)
|
426
|
+
microservice = MicroserviceModel.get_model(name: microservice_name, scope: @scope)
|
421
427
|
microservice.target_names.delete(target_name) unless @target_names.include?(target_name)
|
422
428
|
microservice.update
|
423
429
|
end
|
@@ -432,11 +438,11 @@ module OpenC3
|
|
432
438
|
|
433
439
|
if unmap_old
|
434
440
|
# Remove from old interface
|
435
|
-
all_interfaces = InterfaceModel.all(scope: scope)
|
441
|
+
all_interfaces = InterfaceModel.all(scope: @scope)
|
436
442
|
old_interface = nil
|
437
443
|
all_interfaces.each do |old_interface_name, old_interface_details|
|
438
444
|
if old_interface_details['target_names'].include?(target_name)
|
439
|
-
old_interface = InterfaceModel.from_json(old_interface_details, scope: scope)
|
445
|
+
old_interface = InterfaceModel.from_json(old_interface_details, scope: @scope)
|
440
446
|
old_interface.unmap_target(target_name, cmd_only: cmd_only, tlm_only: tlm_only) if old_interface
|
441
447
|
end
|
442
448
|
end
|
@@ -451,7 +457,7 @@ module OpenC3
|
|
451
457
|
# Respawn the microservice
|
452
458
|
type = self.class._get_type
|
453
459
|
microservice_name = "#{@scope}__#{type}__#{@name}"
|
454
|
-
microservice = MicroserviceModel.get_model(name: microservice_name, scope: scope)
|
460
|
+
microservice = MicroserviceModel.get_model(name: microservice_name, scope: @scope)
|
455
461
|
microservice.target_names << target_name unless microservice.target_names.include?(target_name)
|
456
462
|
microservice.update
|
457
463
|
end
|
@@ -33,6 +33,17 @@ module OpenC3
|
|
33
33
|
"#{scope}#{PRIMARY_KEY}"
|
34
34
|
end
|
35
35
|
|
36
|
+
def self.notify(scope:, kind:, start:, stop: nil)
|
37
|
+
json = {'type' => METADATA_TYPE, 'start' => start}
|
38
|
+
json['stop'] = stop if stop
|
39
|
+
notification = {
|
40
|
+
'data' => JSON.generate(json),
|
41
|
+
'kind' => kind,
|
42
|
+
'type' => 'calendar',
|
43
|
+
}
|
44
|
+
CalendarTopic.write_entry(notification, scope: scope)
|
45
|
+
end
|
46
|
+
|
36
47
|
attr_reader :color, :metadata, :constraints, :type
|
37
48
|
|
38
49
|
# @param [Integer] start - Time metadata is active in seconds from Epoch
|
@@ -42,6 +42,7 @@ module OpenC3
|
|
42
42
|
attr_accessor :parent
|
43
43
|
attr_accessor :secrets
|
44
44
|
attr_accessor :prefix
|
45
|
+
attr_accessor :disable_erb
|
45
46
|
|
46
47
|
# NOTE: The following three class methods are used by the ModelController
|
47
48
|
# and are reimplemented to enable various Model class methods to work
|
@@ -101,6 +102,7 @@ module OpenC3
|
|
101
102
|
needs_dependencies: false,
|
102
103
|
secrets: [],
|
103
104
|
prefix: nil,
|
105
|
+
disable_erb: nil,
|
104
106
|
scope:
|
105
107
|
)
|
106
108
|
parts = name.split("__")
|
@@ -125,6 +127,7 @@ module OpenC3
|
|
125
127
|
@needs_dependencies = needs_dependencies
|
126
128
|
@secrets = secrets
|
127
129
|
@prefix = prefix
|
130
|
+
@disable_erb = disable_erb
|
128
131
|
@bucket = Bucket.getClient()
|
129
132
|
end
|
130
133
|
|
@@ -145,7 +148,8 @@ module OpenC3
|
|
145
148
|
'plugin' => @plugin,
|
146
149
|
'needs_dependencies' => @needs_dependencies,
|
147
150
|
'secrets' => @secrets.as_json(*a),
|
148
|
-
'prefix' => @prefix
|
151
|
+
'prefix' => @prefix,
|
152
|
+
'disable_erb' => @disable_erb
|
149
153
|
}
|
150
154
|
end
|
151
155
|
|
@@ -201,6 +205,12 @@ module OpenC3
|
|
201
205
|
when 'ROUTE_PREFIX'
|
202
206
|
parser.verify_num_parameters(1, 1, "#{keyword} <Route Prefix>")
|
203
207
|
@prefix = parameters[0]
|
208
|
+
when 'DISABLE_ERB'
|
209
|
+
# 0 to unlimited parameters
|
210
|
+
@disable_erb ||= []
|
211
|
+
if parameters
|
212
|
+
@disable_erb.concat(parameters)
|
213
|
+
end
|
204
214
|
else
|
205
215
|
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Microservice: #{keyword} #{parameters.join(" ")}")
|
206
216
|
end
|
@@ -220,8 +230,11 @@ module OpenC3
|
|
220
230
|
|
221
231
|
# Load microservice files
|
222
232
|
data = File.read(filename, mode: "rb")
|
223
|
-
|
224
|
-
|
233
|
+
erb_disabled = check_disable_erb(filename)
|
234
|
+
unless erb_disabled
|
235
|
+
OpenC3.set_working_dir(File.dirname(filename)) do
|
236
|
+
data = ERB.new(data.comment_erb(), trim_mode: "-").result(binding.set_variables(variables)) if data.is_printable? and File.basename(filename)[0] != '_'
|
237
|
+
end
|
225
238
|
end
|
226
239
|
unless validate_only
|
227
240
|
@bucket.put_object(bucket: ENV['OPENC3_CONFIG_BUCKET'], key: key, body: data)
|