openc3 5.12.0 → 5.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/bin/openc3cli +3 -3
- data/data/config/graph_settings.yaml +1 -1
- data/data/config/item_modifiers.yaml +1 -2
- data/data/config/parameter_modifiers.yaml +13 -14
- data/data/config/screen.yaml +1 -2
- data/data/config/target_config.yaml +2 -6
- data/lib/openc3/api/cmd_api.rb +99 -35
- data/lib/openc3/api/tlm_api.rb +63 -24
- data/lib/openc3/interfaces/mqtt_interface.rb +11 -9
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +78 -0
- data/lib/openc3/logs/packet_log_reader.rb +2 -2
- data/lib/openc3/logs/text_log_writer.rb +3 -2
- data/lib/openc3/microservices/trigger_group_microservice.rb +2 -1
- data/lib/openc3/models/plugin_model.rb +38 -4
- data/lib/openc3/packets/json_packet.rb +46 -15
- data/lib/openc3/packets/packet_config.rb +2 -1
- data/lib/openc3/packets/parsers/xtce_parser.rb +5 -1
- data/lib/openc3/script/api_shared.rb +31 -31
- data/lib/openc3/script/commands.rb +18 -12
- data/lib/openc3/script/limits.rb +1 -1
- data/lib/openc3/script/storage.rb +4 -4
- data/lib/openc3/script/web_socket_api.rb +2 -2
- data/lib/openc3/streams/mqtt_stream.rb +109 -0
- data/lib/openc3/utilities/cli_generator.rb +33 -20
- data/lib/openc3/utilities/local_mode.rb +2 -2
- data/lib/openc3/utilities/logger.rb +17 -16
- data/lib/openc3/utilities/process_manager.rb +1 -1
- data/lib/openc3/version.rb +5 -5
- data/templates/conversion/conversion.py +28 -0
- data/templates/conversion/conversion.rb +1 -18
- data/templates/limits_response/response.py +37 -0
- data/templates/limits_response/response.rb +0 -17
- data/templates/microservice/microservices/TEMPLATE/microservice.py +54 -0
- data/templates/microservice/microservices/TEMPLATE/microservice.rb +0 -7
- data/templates/plugin/.gitignore +1 -0
- data/templates/target/targets/TARGET/lib/target.py +9 -0
- data/templates/target/targets/TARGET/procedures/procedure.py +3 -0
- data/templates/tool_angular/package.json +20 -19
- data/templates/tool_angular/yarn.lock +2222 -3212
- data/templates/tool_react/package.json +12 -12
- data/templates/tool_react/yarn.lock +586 -521
- data/templates/tool_svelte/package.json +11 -10
- data/templates/tool_svelte/src/services/openc3-api.js +17 -22
- data/templates/tool_svelte/yarn.lock +600 -516
- data/templates/tool_vue/package.json +10 -9
- data/templates/tool_vue/yarn.lock +113 -41
- data/templates/widget/package.json +9 -8
- data/templates/widget/yarn.lock +96 -35
- metadata +26 -4
@@ -217,14 +217,14 @@ module OpenC3
|
|
217
217
|
|
218
218
|
# Log Messages WebSocket
|
219
219
|
class MessagesWebSocketApi < CmdTlmWebSocketApi
|
220
|
-
def initialize(history_count: 0, start_time: nil, end_time: nil,
|
220
|
+
def initialize(history_count: 0, start_time: nil, end_time: nil, level: nil, types: nil, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
|
221
221
|
@identifier = {
|
222
222
|
channel: "MessagesChannel",
|
223
223
|
history_count: history_count
|
224
224
|
}
|
225
225
|
@identifier['start_time'] = start_time if start_time
|
226
226
|
@identifier['end_time'] = end_time if end_time
|
227
|
-
@identifier['
|
227
|
+
@identifier['level'] = level if level
|
228
228
|
@identifier['types'] = types if types
|
229
229
|
super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
|
230
230
|
end
|
@@ -0,0 +1,109 @@
|
|
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/interfaces/mqtt_interface' # For MQTT patches
|
20
|
+
require 'openc3/streams/stream'
|
21
|
+
require 'openc3/config/config_parser'
|
22
|
+
|
23
|
+
module OpenC3
|
24
|
+
class MqttStream < Stream
|
25
|
+
attr_reader :hostname
|
26
|
+
attr_reader :port
|
27
|
+
attr_reader :ssl
|
28
|
+
attr_reader :write_topic
|
29
|
+
attr_reader :read_topic
|
30
|
+
attr_accessor :username
|
31
|
+
attr_accessor :password
|
32
|
+
attr_accessor :cert
|
33
|
+
attr_accessor :key
|
34
|
+
attr_accessor :ca_file
|
35
|
+
|
36
|
+
def initialize(hostname, port = 1883, ssl = false, write_topic = nil, read_topic = nil)
|
37
|
+
super()
|
38
|
+
|
39
|
+
@hostname = hostname
|
40
|
+
@port = Integer(port)
|
41
|
+
@ssl = ConfigParser.handle_true_false(ssl)
|
42
|
+
@write_topic = ConfigParser.handle_nil(write_topic)
|
43
|
+
@read_topic = ConfigParser.handle_nil(read_topic)
|
44
|
+
@connected = false
|
45
|
+
|
46
|
+
@username = nil
|
47
|
+
@password = nil
|
48
|
+
@cert = nil
|
49
|
+
@key = nil
|
50
|
+
@ca_file = nil
|
51
|
+
|
52
|
+
# Mutex on write is needed to protect from commands coming in from more
|
53
|
+
# than one tool
|
54
|
+
@write_mutex = Mutex.new
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [String] Returns a binary string of data from the read_topic
|
58
|
+
def read
|
59
|
+
raise "Attempt to read from write only stream" unless @read_topic
|
60
|
+
|
61
|
+
# No read mutex is needed because reads happen serially
|
62
|
+
_, data = @client.get
|
63
|
+
if data.nil? or data.length <= 0
|
64
|
+
Logger.info "MqttStream: read returned nil" if data.nil?
|
65
|
+
Logger.info "MqttStream: read returned 0 bytes" if not data.nil? and data.length <= 0
|
66
|
+
return nil
|
67
|
+
end
|
68
|
+
|
69
|
+
return data
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param data [String] A binary string of data to write to the write_topic
|
73
|
+
def write(data)
|
74
|
+
raise "Attempt to write to read only stream" unless @write_topic
|
75
|
+
|
76
|
+
@write_mutex.synchronize do
|
77
|
+
@client.publish(@write_topic, data)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Connect the stream
|
82
|
+
def connect
|
83
|
+
@client = MQTT::Client.new
|
84
|
+
@client.host = @hostname
|
85
|
+
@client.port = @port
|
86
|
+
@client.ssl = @ssl
|
87
|
+
@client.username = @username if @username
|
88
|
+
@client.password = @password if @password
|
89
|
+
@client.cert = @cert if @cert
|
90
|
+
@client.key = @key if @key
|
91
|
+
@client.ca_file = @ca_file.path if @ca_file
|
92
|
+
@client.connect
|
93
|
+
@client.subscribe(@read_topic) if @read_topic
|
94
|
+
@connected = true
|
95
|
+
end
|
96
|
+
|
97
|
+
def connected?
|
98
|
+
@connected
|
99
|
+
end
|
100
|
+
|
101
|
+
def disconnect
|
102
|
+
if @connected
|
103
|
+
@client.disconnect
|
104
|
+
@client = nil
|
105
|
+
@connected = false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -40,20 +40,33 @@ module OpenC3
|
|
40
40
|
if args[0] != 'plugin' and Dir.glob("*.gemspec").empty?
|
41
41
|
abort("No gemspec file detected. #{args[0].to_s.downcase} generator should be run within an existing plugin.")
|
42
42
|
end
|
43
|
+
|
44
|
+
if args[-1] == '--python'
|
45
|
+
@@language = 'py'
|
46
|
+
else
|
47
|
+
@@language = 'rb'
|
48
|
+
end
|
43
49
|
end
|
44
50
|
|
45
51
|
def self.process_template(template_dir, the_binding)
|
46
52
|
Dir.glob("#{template_dir}/**/*", File::FNM_DOTMATCH).each do |file|
|
47
53
|
next if File.basename(file) == '.'
|
54
|
+
if @@language == 'rb'
|
55
|
+
# Ignore python files if we're ruby
|
56
|
+
next if File.extname(file) == '.py'
|
57
|
+
elsif @@language == 'py'
|
58
|
+
# Ignore ruby files if we're python
|
59
|
+
next if File.extname(file) == '.rb'
|
60
|
+
end
|
48
61
|
base_name = file.sub("#{template_dir}/", '')
|
49
62
|
next if yield base_name
|
50
63
|
if File.directory?(file)
|
51
|
-
FileUtils.
|
64
|
+
FileUtils.mkdir_p(base_name)
|
52
65
|
next
|
53
66
|
end
|
54
|
-
output = ERB.new(File.read(file)
|
55
|
-
File.open(base_name, 'w') do |
|
56
|
-
|
67
|
+
output = ERB.new(File.read(file), trim_mode: "-").result(the_binding)
|
68
|
+
File.open(base_name, 'w') do |base_file|
|
69
|
+
base_file.write output
|
57
70
|
end
|
58
71
|
end
|
59
72
|
end
|
@@ -82,8 +95,8 @@ module OpenC3
|
|
82
95
|
end
|
83
96
|
|
84
97
|
def self.generate_target(args)
|
85
|
-
if args.length
|
86
|
-
abort("Usage: cli generate #{args[0]} <NAME>")
|
98
|
+
if args.length < 2 or args.length > 3
|
99
|
+
abort("Usage: cli generate #{args[0]} <NAME> (--ruby or --python)")
|
87
100
|
end
|
88
101
|
|
89
102
|
# Create the local variables
|
@@ -92,14 +105,14 @@ module OpenC3
|
|
92
105
|
if File.exist?(target_path)
|
93
106
|
abort("Target #{target_path} already exists!")
|
94
107
|
end
|
95
|
-
target_lib_filename = "#{target_name.downcase}
|
108
|
+
target_lib_filename = "#{target_name.downcase}.#{@@language}"
|
96
109
|
target_class = target_lib_filename.filename_to_class_name
|
97
110
|
target_object = target_name.downcase
|
98
111
|
|
99
112
|
process_template("#{TEMPLATES_DIR}/target", binding) do |filename|
|
100
113
|
# Rename the template TARGET to our actual target named after the plugin
|
101
114
|
filename.sub!("targets/TARGET", "targets/#{target_name}")
|
102
|
-
filename.sub!("target
|
115
|
+
filename.sub!("target.#{@@language}", target_lib_filename)
|
103
116
|
false
|
104
117
|
end
|
105
118
|
|
@@ -120,8 +133,8 @@ module OpenC3
|
|
120
133
|
end
|
121
134
|
|
122
135
|
def self.generate_microservice(args)
|
123
|
-
if args.length
|
124
|
-
abort("Usage: cli generate #{args[0]} <NAME>")
|
136
|
+
if args.length < 2 or args.length > 3
|
137
|
+
abort("Usage: cli generate #{args[0]} <NAME> (--ruby or --python)")
|
125
138
|
end
|
126
139
|
|
127
140
|
# Create the local variables
|
@@ -130,13 +143,13 @@ module OpenC3
|
|
130
143
|
if File.exist?(microservice_path)
|
131
144
|
abort("Microservice #{microservice_path} already exists!")
|
132
145
|
end
|
133
|
-
microservice_filename = "#{microservice_name.downcase}
|
146
|
+
microservice_filename = "#{microservice_name.downcase}.#{@@language}"
|
134
147
|
microservice_class = microservice_filename.filename_to_class_name
|
135
148
|
|
136
149
|
process_template("#{TEMPLATES_DIR}/microservice", binding) do |filename|
|
137
150
|
# Rename the template MICROSERVICE to our actual microservice name
|
138
151
|
filename.sub!("microservices/TEMPLATE", "microservices/#{microservice_name}")
|
139
|
-
filename.sub!("microservice
|
152
|
+
filename.sub!("microservice.#{@@language}", microservice_filename)
|
140
153
|
false
|
141
154
|
end
|
142
155
|
|
@@ -252,8 +265,8 @@ module OpenC3
|
|
252
265
|
self.singleton_class.send(:alias_method, :generate_tool_svelte, :generate_tool)
|
253
266
|
|
254
267
|
def self.generate_conversion(args)
|
255
|
-
if args.length
|
256
|
-
abort("Usage: cli generate conversion <TARGET> <NAME>")
|
268
|
+
if args.length < 3 or args.length > 4
|
269
|
+
abort("Usage: cli generate conversion <TARGET> <NAME> (--ruby or --python)")
|
257
270
|
end
|
258
271
|
|
259
272
|
# Create the local variables
|
@@ -263,7 +276,7 @@ module OpenC3
|
|
263
276
|
end
|
264
277
|
conversion_name = "#{args[2].upcase.gsub(/_+|-+/, '_')}_CONVERSION"
|
265
278
|
conversion_path = "targets/#{target_name}/lib/"
|
266
|
-
conversion_basename = "#{conversion_name.downcase}
|
279
|
+
conversion_basename = "#{conversion_name.downcase}.#{@@language}"
|
267
280
|
conversion_class = conversion_basename.filename_to_class_name
|
268
281
|
conversion_filename = "targets/#{target_name}/lib/#{conversion_basename}"
|
269
282
|
if File.exist?(conversion_filename)
|
@@ -271,7 +284,7 @@ module OpenC3
|
|
271
284
|
end
|
272
285
|
|
273
286
|
process_template("#{TEMPLATES_DIR}/conversion", binding) do |filename|
|
274
|
-
filename.sub!("conversion
|
287
|
+
filename.sub!("conversion.#{@@language}", conversion_filename)
|
275
288
|
false
|
276
289
|
end
|
277
290
|
|
@@ -282,8 +295,8 @@ module OpenC3
|
|
282
295
|
end
|
283
296
|
|
284
297
|
def self.generate_limits_response(args)
|
285
|
-
if args.length
|
286
|
-
abort("Usage: cli generate limits_response <TARGET> <NAME>")
|
298
|
+
if args.length < 3 or args.length > 4
|
299
|
+
abort("Usage: cli generate limits_response <TARGET> <NAME> (--ruby or --python)")
|
287
300
|
end
|
288
301
|
|
289
302
|
# Create the local variables
|
@@ -293,7 +306,7 @@ module OpenC3
|
|
293
306
|
end
|
294
307
|
response_name = "#{args[2].upcase.gsub(/_+|-+/, '_')}_LIMITS_RESPONSE"
|
295
308
|
response_path = "targets/#{target_name}/lib/"
|
296
|
-
response_basename = "#{response_name.downcase}
|
309
|
+
response_basename = "#{response_name.downcase}.#{@@language}"
|
297
310
|
response_class = response_basename.filename_to_class_name
|
298
311
|
response_filename = "targets/#{target_name}/lib/#{response_basename}"
|
299
312
|
if File.exist?(response_filename)
|
@@ -301,7 +314,7 @@ module OpenC3
|
|
301
314
|
end
|
302
315
|
|
303
316
|
process_template("#{TEMPLATES_DIR}/limits_response", binding) do |filename|
|
304
|
-
filename.sub!("response
|
317
|
+
filename.sub!("response.#{@@language}", response_filename)
|
305
318
|
false
|
306
319
|
end
|
307
320
|
|
@@ -29,9 +29,7 @@ module OpenC3
|
|
29
29
|
# When updating update local_mode.py, PluginsTab.vue, plugins.spec.ts
|
30
30
|
DEFAULT_PLUGINS = [
|
31
31
|
'openc3-cosmos-tool-admin',
|
32
|
-
'openc3-cosmos-tool-autonomic',
|
33
32
|
'openc3-cosmos-tool-bucketexplorer',
|
34
|
-
'openc3-cosmos-tool-calendar',
|
35
33
|
'openc3-cosmos-tool-cmdsender',
|
36
34
|
'openc3-cosmos-tool-cmdtlmserver',
|
37
35
|
'openc3-cosmos-tool-dataextractor',
|
@@ -47,6 +45,8 @@ module OpenC3
|
|
47
45
|
'openc3-cosmos-tool-tlmviewer',
|
48
46
|
'openc3-cosmos-enterprise-tool-admin',
|
49
47
|
'openc3-enterprise-tool-base',
|
48
|
+
'openc3-cosmos-tool-autonomic',
|
49
|
+
'openc3-cosmos-tool-calendar',
|
50
50
|
'openc3-tool-base',
|
51
51
|
]
|
52
52
|
|
@@ -59,11 +59,11 @@ module OpenC3
|
|
59
59
|
# FATAL prints FATAL, ERROR, WARN, INFO, DEBUG messages
|
60
60
|
FATAL = ::Logger::FATAL
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
DEBUG_LEVEL = 'DEBUG'
|
63
|
+
INFO_LEVEL = 'INFO'
|
64
|
+
WARN_LEVEL = 'WARN'
|
65
|
+
ERROR_LEVEL = 'ERROR'
|
66
|
+
FATAL_LEVEL = 'FATAL'
|
67
67
|
|
68
68
|
# Types
|
69
69
|
LOG = 'log'
|
@@ -98,27 +98,27 @@ module OpenC3
|
|
98
98
|
# @param block [Proc] Block to call which should return a string to append
|
99
99
|
# to the log message
|
100
100
|
def debug(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
|
101
|
-
log_message(
|
101
|
+
log_message(DEBUG_LEVEL, message, scope: scope, user: user, type: type, url: url, &block) if @level <= DEBUG
|
102
102
|
end
|
103
103
|
|
104
104
|
# (see #debug)
|
105
105
|
def info(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
|
106
|
-
log_message(
|
106
|
+
log_message(INFO_LEVEL, message, scope: scope, user: user, type: type, url: url, &block) if @level <= INFO
|
107
107
|
end
|
108
108
|
|
109
109
|
# (see #debug)
|
110
110
|
def warn(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
|
111
|
-
log_message(
|
111
|
+
log_message(WARN_LEVEL, message, scope: scope, user: user, type: type, url: url, &block) if @level <= WARN
|
112
112
|
end
|
113
113
|
|
114
114
|
# (see #debug)
|
115
115
|
def error(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
|
116
|
-
log_message(
|
116
|
+
log_message(ERROR_LEVEL, message, scope: scope, user: user, type: type, url: url, &block) if @level <= ERROR
|
117
117
|
end
|
118
118
|
|
119
119
|
# (see #debug)
|
120
120
|
def fatal(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
|
121
|
-
log_message(
|
121
|
+
log_message(FATAL_LEVEL, message, scope: scope, user: user, type: type, url: url, &block) if @level <= FATAL
|
122
122
|
end
|
123
123
|
|
124
124
|
# (see #debug)
|
@@ -174,10 +174,11 @@ module OpenC3
|
|
174
174
|
|
175
175
|
protected
|
176
176
|
|
177
|
-
def log_message(
|
177
|
+
def log_message(log_level, message, scope:, user:, type:, url:)
|
178
178
|
@@mutex.synchronize do
|
179
|
-
time = Time.now
|
180
|
-
|
179
|
+
time = Time.now.utc
|
180
|
+
# timestamp iso8601 with 6 decimal places to match the python output format
|
181
|
+
data = { time: time.to_nsec_from_epoch, '@timestamp' => time.iso8601(6), level: log_level }
|
181
182
|
data[:microservice_name] = @microservice_name if @microservice_name
|
182
183
|
data[:detail] = @detail_string if @detail_string
|
183
184
|
data[:user] = user if user # EE: If a user is passed, put its name. Don't include user data if no user was passed.
|
@@ -185,12 +186,12 @@ module OpenC3
|
|
185
186
|
message = yield
|
186
187
|
end
|
187
188
|
data[:container_name] = @container_name
|
188
|
-
data[:
|
189
|
+
data[:message] = message
|
189
190
|
data[:type] = type
|
190
191
|
data[:url] = url if url
|
191
192
|
if @stdout
|
192
|
-
case
|
193
|
-
when
|
193
|
+
case log_level
|
194
|
+
when WARN_LEVEL, ERROR_LEVEL, FATAL_LEVEL
|
194
195
|
if ENV['OPENC3_LOG_STDERR']
|
195
196
|
$stderr.puts data.as_json(:allow_nan => true).to_json(:allow_nan => true)
|
196
197
|
$stderr.flush
|
@@ -96,7 +96,7 @@ module OpenC3
|
|
96
96
|
process.status.output = output
|
97
97
|
if process.exit_code != 0
|
98
98
|
process.status.state = "Crashed"
|
99
|
-
elsif output.include?('"
|
99
|
+
elsif output.include?('"level":"ERROR"') || output.include?('"level":"WARN"')
|
100
100
|
process.status.state = "Warning"
|
101
101
|
else
|
102
102
|
process.status.state = "Complete"
|
data/lib/openc3/version.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
OPENC3_VERSION = '5.
|
3
|
+
OPENC3_VERSION = '5.13.0'
|
4
4
|
module OpenC3
|
5
5
|
module Version
|
6
6
|
MAJOR = '5'
|
7
|
-
MINOR = '
|
7
|
+
MINOR = '13'
|
8
8
|
PATCH = '0'
|
9
9
|
OTHER = ''
|
10
|
-
BUILD = '
|
10
|
+
BUILD = 'b4c2afb3edf2a5786422538ddef91f00d173855d'
|
11
11
|
end
|
12
|
-
VERSION = '5.
|
13
|
-
GEM_VERSION = '5.
|
12
|
+
VERSION = '5.13.0'
|
13
|
+
GEM_VERSION = '5.13.0'
|
14
14
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from openc3.conversions.conversion import Conversion
|
2
|
+
|
3
|
+
# Custom conversion class
|
4
|
+
# See https://openc3.com/docs/v5/telemetry#read_conversion
|
5
|
+
class <%= conversion_class %>(Conversion):
|
6
|
+
def __init__(self):
|
7
|
+
super().__init__()
|
8
|
+
# Should be one of 'INT', 'UINT', 'FLOAT', 'STRING', 'BLOCK'
|
9
|
+
self.converted_type = 'STRING'
|
10
|
+
# Size of the converted type in bits
|
11
|
+
# Use 0 for 'STRING' or 'BLOCK' where the size can be variable
|
12
|
+
self.converted_bit_size = 0
|
13
|
+
|
14
|
+
# @param value [Object] Value based on the item definition. This could be
|
15
|
+
# a string, integer, float, or array of values.
|
16
|
+
# @param packet [Packet] The packet object where the conversion is defined
|
17
|
+
# @param buffer [String] The raw packet buffer
|
18
|
+
def call(self, value, packet, buffer):
|
19
|
+
# Read values from the packet and do a conversion
|
20
|
+
# Used for DERIVED items that don't have a value
|
21
|
+
# item1 = packet.read("ITEM1") # returns CONVERTED value (default)
|
22
|
+
# item2 = packet.read("ITEM2", 'RAW') # returns RAW value
|
23
|
+
# return (item1 + item2) / 2
|
24
|
+
#
|
25
|
+
# Perform conversion logic directly on value
|
26
|
+
# Used when conversion is applied to a regular (not DERIVED) item
|
27
|
+
# NOTE: You can also use packet.read("ITEM") to get additional values
|
28
|
+
# return value / 2 * packet.read("OTHER_ITEM")
|
@@ -1,21 +1,4 @@
|
|
1
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
2
|
require 'openc3/conversions/conversion'
|
20
3
|
|
21
4
|
module OpenC3
|
@@ -37,7 +20,7 @@ module OpenC3
|
|
37
20
|
# @param buffer [String] The raw packet buffer
|
38
21
|
def call(value, packet, buffer)
|
39
22
|
# Read values from the packet and do a conversion
|
40
|
-
# Used for
|
23
|
+
# Used for DERIVED items that don't have a value
|
41
24
|
# item1 = packet.read("ITEM1") # returns CONVERTED value (default)
|
42
25
|
# item2 = packet.read("ITEM2", :RAW) # returns RAW value
|
43
26
|
# return (item1 + item2) / 2
|
@@ -0,0 +1,37 @@
|
|
1
|
+
from openc3.packets.limits_response import LimitsResponse
|
2
|
+
|
3
|
+
|
4
|
+
class <%= response_class %>(LimitsResponse):
|
5
|
+
# @param packet [Packet] Packet the limits response is assigned to
|
6
|
+
# @param item [PacketItem] PacketItem the limits response is assigned to
|
7
|
+
# @param old_limits_state [Symbol] Previous value of the limit. One of nil,
|
8
|
+
# "GREEN_HIGH", "GREEN_LOW", "YELLOW", "YELLOW_HIGH", "YELLOW_LOW",
|
9
|
+
# "RED", "RED_HIGH", "RED_LOW". nil if the previous limit state has not yet
|
10
|
+
# been established.
|
11
|
+
def call(self, packet, item, old_limits_state):
|
12
|
+
# Take action based on the current limits state
|
13
|
+
# Delete any of the case lines that do not apply or you don't care about
|
14
|
+
match item.limits.state:
|
15
|
+
case "RED_HIGH":
|
16
|
+
# Take action like sending a command:
|
17
|
+
# cmd("TARGET SAFE")
|
18
|
+
pass
|
19
|
+
case "RED_LOW":
|
20
|
+
pass
|
21
|
+
case "YELLOW_LOW":
|
22
|
+
pass
|
23
|
+
case "YELLOW_HIGH":
|
24
|
+
pass
|
25
|
+
# GREEN limits are only available if a telemetry item has them defined
|
26
|
+
# COSMOS refers to these as "operational limits"
|
27
|
+
# See https://openc3.com/docs/v5/telemetry#limits
|
28
|
+
case "GREEN_LOW":
|
29
|
+
pass
|
30
|
+
case "GREEN_HIGH":
|
31
|
+
pass
|
32
|
+
# :RED and :YELLOW limits are triggered for STATES with defined RED and YELLOW states
|
33
|
+
# See https://openc3.com/docs/v5/telemetry#state
|
34
|
+
case "RED":
|
35
|
+
pass
|
36
|
+
case "YELLOW":
|
37
|
+
pass
|
@@ -1,21 +1,4 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
# Copyright 2022 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
2
|
require 'openc3/packets/limits_response'
|
20
3
|
|
21
4
|
module OpenC3
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import time
|
2
|
+
from openc3.microservices.microservice import Microservice
|
3
|
+
from openc3.utilities.sleeper import Sleeper
|
4
|
+
from openc3.api import *
|
5
|
+
|
6
|
+
|
7
|
+
class <%= microservice_class %>(Microservice):
|
8
|
+
def __init__(self, name):
|
9
|
+
super().__init__(name)
|
10
|
+
for option in self.config['options']:
|
11
|
+
# Update with your own OPTION handling
|
12
|
+
match option[0].upper():
|
13
|
+
case 'PERIOD':
|
14
|
+
self.period = int(option[1])
|
15
|
+
case _:
|
16
|
+
self.logger.error(
|
17
|
+
"Unknown option passed to microservice #{@name}: #{option}"
|
18
|
+
)
|
19
|
+
|
20
|
+
if not self.period:
|
21
|
+
self.period = 60 # 1 minutes
|
22
|
+
self.sleeper = Sleeper()
|
23
|
+
|
24
|
+
def run(self):
|
25
|
+
while True:
|
26
|
+
start_time = time.time()
|
27
|
+
if self.cancel_thread:
|
28
|
+
break
|
29
|
+
|
30
|
+
# Do your microservice work here
|
31
|
+
self.logger.info("Template Microservice ran")
|
32
|
+
# cmd("INST ABORT")
|
33
|
+
|
34
|
+
# The self.state variable is set to 'RUNNING' by the microservice base class
|
35
|
+
# The self.state is reflected to the user in the MICROSERVICES tab so you can
|
36
|
+
# convey long running actions by changing it, e.g. self.state = 'CALCULATING ...'
|
37
|
+
|
38
|
+
run_time = time.time() - start_time
|
39
|
+
delta = self.period - run_time
|
40
|
+
if delta > 0:
|
41
|
+
# Delay till the next period
|
42
|
+
if self.sleeper.sleep(
|
43
|
+
delta
|
44
|
+
): # returns true and breaks loop on shutdown
|
45
|
+
break
|
46
|
+
self.count += 1
|
47
|
+
|
48
|
+
def shutdown(self):
|
49
|
+
self.sleeper.cancel() # Breaks out of run()
|
50
|
+
super().shutdown()
|
51
|
+
|
52
|
+
|
53
|
+
if __name__ == "__main__":
|
54
|
+
<%= microservice_class %>.run()
|
@@ -1,11 +1,4 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
# Copyright 2023 OpenC3, Inc.
|
4
|
-
# All Rights Reserved.
|
5
|
-
#
|
6
|
-
# This file may also be used under the terms of a commercial license
|
7
|
-
# if purchased from OpenC3, Inc.
|
8
|
-
|
9
2
|
require 'openc3/microservices/microservice'
|
10
3
|
require 'openc3/api/api'
|
11
4
|
|
@@ -0,0 +1 @@
|
|
1
|
+
node_modules
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# This class can be used in your scripts like so:
|
2
|
+
# require_utility '<%= target_class.upcase %>/lib/<%= target_lib_filename %>'
|
3
|
+
# <%= target_object %> = <%= target_class %>()
|
4
|
+
# <%= target_object %>.utility()
|
5
|
+
# For more information see the OpenC3 scripting guide
|
6
|
+
|
7
|
+
class <%= target_class %>:
|
8
|
+
def utility():
|
9
|
+
pass
|