openc3 5.15.0 → 5.15.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0228b27d56d6fce2f445eb5842ec223be1351aaf09767da803e735ffb80875ec'
4
- data.tar.gz: 7f78a835eb8d3d1c678afa7f93490821cac67dcbf3d854ec1973c452b139a647
3
+ metadata.gz: a39dab08bb9810376520e75a7bf3a6c63d30ad54b93566b82a849d780693a366
4
+ data.tar.gz: 65d282829dba0706cbe0e32603e51ad8ab3dfc0fdaf37d9bd400787bb7a1cb03
5
5
  SHA512:
6
- metadata.gz: 545775f6dd330af7e6e4f566a07ea44f5f5b2e533d2dadb9704e5e1dba142377f4b63dacc89157b0c4b996e20c78851fba4d397d830619fa51ff0a313850935f
7
- data.tar.gz: 9eb87fbc7b5410327f0142f1e2bf08ae8070169057a34fbef6eb0f7c9bd846c07aae7e49b70d9b8f4ff5647fe1258155eeb879d0ace4cbe782b1e7b5ca2c8019
6
+ metadata.gz: 12bffefe104e90e159c16bcc54ab53745e86a97bfb762c7e0e25141d6bd3c91ad6bb8827017d915dfb459b2fc69ea7365c97e7fa22236abb16ff0d73d8d485d7
7
+ data.tar.gz: b2efa2780f97e2aa3392cc483534d949be4fb27032dbc3e52015ebfa89da08d234e5777c50dbfa09e477357d3b5ca67aba847f8f5d723676d2331da84e880f7f
@@ -1302,7 +1302,7 @@ Interactive Widgets:
1302
1302
 
1303
1303
  Button code can get rather complex so remember to use string concatenation
1304
1304
  to make things more readable. If you use `+` newlines are inserted automatically
