openc3 5.5.2 → 5.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/openc3cli +167 -69
- data/data/config/_interfaces.yaml +1 -6
- data/data/config/interface_modifiers.yaml +55 -4
- data/data/config/microservice.yaml +30 -3
- data/ext/openc3/ext/crc/crc.c +82 -1
- data/lib/openc3/api/cmd_api.rb +19 -7
- data/lib/openc3/api/tlm_api.rb +13 -12
- data/lib/openc3/bridge/bridge_config.rb +4 -4
- data/lib/openc3/config/config_parser.rb +1 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +3 -1
- data/lib/openc3/ext/.keep +0 -0
- data/lib/openc3/interfaces/interface.rb +54 -26
- data/lib/openc3/interfaces/serial_interface.rb +4 -5
- data/lib/openc3/interfaces/simulated_target_interface.rb +4 -4
- data/lib/openc3/interfaces/stream_interface.rb +2 -2
- data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -3
- data/lib/openc3/interfaces/tcpip_server_interface.rb +18 -19
- data/lib/openc3/interfaces/udp_interface.rb +10 -4
- data/lib/openc3/io/json_api.rb +72 -0
- data/lib/openc3/io/serial_driver.rb +4 -5
- data/lib/openc3/logs/buffered_packet_log_writer.rb +2 -4
- data/lib/openc3/logs/log_writer.rb +9 -8
- data/lib/openc3/logs/packet_log_reader.rb +8 -1
- data/lib/openc3/logs/packet_log_writer.rb +3 -4
- data/lib/openc3/logs/stream_log.rb +116 -0
- data/lib/openc3/logs/stream_log_pair.rb +70 -0
- data/lib/openc3/microservices/cleanup_microservice.rb +1 -1
- data/lib/openc3/microservices/decom_microservice.rb +17 -2
- data/lib/openc3/microservices/interface_decom_common.rb +42 -0
- data/lib/openc3/microservices/interface_microservice.rb +24 -17
- data/lib/openc3/microservices/router_microservice.rb +46 -4
- data/lib/openc3/migrations/20221202214600_add_target_names.rb +1 -1
- data/lib/openc3/migrations/20230319154100_log_stream.rb +40 -0
- data/lib/openc3/migrations/20230413101100_remove_log.rb +30 -0
- data/lib/openc3/models/gem_model.rb +2 -2
- data/lib/openc3/models/interface_model.rb +13 -14
- data/lib/openc3/models/metadata_model.rb +1 -1
- data/lib/openc3/models/note_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +3 -2
- data/lib/openc3/operators/operator.rb +2 -0
- data/lib/openc3/packets/commands.rb +2 -0
- data/lib/openc3/packets/packet_config.rb +3 -2
- data/lib/openc3/packets/parsers/xtce_converter.rb +2 -1
- data/lib/openc3/script/gems.rb +125 -0
- data/lib/openc3/script/plugins.rb +186 -0
- data/lib/openc3/script/screen.rb +119 -0
- data/lib/openc3/script/script.rb +3 -0
- data/lib/openc3/script/script_runner.rb +19 -8
- data/lib/openc3/script/suite_results.rb +2 -2
- data/lib/openc3/script/web_socket_api.rb +5 -1
- data/lib/openc3/streams/serial_stream.rb +14 -11
- data/lib/openc3/streams/tcpip_client_stream.rb +5 -2
- data/lib/openc3/streams/tcpip_socket_stream.rb +37 -71
- data/lib/openc3/streams/web_socket_client_stream.rb +5 -3
- data/lib/openc3/system/system.rb +2 -0
- data/lib/openc3/topics/interface_topic.rb +13 -4
- data/lib/openc3/topics/router_topic.rb +6 -6
- data/lib/openc3/topics/telemetry_decom_topic.rb +10 -1
- data/lib/openc3/utilities/bucket_utilities.rb +12 -5
- data/lib/openc3/utilities/cli_generator.rb +56 -4
- data/lib/openc3/utilities/crc.rb +42 -7
- data/lib/openc3/utilities/process_manager.rb +3 -1
- data/lib/openc3/utilities/ruby_lex_utils.rb +265 -504
- data/lib/openc3/version.rb +6 -6
- data/templates/conversion/conversion.rb +10 -2
- data/templates/microservice/microservices/TEMPLATE/microservice.rb +1 -1
- data/templates/plugin/Rakefile +8 -1
- data/templates/widget/.browserslistrc +16 -0
- data/templates/widget/.eslintrc.js +43 -0
- data/templates/widget/.nycrc +3 -0
- data/templates/widget/.prettierrc.js +5 -0
- data/templates/widget/LICENSE.txt +20 -0
- data/templates/widget/Rakefile +24 -0
- data/templates/widget/babel.config.json +11 -0
- data/templates/widget/package.json +35 -0
- data/templates/widget/src/Widget.vue +46 -0
- data/templates/widget/vue.config.js +25 -0
- data/templates/widget/yarn.lock +8938 -0
- metadata +23 -4
- data/lib/openc3/io/raw_logger.rb +0 -170
- data/lib/openc3/io/raw_logger_pair.rb +0 -80
@@ -26,11 +26,9 @@ module OpenC3
|
|
26
26
|
# @param label [String] Label to apply to the log filename
|
27
27
|
# @param logging_enabled [Boolean] Whether to start with logging enabled
|
28
28
|
# @param cycle_time [Integer] The amount of time in seconds before creating
|
29
|
-
# a new log file. This can be combined with cycle_size
|
30
|
-
# independently.
|
29
|
+
# a new log file. This can be combined with cycle_size.
|
31
30
|
# @param cycle_size [Integer] The size in bytes before creating a new log
|
32
|
-
# file. This can be combined with cycle_time
|
33
|
-
# independently.
|
31
|
+
# file. This can be combined with cycle_time.
|
34
32
|
# @param cycle_hour [Integer] The time at which to cycle the log. Combined with
|
35
33
|
# cycle_minute to cycle the log daily at the specified time. If nil, the log
|
36
34
|
# will be cycled hourly at the specified cycle_minute.
|
@@ -36,10 +36,13 @@ module OpenC3
|
|
36
36
|
attr_reader :logging_enabled
|
37
37
|
|
38
38
|
# @return cycle_time [Integer] The amount of time in seconds before creating
|
39
|
-
# a new log file. This can be combined with cycle_size
|
40
|
-
# independently.
|
39
|
+
# a new log file. This can be combined with cycle_size.
|
41
40
|
attr_reader :cycle_time
|
42
41
|
|
42
|
+
# @return cycle_size [Integer] The amount of data in bytes before creating
|
43
|
+
# a new log file. This can be combined with cycle_time.
|
44
|
+
attr_reader :cycle_size
|
45
|
+
|
43
46
|
# @return cycle_hour [Integer] The time at which to cycle the log. Combined with
|
44
47
|
# cycle_minute to cycle the log daily at the specified time. If nil, the log
|
45
48
|
# will be cycled hourly at the specified cycle_minute.
|
@@ -83,11 +86,9 @@ module OpenC3
|
|
83
86
|
# @param remote_log_directory [String] The path to store the log files
|
84
87
|
# @param logging_enabled [Boolean] Whether to start with logging enabled
|
85
88
|
# @param cycle_time [Integer] The amount of time in seconds before creating
|
86
|
-
# a new log file. This can be combined with cycle_size
|
87
|
-
# independently.
|
89
|
+
# a new log file. This can be combined with cycle_size.
|
88
90
|
# @param cycle_size [Integer] The size in bytes before creating a new log
|
89
|
-
# file. This can be combined with cycle_time
|
90
|
-
# independently.
|
91
|
+
# file. This can be combined with cycle_time.
|
91
92
|
# @param cycle_hour [Integer] The time at which to cycle the log. Combined with
|
92
93
|
# cycle_minute to cycle the log daily at the specified time. If nil, the log
|
93
94
|
# will be cycled hourly at the specified cycle_minute.
|
@@ -97,7 +98,7 @@ module OpenC3
|
|
97
98
|
remote_log_directory,
|
98
99
|
logging_enabled = true,
|
99
100
|
cycle_time = nil,
|
100
|
-
cycle_size =
|
101
|
+
cycle_size = 1_000_000_000,
|
101
102
|
cycle_hour = nil,
|
102
103
|
cycle_minute = nil,
|
103
104
|
enforce_time_order = true
|
@@ -278,7 +279,7 @@ module OpenC3
|
|
278
279
|
OpenC3.handle_critical_exception(err)
|
279
280
|
end
|
280
281
|
|
281
|
-
def prepare_write(time_nsec_since_epoch, data_length, redis_topic, redis_offset)
|
282
|
+
def prepare_write(time_nsec_since_epoch, data_length, redis_topic = nil, redis_offset = nil)
|
282
283
|
# This check includes logging_enabled again because it might have changed since we acquired the mutex
|
283
284
|
# Ensures new files based on size, and ensures always increasing time order in files
|
284
285
|
if @logging_enabled
|
@@ -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/core_ext/io'
|
@@ -174,6 +174,13 @@ module OpenC3
|
|
174
174
|
elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_PACKET_DECLARATION_ENTRY_TYPE_MASK
|
175
175
|
target_index = entry[2..3].unpack('n')[0]
|
176
176
|
target_name = @target_names[target_index]
|
177
|
+
unless target_name
|
178
|
+
# There was a bug in the PacketLogWriter before version 5.6.0 that stored an invalid target_index
|
179
|
+
# Attempt to work around by reading the target_name from the filename
|
180
|
+
filename_split = @filename.to_s.split('__')
|
181
|
+
target_name = filename_split[3]
|
182
|
+
target_name = 'UNKNOWN' unless target_name
|
183
|
+
end
|
177
184
|
packet_name_length = length - OPENC3_PRIMARY_FIXED_SIZE - OPENC3_PACKET_DECLARATION_SECONDARY_FIXED_SIZE
|
178
185
|
packet_name_length -= OPENC3_ID_FIXED_SIZE if id
|
179
186
|
packet_name = entry[4..(packet_name_length + 3)]
|
@@ -36,11 +36,9 @@ module OpenC3
|
|
36
36
|
# @param label [String] Label to apply to the log filename
|
37
37
|
# @param logging_enabled [Boolean] Whether to start with logging enabled
|
38
38
|
# @param cycle_time [Integer] The amount of time in seconds before creating
|
39
|
-
# a new log file. This can be combined with cycle_size
|
40
|
-
# independently.
|
39
|
+
# a new log file. This can be combined with cycle_size.
|
41
40
|
# @param cycle_size [Integer] The size in bytes before creating a new log
|
42
|
-
# file. This can be combined with cycle_time
|
43
|
-
# independently.
|
41
|
+
# file. This can be combined with cycle_time.
|
44
42
|
# @param cycle_hour [Integer] The time at which to cycle the log. Combined with
|
45
43
|
# cycle_minute to cycle the log daily at the specified time. If nil, the log
|
46
44
|
# will be cycled hourly at the specified cycle_minute.
|
@@ -129,6 +127,7 @@ module OpenC3
|
|
129
127
|
@key_map_table = {}
|
130
128
|
@next_packet_index = 0
|
131
129
|
@target_indexes = {}
|
130
|
+
@next_target_index = 0
|
132
131
|
@target_dec_entries = []
|
133
132
|
@packet_dec_entries = []
|
134
133
|
@key_map_entries = []
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2023 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
|
+
require 'openc3/logs/log_writer'
|
20
|
+
|
21
|
+
module OpenC3
|
22
|
+
# Creates a log file of stream data for either reads or writes. Can automatically
|
23
|
+
# cycle the log based on when the log file reaches a predefined size or based on time.
|
24
|
+
class StreamLog < LogWriter
|
25
|
+
# @return [String] Original name passed to stream log
|
26
|
+
attr_reader :orig_name
|
27
|
+
|
28
|
+
# The allowable log types
|
29
|
+
LOG_TYPES = [:READ, :WRITE]
|
30
|
+
|
31
|
+
# @param log_name [String] The name of the stream log. Typically matches the
|
32
|
+
# name of the corresponding interface
|
33
|
+
# @param log_type [Symbol] The type of log to create. Must be :READ
|
34
|
+
# or :WRITE.
|
35
|
+
# @param cycle_time [Integer] The amount of time in seconds before creating
|
36
|
+
# a new log file. This can be combined with cycle_size.
|
37
|
+
# @param cycle_size [Integer] The size in bytes before creating a new log
|
38
|
+
# file. This can be combined with cycle_time.
|
39
|
+
# @param cycle_hour [Integer] The time at which to cycle the log. Combined with
|
40
|
+
# cycle_minute to cycle the log daily at the specified time. If nil, the log
|
41
|
+
# will be cycled hourly at the specified cycle_minute.
|
42
|
+
# @param cycle_minute [Integer] The time at which to cycle the log. See cycle_hour
|
43
|
+
# for more information.
|
44
|
+
def initialize(
|
45
|
+
log_name,
|
46
|
+
log_type,
|
47
|
+
cycle_time = 600, # 10 minutes, matches time in target_model
|
48
|
+
cycle_size = 50_000_000, # 50MB, matches size in target_model
|
49
|
+
cycle_hour = nil,
|
50
|
+
cycle_minute = nil
|
51
|
+
)
|
52
|
+
raise "log_type must be :READ or :WRITE" unless LOG_TYPES.include? log_type
|
53
|
+
|
54
|
+
super(
|
55
|
+
"#{ENV['OPENC3_SCOPE']}/stream_logs/",
|
56
|
+
true, # Start with logging enabled
|
57
|
+
cycle_time,
|
58
|
+
cycle_size,
|
59
|
+
cycle_hour,
|
60
|
+
cycle_minute
|
61
|
+
)
|
62
|
+
|
63
|
+
@log_type = log_type
|
64
|
+
self.name = log_name
|
65
|
+
end
|
66
|
+
|
67
|
+
# Set the stream log name
|
68
|
+
# @param log_name [String] new name
|
69
|
+
def name=(log_name)
|
70
|
+
@orig_name = log_name
|
71
|
+
@log_name = (log_name.to_s.downcase + '_stream_' + @log_type.to_s.downcase).freeze
|
72
|
+
end
|
73
|
+
|
74
|
+
# Create a clone of this object with a new name
|
75
|
+
def clone
|
76
|
+
stream_log = super()
|
77
|
+
stream_log.name = stream_log.orig_name
|
78
|
+
stream_log
|
79
|
+
end
|
80
|
+
|
81
|
+
# Write to the log file.
|
82
|
+
#
|
83
|
+
# If no log file currently exists in the filesystem, a new file will be
|
84
|
+
# created.
|
85
|
+
#
|
86
|
+
# @param data [String] String of data
|
87
|
+
def write(data)
|
88
|
+
return if !@logging_enabled
|
89
|
+
return if !data or data.length <= 0
|
90
|
+
|
91
|
+
@mutex.synchronize do
|
92
|
+
time_nsec_since_epoch = Time.now.to_nsec_from_epoch
|
93
|
+
prepare_write(time_nsec_since_epoch, data.length)
|
94
|
+
write_entry(time_nsec_since_epoch, data) if @file
|
95
|
+
end
|
96
|
+
rescue => err
|
97
|
+
Logger.instance.error "Error writing #{@filename} : #{err.formatted}"
|
98
|
+
OpenC3.handle_critical_exception(err)
|
99
|
+
end
|
100
|
+
|
101
|
+
def write_entry(time_nsec_since_epoch, data)
|
102
|
+
@file.write(data)
|
103
|
+
@file_size += data.length
|
104
|
+
@first_time = time_nsec_since_epoch unless @first_time
|
105
|
+
@last_time = time_nsec_since_epoch
|
106
|
+
end
|
107
|
+
|
108
|
+
def bucket_filename
|
109
|
+
"#{first_timestamp}__#{@log_name}" + extension
|
110
|
+
end
|
111
|
+
|
112
|
+
def extension
|
113
|
+
'.bin'.freeze
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2023 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
|
+
require 'openc3/logs/stream_log'
|
20
|
+
|
21
|
+
module OpenC3
|
22
|
+
# Holds a read/write pair of stream logs
|
23
|
+
class StreamLogPair
|
24
|
+
# @return [StreamLog] The read log
|
25
|
+
attr_accessor :read_log
|
26
|
+
# @return [StreamLog] The write log
|
27
|
+
attr_accessor :write_log
|
28
|
+
|
29
|
+
# @param name [String] name to be added to log filenames
|
30
|
+
# @param params [Array] stream log writer parameters or empty array
|
31
|
+
def initialize(name, params = [])
|
32
|
+
@read_log = StreamLog.new(name, :READ, *params)
|
33
|
+
@write_log = StreamLog.new(name, :WRITE, *params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Change the stream log name
|
37
|
+
# @param name [String] new name
|
38
|
+
def name=(name)
|
39
|
+
@read_log.name = name
|
40
|
+
@write_log.name = name
|
41
|
+
end
|
42
|
+
|
43
|
+
# Start stream logs
|
44
|
+
def start
|
45
|
+
@read_log.start
|
46
|
+
@write_log.start
|
47
|
+
end
|
48
|
+
|
49
|
+
# Close any open stream log files
|
50
|
+
def stop
|
51
|
+
@read_log.stop
|
52
|
+
@write_log.stop
|
53
|
+
end
|
54
|
+
|
55
|
+
def shutdown
|
56
|
+
@read_log.shutdown
|
57
|
+
@write_log.shutdown
|
58
|
+
end
|
59
|
+
|
60
|
+
# Clone the stream log pair
|
61
|
+
def clone
|
62
|
+
stream_log_pair = super()
|
63
|
+
stream_log_pair.read_log = @read_log.clone
|
64
|
+
stream_log_pair.write_log = @write_log.clone
|
65
|
+
stream_log_pair.read_log.start if @read_log.logging_enabled
|
66
|
+
stream_log_pair.write_log.start if @write_log.logging_enabled
|
67
|
+
stream_log_pair
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -62,7 +62,7 @@ module OpenC3
|
|
62
62
|
@state = 'DELETING_OBJECTS'
|
63
63
|
oldest_list.each_slice(1000) do |slice|
|
64
64
|
bucket.delete_objects(bucket: ENV['OPENC3_LOGS_BUCKET'], keys: slice)
|
65
|
-
@logger.
|
65
|
+
@logger.debug("Deleted #{slice.length} #{target_name} log files")
|
66
66
|
@delete_count += slice.length
|
67
67
|
@metric.set(name: 'cleanup_delete_total', value: @delete_count, type: 'counter')
|
68
68
|
end
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/microservices/microservice'
|
24
|
+
require 'openc3/microservices/interface_decom_common'
|
24
25
|
require 'openc3/topics/telemetry_decom_topic'
|
25
26
|
require 'openc3/topics/limits_event_topic'
|
26
27
|
require 'openc3/topics/notifications_topic'
|
@@ -28,8 +29,15 @@ require 'openc3/models/notification_model'
|
|
28
29
|
|
29
30
|
module OpenC3
|
30
31
|
class DecomMicroservice < Microservice
|
32
|
+
include InterfaceDecomCommon
|
33
|
+
|
31
34
|
def initialize(*args)
|
32
35
|
super(*args)
|
36
|
+
# Should only be one target, but there might be multiple decom microservices for a given target
|
37
|
+
# First Decom microservice has no number in the name
|
38
|
+
if @name =~ /__DECOM__/
|
39
|
+
@topics << "#{scope}__DECOMINTERFACE__{#{@target_names[0]}}"
|
40
|
+
end
|
33
41
|
Topic.update_topic_offsets(@topics)
|
34
42
|
System.telemetry.limits_change_callback = method(:limits_change_callback)
|
35
43
|
LimitsEventTopic.sync_system(scope: @scope)
|
@@ -47,9 +55,16 @@ module OpenC3
|
|
47
55
|
Topic.read_topics(@topics) do |topic, msg_id, msg_hash, redis|
|
48
56
|
break if @cancel_thread
|
49
57
|
|
50
|
-
|
58
|
+
if topic =~ /__DECOMINTERFACE/
|
59
|
+
if msg_hash.key?('inject_tlm')
|
60
|
+
handle_inject_tlm(msg_hash['inject_tlm'])
|
61
|
+
next
|
62
|
+
end
|
63
|
+
else
|
64
|
+
decom_packet(topic, msg_id, msg_hash, redis)
|
65
|
+
@metric.set(name: 'decom_total', value: @count, type: 'counter')
|
66
|
+
end
|
51
67
|
@count += 1
|
52
|
-
@metric.set(name: 'decom_total', value: @count, type: 'counter')
|
53
68
|
end
|
54
69
|
end
|
55
70
|
LimitsEventTopic.sync_system_thread_body(scope: @scope)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2023 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
|
+
require 'openc3/topics/telemetry_topic'
|
20
|
+
require 'openc3/system/system'
|
21
|
+
|
22
|
+
module OpenC3
|
23
|
+
module InterfaceDecomCommon
|
24
|
+
def handle_inject_tlm(inject_tlm_json)
|
25
|
+
inject_tlm_hash = JSON.parse(inject_tlm_json, allow_nan: true, create_additions: true)
|
26
|
+
target_name = inject_tlm_hash['target_name']
|
27
|
+
packet_name = inject_tlm_hash['packet_name']
|
28
|
+
item_hash = inject_tlm_hash['item_hash']
|
29
|
+
type = inject_tlm_hash['type'].to_s.intern
|
30
|
+
packet = System.telemetry.packet(target_name, packet_name)
|
31
|
+
if item_hash
|
32
|
+
item_hash.each do |name, value|
|
33
|
+
packet.write(name.to_s, value, type)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
topic = "#{@scope}__TELEMETRY__{#{target_name}}__#{packet_name}"
|
37
|
+
packet.received_count += 1
|
38
|
+
packet.received_time = Time.now.sys
|
39
|
+
TelemetryTopic.write_packet(packet, scope: @scope)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -14,13 +14,14 @@
|
|
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
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/microservices/microservice'
|
24
|
+
require 'openc3/microservices/interface_decom_common'
|
24
25
|
require 'openc3/models/interface_model'
|
25
26
|
require 'openc3/models/router_model'
|
26
27
|
require 'openc3/models/interface_status_model'
|
@@ -33,6 +34,8 @@ require 'openc3/topics/router_topic'
|
|
33
34
|
|
34
35
|
module OpenC3
|
35
36
|
class InterfaceCmdHandlerThread
|
37
|
+
include InterfaceDecomCommon
|
38
|
+
|
36
39
|
def initialize(interface, tlm, logger: nil, metric: nil, scope:)
|
37
40
|
@interface = interface
|
38
41
|
@tlm = tlm
|
@@ -108,12 +111,12 @@ module OpenC3
|
|
108
111
|
next "Interface not connected: #{@interface.name}"
|
109
112
|
end
|
110
113
|
end
|
111
|
-
if msg_hash.key?('
|
112
|
-
if msg_hash['
|
113
|
-
@logger.info "#{@interface.name}: Enable
|
114
|
+
if msg_hash.key?('log_stream')
|
115
|
+
if msg_hash['log_stream'] == 'true'
|
116
|
+
@logger.info "#{@interface.name}: Enable stream logging"
|
114
117
|
@interface.start_raw_logging
|
115
118
|
else
|
116
|
-
@logger.info "#{@interface.name}: Disable
|
119
|
+
@logger.info "#{@interface.name}: Disable stream logging"
|
117
120
|
@interface.stop_raw_logging
|
118
121
|
end
|
119
122
|
next 'SUCCESS'
|
@@ -122,7 +125,7 @@ module OpenC3
|
|
122
125
|
params = JSON.parse(msg_hash['interface_cmd'], allow_nan: true, create_additions: true)
|
123
126
|
begin
|
124
127
|
@logger.info "#{@interface.name}: interface_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
|
125
|
-
@interface.interface_cmd(params['cmd_name'], params['cmd_params'])
|
128
|
+
@interface.interface_cmd(params['cmd_name'], *params['cmd_params'])
|
126
129
|
rescue => e
|
127
130
|
@logger.error "#{@interface.name}: interface_cmd: #{e.formatted}"
|
128
131
|
next e.message
|
@@ -133,13 +136,17 @@ module OpenC3
|
|
133
136
|
params = JSON.parse(msg_hash['protocol_cmd'], allow_nan: true, create_additions: true)
|
134
137
|
begin
|
135
138
|
@logger.info "#{@interface.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
|
136
|
-
@interface.protocol_cmd(params['cmd_name'], params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
139
|
+
@interface.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
137
140
|
rescue => e
|
138
141
|
@logger.error "#{@interface.name}: protocol_cmd: #{e.formatted}"
|
139
142
|
next e.message
|
140
143
|
end
|
141
144
|
next 'SUCCESS'
|
142
145
|
end
|
146
|
+
if msg_hash.key?('inject_tlm')
|
147
|
+
handle_inject_tlm(msg_hash['inject_tlm'])
|
148
|
+
next 'SUCCESS'
|
149
|
+
end
|
143
150
|
end
|
144
151
|
|
145
152
|
target_name = msg_hash['target_name']
|
@@ -164,7 +171,7 @@ module OpenC3
|
|
164
171
|
if target_name
|
165
172
|
command = System.commands.identify(cmd_buffer, [target_name])
|
166
173
|
else
|
167
|
-
command = System.commands.identify(cmd_buffer, @cmd_target_names)
|
174
|
+
command = System.commands.identify(cmd_buffer, @interface.cmd_target_names)
|
168
175
|
end
|
169
176
|
unless command
|
170
177
|
command = System.commands.packet('UNKNOWN', 'UNKNOWN')
|
@@ -275,12 +282,12 @@ module OpenC3
|
|
275
282
|
@logger.info "#{@router.name}: Disconnect requested"
|
276
283
|
@tlm.disconnect(false)
|
277
284
|
end
|
278
|
-
if msg_hash.key?('
|
279
|
-
if msg_hash['
|
280
|
-
@logger.info "#{@router.name}: Enable
|
285
|
+
if msg_hash.key?('log_stream')
|
286
|
+
if msg_hash['log_stream'] == 'true'
|
287
|
+
@logger.info "#{@router.name}: Enable stream logging"
|
281
288
|
@router.start_raw_logging
|
282
289
|
else
|
283
|
-
@logger.info "#{@router.name}: Disable
|
290
|
+
@logger.info "#{@router.name}: Disable stream logging"
|
284
291
|
@router.stop_raw_logging
|
285
292
|
end
|
286
293
|
end
|
@@ -288,7 +295,7 @@ module OpenC3
|
|
288
295
|
params = JSON.parse(msg_hash['router_cmd'], allow_nan: true, create_additions: true)
|
289
296
|
begin
|
290
297
|
@logger.info "#{@router.name}: router_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
|
291
|
-
@router.interface_cmd(params['cmd_name'], params['cmd_params'])
|
298
|
+
@router.interface_cmd(params['cmd_name'], *params['cmd_params'])
|
292
299
|
rescue => e
|
293
300
|
@logger.error "#{@router.name}: router_cmd: #{e.formatted}"
|
294
301
|
next e.message
|
@@ -299,7 +306,7 @@ module OpenC3
|
|
299
306
|
params = JSON.parse(msg_hash['protocol_cmd'], allow_nan: true, create_additions: true)
|
300
307
|
begin
|
301
308
|
@logger.info "#{@router.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
|
302
|
-
@router.protocol_cmd(params['cmd_name'], params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
309
|
+
@router.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
303
310
|
rescue => e
|
304
311
|
@logger.error "#{@router.name}: protoco_cmd: #{e.formatted}"
|
305
312
|
next e.message
|
@@ -509,7 +516,7 @@ module OpenC3
|
|
509
516
|
|
510
517
|
if packet.stored
|
511
518
|
# Stored telemetry does not update the current value table
|
512
|
-
identified_packet = System.telemetry.identify_and_define_packet(packet, @tlm_target_names)
|
519
|
+
identified_packet = System.telemetry.identify_and_define_packet(packet, @interface.tlm_target_names)
|
513
520
|
else
|
514
521
|
# Identify and update packet
|
515
522
|
if packet.identified?
|
@@ -525,12 +532,12 @@ module OpenC3
|
|
525
532
|
packet.target_name = nil
|
526
533
|
packet.packet_name = nil
|
527
534
|
identified_packet = System.telemetry.identify!(packet.buffer,
|
528
|
-
@tlm_target_names)
|
535
|
+
@interface.tlm_target_names)
|
529
536
|
end
|
530
537
|
else
|
531
538
|
# Packet needs to be identified
|
532
539
|
identified_packet = System.telemetry.identify!(packet.buffer,
|
533
|
-
@tlm_target_names)
|
540
|
+
@interface.tlm_target_names)
|
534
541
|
end
|
535
542
|
end
|
536
543
|
|
@@ -25,17 +25,59 @@ require 'openc3/microservices/interface_microservice'
|
|
25
25
|
module OpenC3
|
26
26
|
class RouterMicroservice < InterfaceMicroservice
|
27
27
|
def handle_packet(packet)
|
28
|
-
@count += 1
|
29
28
|
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
30
29
|
if !packet.identified?
|
31
30
|
# Need to identify so we can find the target
|
32
|
-
identified_packet = System.commands.identify(packet.buffer(false), @cmd_target_names)
|
31
|
+
identified_packet = System.commands.identify(packet.buffer(false), @interface.cmd_target_names)
|
33
32
|
packet = identified_packet if identified_packet
|
34
33
|
end
|
35
34
|
|
35
|
+
unless packet.defined?
|
36
|
+
if packet.target_name and packet.packet_name
|
37
|
+
begin
|
38
|
+
defined_packet = System.commands.packet(packet.target_name, packet.packet_name)
|
39
|
+
defined_packet.received_time = packet.received_time
|
40
|
+
defined_packet.stored = packet.stored
|
41
|
+
defined_packet.buffer = packet.buffer
|
42
|
+
packet = defined_packet
|
43
|
+
rescue => err
|
44
|
+
@logger.warn "Error defining packet of #{packet.length} bytes"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
target_name = packet.target_name
|
50
|
+
target_name = 'UNKNOWN' unless target_name
|
51
|
+
target = System.targets[target_name]
|
52
|
+
|
36
53
|
begin
|
37
|
-
|
38
|
-
|
54
|
+
begin
|
55
|
+
log_message = true # Default is true
|
56
|
+
# If the packet has the DISABLE_MESSAGES keyword then no messages by default
|
57
|
+
log_message = false if packet.messages_disabled
|
58
|
+
# Check if any of the parameters have DISABLE_MESSAGES
|
59
|
+
packet.sorted_items.each do |item|
|
60
|
+
if item.states and item.messages_disabled
|
61
|
+
value = packet.read_item(item)
|
62
|
+
if item.messages_disabled[value]
|
63
|
+
log_message = false
|
64
|
+
break
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if log_message
|
70
|
+
if target and target_name != 'UNKNOWN'
|
71
|
+
@logger.info System.commands.format(packet, target.ignored_parameters)
|
72
|
+
else
|
73
|
+
@logger.warn "Unidentified packet of #{packet.length} bytes being routed to target #{@interface.cmd_target_names[0]}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
rescue => err
|
77
|
+
@logger.error "Problem formatting command from router:\n#{err.formatted}"
|
78
|
+
end
|
79
|
+
|
80
|
+
RouterTopic.route_command(packet, @interface.cmd_target_names, scope: @scope)
|
39
81
|
rescue Exception => err
|
40
82
|
@error = err
|
41
83
|
@logger.error "Error routing command from #{@interface.name}\n#{err.formatted}"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'openc3/utilities/migration'
|
2
|
+
require 'openc3/models/scope_model'
|
3
|
+
|
4
|
+
module OpenC3
|
5
|
+
class LogStream < Migration
|
6
|
+
def self.run
|
7
|
+
ScopeModel.names.each do |scope|
|
8
|
+
# Get all existing InterfaceModels and change json for log_raw to log_stream
|
9
|
+
interface_models = InterfaceModel.all(scope: scope)
|
10
|
+
interface_models.each do |key, model_hash|
|
11
|
+
if model_hash.has_key?('log_raw')
|
12
|
+
if model_hash['log_raw']
|
13
|
+
model_hash['log_stream'] = []
|
14
|
+
else
|
15
|
+
model_hash['log_stream'] = nil
|
16
|
+
end
|
17
|
+
model_hash.delete('log_raw')
|
18
|
+
InterfaceModel.from_json(model_hash, scope: scope).update
|
19
|
+
end
|
20
|
+
end
|
21
|
+
router_models = RouterModel.all(scope: scope)
|
22
|
+
router_models.each do |key, model_hash|
|
23
|
+
if model_hash.has_key?('log_raw')
|
24
|
+
if model_hash['log_raw']
|
25
|
+
model_hash['log_stream'] = []
|
26
|
+
else
|
27
|
+
model_hash['log_stream'] = nil
|
28
|
+
end
|
29
|
+
model_hash.delete('log_raw')
|
30
|
+
RouterModel.from_json(model_hash, scope: scope).update
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
unless ENV['OPENC3_NO_MIGRATE']
|
39
|
+
OpenC3::LogStream.run
|
40
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'openc3/utilities/migration'
|
2
|
+
require 'openc3/models/scope_model'
|
3
|
+
|
4
|
+
module OpenC3
|
5
|
+
class RemoveLog < Migration
|
6
|
+
def self.run
|
7
|
+
ScopeModel.names.each do |scope|
|
8
|
+
# Get all existing InterfaceModels and remove log from json
|
9
|
+
interface_models = InterfaceModel.all(scope: scope)
|
10
|
+
interface_models.each do |key, model_hash|
|
11
|
+
if model_hash.has_key?('log')
|
12
|
+
model_hash.delete('log')
|
13
|
+
InterfaceModel.from_json(model_hash, scope: scope).update
|
14
|
+
end
|
15
|
+
end
|
16
|
+
router_models = RouterModel.all(scope: scope)
|
17
|
+
router_models.each do |key, model_hash|
|
18
|
+
if model_hash.has_key?('log')
|
19
|
+
model_hash.delete('log')
|
20
|
+
RouterModel.from_json(model_hash, scope: scope).update
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
unless ENV['OPENC3_NO_MIGRATE']
|
29
|
+
OpenC3::RemoveLog.run
|
30
|
+
end
|