openc3 5.5.2 → 5.6.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/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
|