1305
- during string concatenation. If you use `\` you'll need to separate lines with a
1305
+ during string concatenation. If you use `\\` you'll need to separate lines with a
1306
1306
  single semicolon `;`. COSMOS uses double semicolon `;;` to indicate lines should
1307
1307
  be evaluated separately. Note that all OpenC3 commands (using api.cmd) must be
1308
1308
  separated by `;;`.
@@ -18,8 +18,16 @@
18
18
 
19
19
  require 'json'
20
20
  require 'jsonpath'
21
+ require 'openc3/io/json_rpc'
21
22
  require 'openc3/accessors/accessor'
22
23
 
24
+ # Monkey patch JsonPath to enable create_additions and allow_nan to support binary strings, and NaN, Infinity, -Infinity
25
+ class JsonPath
26
+ def self.process_object(obj_or_str, opts = {})
27
+ obj_or_str.is_a?(String) ? MultiJson.decode(obj_or_str, max_nesting: opts[:max_nesting], create_additions: true, allow_nan: true) : obj_or_str
28
+ end
29
+ end
30
+
23
31
  module OpenC3
24
32
  class JsonAccessor < Accessor
25
33
  def self.read_item(item, buffer)
@@ -33,7 +41,7 @@ module OpenC3
33
41
 
34
42
  # Convert to ruby objects
35
43
  if String === buffer
36
- decoded = JSON.parse(buffer, :allow_nan => true)
44
+ decoded = JSON.parse(buffer, :allow_nan => true, :create_additions => true)
37
45
  else
38
46
  decoded = buffer
39
47
  end
@@ -43,7 +51,7 @@ module OpenC3
43
51
 
44
52
  # Update buffer
45
53
  if String === buffer
46
- buffer.replace(JSON.generate(decoded, :allow_nan => true))
54
+ buffer.replace(JSON.generate(decoded.as_json, :allow_nan => true))
47
55
  end
48
56
 
49
57
  return value
@@ -52,7 +60,7 @@ module OpenC3
52
60
  def self.read_items(items, buffer)
53
61
  # Prevent JsonPath from decoding every call
54
62
  if String === buffer
55
- decoded = JSON.parse(buffer, :allow_nan => true)
63
+ decoded = JSON.parse(buffer, :allow_nan => true, :create_additions => true)
56
64
  else
57
65
  decoded = buffer
58
66
  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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -41,6 +41,8 @@ module OpenC3
41
41
  'cmd_raw_no_checks',
42
42
  'build_cmd',
43
43
  'build_command', # DEPRECATED
44
+ 'enable_cmd',
45
+ 'disable_cmd',
44
46
  'send_raw',
45
47
  'get_all_cmds',
46
48
  'get_all_commands', # DEPRECATED
@@ -131,6 +133,30 @@ module OpenC3
131
133
  # build_command is DEPRECATED
132
134
  alias build_command build_cmd
133
135
 
136
+ # Helper method for disable_cmd / enable_cmd
137
+ def _get_and_set_cmd(method, *args, scope: $openc3_scope, token: $openc3_token)
138
+ target_name, command_name = _extract_target_command_names(method, *args)
139
+ authorize(permission: 'admin', target_name: target_name, packet_name: command_name, scope: scope, token: token)
140
+ command = yield TargetModel.packet(target_name, command_name, type: :CMD, scope: scope)
141
+ TargetModel.set_packet(target_name, command_name, command, type: :CMD, scope: scope)
142
+ end
143
+
144
+ # @since 5.15.1
145
+ def enable_cmd(*args, scope: $openc3_scope, token: $openc3_token)
146
+ _get_and_set_cmd('enable_cmd', *args, scope: scope, token: token) do |command|
147
+ command['disabled'] = false
148
+ command
149
+ end
150
+ end
151
+
152
+ # @since 5.15.1
153
+ def disable_cmd(*args, scope: $openc3_scope, token: $openc3_token)
154
+ _get_and_set_cmd('disable_cmd', *args, scope: scope, token: token) do |command|
155
+ command['disabled'] = true
156
+ command
157
+ end
158
+ end
159
+
134
160
  # Send a raw binary string to the specified interface.
135
161
  #
136
162
  # @param interface_name [String] The interface to send the raw binary
@@ -456,6 +482,12 @@ module OpenC3
456
482
  cmd_params = cmd_params.transform_keys(&:upcase)
457
483
  authorize(permission: 'cmd', target_name: target_name, packet_name: cmd_name, scope: scope, token: token)
458
484
  packet = TargetModel.packet(target_name, cmd_name, type: :CMD, scope: scope)
485
+ if packet['disabled']
486
+ error = DisabledError.new
487
+ error.target_name = target_name
488
+ error.cmd_name = cmd_name
489
+ raise error
490
+ end
459
491
 
460
492
  command = {
461
493
  'target_name' => target_name,
@@ -14,10 +14,10 @@
14
14
  # GNU Affero General Public License for more details.
15
15
 
16
16
  # Modified by OpenC3, Inc.
17
- # All changes Copyright 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, 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 'fcntl'
@@ -82,12 +82,17 @@ module OpenC3
82
82
  tio.ospeed = baud_rate
83
83
  @handle.tcflush(Termios::TCIOFLUSH)
84
84
  @handle.tcsetattr(Termios::TCSANOW, tio)
85
+
86
+ @pipe_reader, @pipe_writer = IO.pipe
87
+ @readers = [@handle, @pipe_reader]
85
88
  end
86
89
 
87
90
  # (see SerialDriver#close)
88
91
  def close
89
92
  if @handle
90
93
  # Close the serial Port
94
+ @pipe_writer.write('.')
95
+ @pipe_writer.close
91
96
  @handle.close
92
97
  @handle = nil
93
98
  end
@@ -132,9 +137,19 @@ module OpenC3
132
137
  begin
133
138
  data = @handle.read_nonblock(65535)
134
139
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK
135
- result = IO.fast_select([@handle], nil, nil, @read_timeout)
136
- if result
137
- retry
140
+ begin
141
+ read_ready, _ = IO.fast_select(@readers, nil, nil, @read_timeout)
142
+ rescue IOError
143
+ @pipe_reader.close unless @pipe_reader.closed?
144
+ return ""
145
+ end
146
+ if read_ready
147
+ if read_ready.include?(@pipe_reader)
148
+ @pipe_reader.close unless @pipe_reader.closed?
149
+ return ""
150
+ else
151
+ retry
152
+ end
138
153
  else
139
154
  raise Timeout::Error, "Read Timeout"
140
155
  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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -96,9 +96,9 @@ module OpenC3
96
96
  @max_read_size = @file.size
97
97
  @max_read_size = MAX_READ_SIZE if @max_read_size > MAX_READ_SIZE
98
98
  return read_file_header()
99
- rescue => err
99
+ rescue => e
100
100
  close()
101
- raise err
101
+ raise e
102
102
  end
103
103
 
104
104
  # Closes the current log file
@@ -134,9 +134,8 @@ module OpenC3
134
134
 
135
135
  if flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_JSON_PACKET_ENTRY_TYPE_MASK
136
136
  packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
137
- next_offset = 12
138
137
  received_time_nsec_since_epoch, extra, json_data = handle_received_time_extra_and_data(entry, time_nsec_since_epoch, includes_received_time, includes_extra, cbor)
139
- lookup_cmd_or_tlm, target_name, packet_name, id, key_map = @packets[packet_index]
138
+ lookup_cmd_or_tlm, target_name, packet_name, _id, key_map = @packets[packet_index]
140
139
  if cmd_or_tlm != lookup_cmd_or_tlm
141
140
  raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
142
141
  end
@@ -148,8 +147,8 @@ module OpenC3
148
147
  end
149
148
  elsif flags & OPENC3_ENTRY_TYPE_MASK == OPENC3_RAW_PACKET_ENTRY_TYPE_MASK
150
149
  packet_index, time_nsec_since_epoch = entry[2..11].unpack('nQ>')
151
- received_time_nsec_since_epoch, extra, packet_data = handle_received_time_extra_and_data(entry, time_nsec_since_epoch, includes_received_time, includes_extra, cbor)
152
- lookup_cmd_or_tlm, target_name, packet_name, id = @packets[packet_index]
150
+ received_time_nsec_since_epoch, _extra, packet_data = handle_received_time_extra_and_data(entry, time_nsec_since_epoch, includes_received_time, includes_extra, cbor)
151
+ lookup_cmd_or_tlm, target_name, packet_name, _id = @packets[packet_index]
153
152
  if cmd_or_tlm != lookup_cmd_or_tlm
154
153
  raise "Packet type mismatch, packet:#{cmd_or_tlm}, lookup:#{lookup_cmd_or_tlm}"
155
154
  end
@@ -220,9 +219,9 @@ module OpenC3
220
219
  else
221
220
  raise "Invalid Entry Flags: #{flags}"
222
221
  end
223
- rescue => err
222
+ rescue => e
224
223
  close()
225
- raise err
224
+ raise e
226
225
  end
227
226
 
228
227
  # @return [Integer] The size of the log file being processed
@@ -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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -418,7 +418,7 @@ module OpenC3
418
418
  when 'OR'
419
419
  return left || right ? 1 : 0
420
420
  end
421
- rescue ArgumentError => error
421
+ rescue ArgumentError
422
422
  message = "invalid evaluate: (#{left} #{operator} #{right})"
423
423
  notify(name: name, severity: 'error', message: message)
424
424
  return -1
@@ -447,7 +447,7 @@ module OpenC3
447
447
  if visited["#{head.name}__P"][trigger.name]
448
448
  # Not sure if this is posible as on create it validates that the dependents are already created
449
449
  message = "loop detected from #{head.name} -> #{trigger.name} path: #{visited["#{head.name}__P"]}"
450
- notify(name: trigger.name, severity: 'error', message: error.message)
450
+ notify(name: trigger.name, severity: 'error', message: message)
451
451
  return visited["#{trigger.name}__R"] = -1
452
452
  end
453
453
  trigger.roots.each do | root_trigger_name |
@@ -455,7 +455,7 @@ module OpenC3
455
455
  root_trigger = triggers[root_trigger_name]
456
456
  if head.name == root_trigger.name
457
457
  message = "loop detected from #{head.name} -> #{root_trigger_name} path: #{visited["#{head.name}__P"]}"
458
- notify(name: trigger.name, severity: 'error', message: error.message)
458
+ notify(name: trigger.name, severity: 'error', message: message)
459
459
  return visited["#{trigger.name}__R"] = -1
460
460
  end
461
461
  result = evaluate_trigger(
@@ -474,9 +474,9 @@ module OpenC3
474
474
  else
475
475
  right = operand_value(operand: trigger.right, other: trigger.left, visited: visited)
476
476
  end
477
- rescue => error
477
+ rescue => e
478
478
  # This will primarily happen when the user inputs a bad Regexp
479
- notify(name: trigger.name, severity: 'error', message: error.message)
479
+ notify(name: trigger.name, severity: 'error', message: e.message)
480
480
  return visited["#{trigger.name}__R"] = -1
481
481
  end
482
482
  # Convert the standard '==' and '!=' into Ruby Regexp operators
@@ -560,7 +560,7 @@ module OpenC3
560
560
  while @read_topic
561
561
  begin
562
562
  Topic.read_topics(@topics) do |topic, _msg_id, msg_hash, _redis|
563
- @logger.debug "TriggerGroupManager block_for_updates: #{topic} #{msg_hash.to_s}"
563
+ @logger.debug "TriggerGroupManager block_for_updates: #{topic} #{msg_hash}"
564
564
  if topic != @share.trigger_base.autonomic_topic
565
565
  packet = JsonPacket.new(:TLM, msg_hash['target_name'], msg_hash['packet_name'], msg_hash['time'].to_i, false, msg_hash["json_data"])
566
566
  @share.packet_base.add(topic: topic, packet: packet)
@@ -580,7 +580,7 @@ module OpenC3
580
580
  def shutdown
581
581
  @read_topic = false
582
582
  @cancel_thread = true
583
- @worker_count.times do | i |
583
+ @worker_count.times do | _i |
584
584
  @queue << nil
585
585
  end
586
586
  end
@@ -635,7 +635,7 @@ module OpenC3
635
635
  begin
636
636
  AutonomicTopic.read_topics(@topics) do |_topic, _msg_id, msg_hash, _redis|
637
637
  break if @cancel_thread
638
- @logger.debug "TriggerGroupMicroservice block_for_updates: #{msg_hash.to_s}"
638
+ @logger.debug "TriggerGroupMicroservice block_for_updates: #{msg_hash}"
639
639
  # Process trigger notifications created by TriggerModel notify
640
640
  if msg_hash['type'] == 'trigger'
641
641
  data = JSON.parse(msg_hash['data'], :allow_nan => true, :create_additions => true)
@@ -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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -31,11 +31,11 @@ module OpenC3
31
31
  @@token_cache = nil
32
32
  @@token_cache_time = nil
33
33
 
34
- def self.is_set?(key = PRIMARY_KEY)
34
+ def self.set?(key = PRIMARY_KEY)
35
35
  Store.exists(key) == 1
36
36
  end
37
37
 
38
- def self.verify(token, permission: nil)
38
+ def self.verify(token)
39
39
  return false if token.nil? or token.empty?
40
40
 
41
41
  token_hash = hash(token)
@@ -47,7 +47,7 @@ module OpenC3
47
47
 
48
48
  # Handle a service password - Generally only used by ScriptRunner
49
49
  service_password = ENV['OPENC3_SERVICE_PASSWORD']
50
- return true if service_password and service_password == token and permission != 'admin'
50
+ return true if service_password and service_password == token
51
51
 
52
52
  return false
53
53
  end
@@ -55,15 +55,13 @@ module OpenC3
55
55
  def self.set(token, old_token, key = PRIMARY_KEY)
56
56
  raise "token must not be nil or empty" if token.nil? or token.empty?
57
57
 
58
- if is_set?(key)
58
+ if set?(key)
59
59
  raise "old_token must not be nil or empty" if old_token.nil? or old_token.empty?
60
60
  raise "old_token incorrect" unless verify(old_token)
61
61
  end
62
62
  Store.set(key, hash(token))
63
63
  end
64
64
 
65
- private
66
-
67
65
  def self.hash(token)
68
66
  Digest::SHA2.hexdigest token
69
67
  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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -96,7 +96,7 @@ module OpenC3
96
96
 
97
97
  # Get the command and validate the parameters
98
98
  command = $api_server.get_cmd(target_name, cmd_name, scope: scope)
99
- cmd_params.each do |param_name, param_value|
99
+ cmd_params.each do |param_name, _param_value|
100
100
  param = command['items'].find { |item| item['name'] == param_name }
101
101
  unless param
102
102
  raise "Packet item '#{target_name} #{cmd_name} #{param_name}' does not exist"
@@ -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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, 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,8 +43,8 @@ module OpenC3
43
43
  if response.nil? || response.status != 200
44
44
  raise "Failed to delete #{delete_path}"
45
45
  end
46
- rescue => error
47
- raise "Failed deleting #{path} due to #{error.message}"
46
+ rescue => e
47
+ raise "Failed deleting #{path} due to #{e.message}"
48
48
  end
49
49
  nil
50
50
  end
@@ -84,8 +84,8 @@ module OpenC3
84
84
  end
85
85
  end
86
86
  end
87
- rescue => error
88
- raise "Failed to write #{upload_path} due to #{error.message}"
87
+ rescue => e
88
+ raise "Failed to write #{upload_path} due to #{e.message}"
89
89
  end
90
90
  nil
91
91
  end
@@ -115,19 +115,33 @@ module OpenC3
115
115
  end
116
116
 
117
117
  return _get_storage_file("#{part}/#{path}", scope: scope)
118
- rescue => error
118
+ rescue => e
119
119
  if part == "targets_modified"
120
120
  part = "targets"
121
121
  redo
122
122
  else
123
- raise error
123
+ raise e
124
124
  end
125
125
  end
126
126
  break
127
127
  end
128
128
  end
129
129
 
130
- # download_file(path_or_file) is implemented by running_script to download a file
130
+ def get_download_url(path, scope: $openc3_scope)
131
+ targets = "targets_modified" # First try targets_modified
132
+ response = $api_server.request('get', "/openc3-api/storage/exists/#{scope}/#{targets}/#{path}", query: { bucket: 'OPENC3_CONFIG_BUCKET' }, scope: scope)
133
+ if response.status != 200
134
+ targets = "targets" # Next try targets
135
+ response = $api_server.request('get', "/openc3-api/storage/exists/#{scope}/#{targets}/#{path}", query: { bucket: 'OPENC3_CONFIG_BUCKET' }, scope: scope)
136
+ if response.status != 200
137
+ raise "File not found: #{path} in scope: #{scope}"
138
+ end
139
+ end
140
+ endpoint = "/openc3-api/storage/download/#{scope}/#{targets}/#{path}"
141
+ # external must be true because we're using this URL from the frontend
142
+ result = _get_presigned_request(endpoint, external: true, scope: scope)
143
+ return result['url']
144
+ end
131
145
 
132
146
  # These are helper methods ... should not be used directly
133
147
 
@@ -161,7 +175,8 @@ module OpenC3
161
175
  if $openc3_in_cluster
162
176
  case ENV['OPENC3_CLOUD']
163
177
  when 'local'
164
- URI.parse("http://openc3-minio:9000" + url)
178
+ bucket_url = ENV["OPENC3_BUCKET_URL"] || "http://openc3-minio:9000"
179
+ URI.parse("#{bucket_url}#{url}")
165
180
  when 'aws'
166
181
  URI.parse("https://s3.#{ENV['AWS_REGION']}.amazonaws.com" + url)
167
182
  when 'gcp'
@@ -175,11 +190,11 @@ module OpenC3
175
190
  end
176
191
  end
177
192
 
178
- def _get_presigned_request(endpoint, scope: $openc3_scope)
179
- if $openc3_in_cluster
180
- response = $api_server.request('get', endpoint, query: { bucket: 'OPENC3_CONFIG_BUCKET', internal: true }, scope: scope)
181
- else
193
+ def _get_presigned_request(endpoint, external: nil, scope: $openc3_scope)
194
+ if external or !$openc3_in_cluster
182
195
  response = $api_server.request('get', endpoint, query: { bucket: 'OPENC3_CONFIG_BUCKET' }, scope: scope)
196
+ else
197
+ response = $api_server.request('get', endpoint, query: { bucket: 'OPENC3_CONFIG_BUCKET', internal: true }, scope: scope)
183
198
  end
184
199
  if response.nil? || response.status != 201
185
200
  raise "Failed to get presigned URL for #{endpoint}"
@@ -215,6 +215,16 @@ module OpenC3
215
215
  end
216
216
  end
217
217
 
218
+ # All Scripts WebSocket
219
+ class AllScriptsWebSocketApi < ScriptWebSocketApi
220
+ def initialize(url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
221
+ @identifier = {
222
+ channel: "AllScriptsChannel",
223
+ }
224
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
225
+ end
226
+ end
227
+
218
228
  # Log Messages WebSocket
219
229
  class MessagesWebSocketApi < CmdTlmWebSocketApi
220
230
  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)
@@ -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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -31,7 +31,6 @@ require 'openc3/system/target'
31
31
  require 'openc3/utilities/bucket'
32
32
  require 'openc3/utilities/zip'
33
33
  require 'openc3/topics/limits_event_topic'
34
- require 'thread'
35
34
  require 'fileutils'
36
35
 
37
36
  module OpenC3
@@ -109,7 +108,7 @@ module OpenC3
109
108
  # target.txt must be configured to either use all files in cmd_tlm folder (default)
110
109
  # or have a predetermined empty file like dynamic_tlm.txt
111
110
  bucket_path = "#{scope}/targets_modified/#{target_name}/cmd_tlm"
112
- dirs, files = bucket.list_files(bucket: ENV['OPENC3_CONFIG_BUCKET'], path: bucket_path)
111
+ _, files = bucket.list_files(bucket: ENV['OPENC3_CONFIG_BUCKET'], path: bucket_path)
113
112
  files.each do |file|
114
113
  bucket_key = File.join(bucket_path, file['name'])
115
114
  local_path = "#{base_dir}/targets/#{target_name}/cmd_tlm/#{file['name']}"
@@ -180,8 +179,8 @@ module OpenC3
180
179
  errors = [] # Store all errors processing the cmd_tlm files
181
180
  target.cmd_tlm_files.each do |cmd_tlm_file|
182
181
  @packet_config.process_file(cmd_tlm_file, target.name, target.language)
183
- rescue Exception => error
184
- errors << "Error processing #{cmd_tlm_file}:\n#{error.message}"
182
+ rescue Exception => e
183
+ errors << "Error processing #{cmd_tlm_file}:\n#{e.message}"
185
184
  end
186
185
  unless errors.empty?
187
186
  raise errors.join("\n")
@@ -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 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -22,7 +22,6 @@
22
22
 
23
23
  # This file contains top level functions in the OpenC3 namespace
24
24
 
25
- require 'thread'
26
25
  require 'digest'
27
26
  require 'open3'
28
27
  require 'openc3/core_ext'
@@ -50,6 +49,16 @@ class HazardousError < StandardError
50
49
  end
51
50
  end
52
51
 
52
+ # If a disabled command is sent through the {OpenC3::Api} this error is raised.
53
+ class DisabledError < StandardError
54
+ attr_accessor :target_name
55
+ attr_accessor :cmd_name
56
+
57
+ def to_s
58
+ "#{target_name} #{cmd_name} is Disabled"
59
+ end
60
+ end
61
+
53
62
  # OpenC3 is almost
54
63
  # wholly contained within the OpenC3 module. OpenC3 also extends some of the
55
64
  # core Ruby classes to add additional functionality.
@@ -102,18 +111,18 @@ module OpenC3
102
111
  file.write(OPENC3_MARSHAL_HEADER)
103
112
  file.write(Marshal.dump(obj))
104
113
  end
105
- rescue Exception => exception
114
+ rescue Exception => e
106
115
  begin
107
116
  File.delete(marshal_filename)
108
117
  rescue Exception
109
118
  # Oh well - we tried
110
119
  end
111
- if exception.class == TypeError and exception.message =~ /Thread::Mutex/
112
- original_backtrace = exception.backtrace
113
- exception = exception.exception("Mutex exists in a packet. Note: Packets must not be read during class initializers for Conversions, Limits Responses, etc.: #{exception}")
114
- exception.set_backtrace(original_backtrace)
120
+ if e.class == TypeError and e.message =~ /Thread::Mutex/
121
+ original_backtrace = e.backtrace
122
+ e = e.exception("Mutex exists in a packet. Note: Packets must not be read during class initializers for Conversions, Limits Responses, etc.: #{e}")
123
+ e.set_backtrace(original_backtrace)
115
124
  end
116
- self.handle_fatal_exception(exception)
125
+ self.handle_fatal_exception(e)
117
126
  end
118
127
 
119
128
  # Loads the marshal file back into a Ruby object
@@ -132,9 +141,9 @@ module OpenC3
132
141
  Logger.warn "Marshal load failed with invalid marshal file: #{marshal_filename}"
133
142
  return nil
134
143
  end
135
- rescue Exception => exception
144
+ rescue Exception => e
136
145
  if File.exist?(marshal_filename)
137
- Logger.error "Marshal load failed with exception: #{marshal_filename}\n#{exception.formatted}"
146
+ Logger.error "Marshal load failed with exception: #{marshal_filename}\n#{e.formatted}"
138
147
  else
139
148
  Logger.info "Marshal file does not exist: #{marshal_filename}"
140
149
  end
@@ -145,7 +154,7 @@ module OpenC3
145
154
  rescue Exception
146
155
  # Oh well - we tried
147
156
  end
148
- self.handle_fatal_exception(exception) if File.exist?(marshal_filename)
157
+ self.handle_fatal_exception(e) if File.exist?(marshal_filename)
149
158
  return nil
150
159
  end
151
160
 
@@ -354,7 +363,7 @@ module OpenC3
354
363
  #
355
364
  # @param error [Exception] The exception to handle
356
365
  # @param try_gui [Boolean] Whether to try and create a GUI exception popup
357
- def self.handle_fatal_exception(error, try_gui = true)
366
+ def self.handle_fatal_exception(error, _try_gui = true)
358
367
  unless SystemExit === error or SignalException === error
359
368
  $openc3_fatal_exception = error
360
369
  self.write_exception_file(error)
@@ -380,7 +389,7 @@ module OpenC3
380
389
  #
381
390
  # @param error [Exception] The exception to handle
382
391
  # @param try_gui [Boolean] Whether to try and create a GUI exception popup
383
- def self.handle_critical_exception(error, try_gui = true)
392
+ def self.handle_critical_exception(error, _try_gui = true)
384
393
  Logger.error "Critical Exception! #{error.formatted}"
385
394
  self.write_exception_file(error)
386
395
  end
@@ -397,15 +406,15 @@ module OpenC3
397
406
  retry_count = 0
398
407
  begin
399
408
  yield
400
- rescue => error
409
+ rescue => e
401
410
  Logger.error "#{name} thread unexpectedly died. Retries: #{retry_count} of #{retry_attempts}"
402
- Logger.error error.formatted
411
+ Logger.error e.formatted
403
412
  retry_count += 1
404
413
  if retry_count <= retry_attempts
405
- self.write_exception_file(error)
414
+ self.write_exception_file(e)
406
415
  retry
407
416
  end
408
- handle_fatal_exception(error)
417
+ handle_fatal_exception(e)
409
418
  end
410
419
  end
411
420
  end
@@ -440,15 +449,15 @@ module OpenC3
440
449
  # @param log_error [Boolean] Whether to log an error if we can't require the class
441
450
  def self.require_file(filename, log_error = true)
442
451
  require filename
443
- rescue Exception => err
444
- msg = "Unable to require #{filename} due to #{err.message}. "\
452
+ rescue Exception => e
453
+ msg = "Unable to require #{filename} due to #{e.message}. "\
445
454
  "Ensure #{filename} is in the OpenC3 lib directory."
446
455
  Logger.error msg if log_error
447
456
  raise $!, msg, $!.backtrace
448
457
  end
449
458
 
450
459
  # @param filename [String] Name of the file to open in the web browser
451
- def self.open_in_web_browser(filename)
460
+ def self.open_in_web_browser(_filename)
452
461
  puts "open_in_web_browser is DEPRECATED"
453
462
  end
454
463
 
@@ -456,12 +465,12 @@ module OpenC3
456
465
  # Working directory is global, so this can make other threads wait
457
466
  # Ruby Dir.chdir with block always throws an error if multiple threads
458
467
  # call Dir.chdir
459
- def self.set_working_dir(working_dir, &block)
468
+ def self.set_working_dir(working_dir, &)
460
469
  if $openc3_chdir_mutex.owned?
461
- set_working_dir_internal(working_dir, &block)
470
+ set_working_dir_internal(working_dir, &)
462
471
  else
463
472
  $openc3_chdir_mutex.synchronize do
464
- set_working_dir_internal(working_dir, &block)
473
+ set_working_dir_internal(working_dir, &)
465
474
  end
466
475
  end
467
476
  end
@@ -42,7 +42,7 @@ rescue LoadError
42
42
 
43
43
  if $openc3_authorize
44
44
  raise AuthError.new("Token is required") unless token
45
- unless OpenC3::AuthModel.verify(token, permission: permission)
45
+ unless OpenC3::AuthModel.verify(token)
46
46
  raise AuthError.new("Password is invalid for '#{permission}' permission")
47
47
  end
48
48
  end
@@ -37,13 +37,17 @@ module OpenC3
37
37
  NO_OPTIONS = {}
38
38
 
39
39
  def pipelined
40
- with(NO_OPTIONS) do |redis|
41
- redis.pipelined do |pipeline|
42
- Thread.current[:pipeline] = pipeline
43
- begin
44
- yield
45
- ensure
46
- Thread.current[:pipeline] = nil
40
+ if $openc3_redis_cluster
41
+ yield # TODO: Update keys to support pipelining in cluster
42
+ else
43
+ with(NO_OPTIONS) do |redis|
44
+ redis.pipelined do |pipeline|
45
+ Thread.current[:pipeline] = pipeline
46
+ begin
47
+ yield
48
+ ensure
49
+ Thread.current[:pipeline] = nil
50
+ end
47
51
  end
48
52
  end
49
53
  end
@@ -1,14 +1,14 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- OPENC3_VERSION = '5.15.0'
3
+ OPENC3_VERSION = '5.15.2'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '5'
7
7
  MINOR = '15'
8
- PATCH = '0'
8
+ PATCH = '2'
9
9
  OTHER = ''
10
- BUILD = 'a7dd92ddb0ba4d378da1b611cafc5ad7e89a9223'
10
+ BUILD = '460e13eadf313640ad089597bee233ecdafd2ffa'
11
11
  end
12
- VERSION = '5.15.0'
13
- GEM_VERSION = '5.15.0'
12
+ VERSION = '5.15.2'
13
+ GEM_VERSION = '5.15.2'
14
14
  end
@@ -4,6 +4,8 @@
4
4
  # <%= target_object %>.utility()
5
5
  # For more information see the OpenC3 scripting guide
6
6
 
7
+ from openc3.script import *
8
+
7
9
  class <%= target_class %>:
8
10
  def utility(self):
9
11
  pass
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "5.15.0",
3
+ "version": "5.15.2",
4
4
  "scripts": {
5
5
  "ng": "ng",
6
6
  "start": "ng serve",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "private": true,
14
14
  "dependencies": {
15
- "@openc3/tool-common": "5.15.0",
15
+ "@openc3/tool-common": "5.15.2",
16
16
  "@angular/animations": "^17.0.8",
17
17
  "@angular/cdk": "^17.0.4",
18
18
  "@angular/common": "^17.0.8",
@@ -11,7 +11,7 @@
11
11
  "smui-theme": "smui-theme compile build/smui.css -i src/theme"
12
12
  },
13
13
  "dependencies": {
14
- "@openc3/tool-common": "5.15.0",
14
+ "@openc3/tool-common": "5.15.2",
15
15
  "@astrouxds/astro-web-components": "7.20.0",
16
16
  "@smui/button": "^7.0.0-beta.16",
17
17
  "@smui/card": "^7.0.0-beta.16",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "5.15.0",
3
+ "version": "5.15.2",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -11,7 +11,7 @@
11
11
  "test:components": "vue-cli-service test:components"
12
12
  },
13
13
  "dependencies": {
14
- "@openc3/tool-common": "5.15.0",
14
+ "@openc3/tool-common": "5.15.2",
15
15
  "@astrouxds/astro-web-components": "7.20.0",
16
16
  "axios": "1.6.5",
17
17
  "date-fns": "2.30.0",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "widget",
3
- "version": "5.15.0",
3
+ "version": "5.15.2",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "build": "vue-cli-service build --target lib --dest tools/widgets/<%= widget_name %> --formats umd-min <%= widget_path %> --name <%= widget_name %>"
7
7
  },
8
8
  "dependencies": {
9
- "@openc3/tool-common": "5.15.0",
9
+ "@openc3/tool-common": "5.15.2",
10
10
  "@astrouxds/astro-web-components": "7.20.0",
11
11
  "vue": "2.7.16",
12
12
  "vuetify": "2.7.1"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openc3
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.15.0
4
+ version: 5.15.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Melton
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-03-10 00:00:00.000000000 Z
12
+ date: 2024-04-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler