openc3 6.8.1 → 6.9.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/bin/openc3cli +5 -5
  4. data/data/config/command_modifiers.yaml +9 -1
  5. data/data/config/screen.yaml +1 -1
  6. data/lib/openc3/accessors/json_accessor.rb +5 -5
  7. data/lib/openc3/api/interface_api.rb +71 -4
  8. data/lib/openc3/api/router_api.rb +98 -8
  9. data/lib/openc3/api/stash_api.rb +3 -3
  10. data/lib/openc3/api/tlm_api.rb +1 -1
  11. data/lib/openc3/bridge/bridge_config.rb +1 -1
  12. data/lib/openc3/interfaces/file_interface.rb +18 -0
  13. data/lib/openc3/interfaces/http_client_interface.rb +11 -0
  14. data/lib/openc3/interfaces/http_server_interface.rb +8 -0
  15. data/lib/openc3/interfaces/interface.rb +90 -21
  16. data/lib/openc3/interfaces/mqtt_interface.rb +19 -0
  17. data/lib/openc3/interfaces/mqtt_stream_interface.rb +20 -0
  18. data/lib/openc3/interfaces/protocols/burst_protocol.rb +16 -0
  19. data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +18 -0
  20. data/lib/openc3/interfaces/protocols/crc_protocol.rb +19 -0
  21. data/lib/openc3/interfaces/protocols/fixed_protocol.rb +17 -1
  22. data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +14 -0
  23. data/lib/openc3/interfaces/protocols/length_protocol.rb +25 -1
  24. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +16 -3
  25. data/lib/openc3/interfaces/protocols/protocol.rb +79 -1
  26. data/lib/openc3/interfaces/protocols/slip_protocol.rb +23 -0
  27. data/lib/openc3/interfaces/protocols/template_protocol.rb +38 -0
  28. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +14 -1
  29. data/lib/openc3/interfaces/serial_interface.rb +14 -0
  30. data/lib/openc3/interfaces/simulated_target_interface.rb +1 -1
  31. data/lib/openc3/interfaces/tcpip_client_interface.rb +16 -2
  32. data/lib/openc3/interfaces/tcpip_server_interface.rb +11 -1
  33. data/lib/openc3/interfaces/udp_interface.rb +14 -0
  34. data/lib/openc3/io/json_api_object.rb +1 -1
  35. data/lib/openc3/io/json_drb.rb +1 -1
  36. data/lib/openc3/io/json_drb_object.rb +1 -1
  37. data/lib/openc3/io/json_rpc.rb +5 -4
  38. data/lib/openc3/logs/packet_log_reader.rb +1 -1
  39. data/lib/openc3/logs/packet_log_writer.rb +6 -6
  40. data/lib/openc3/microservices/decom_microservice.rb +5 -1
  41. data/lib/openc3/microservices/interface_microservice.rb +103 -38
  42. data/lib/openc3/microservices/microservice.rb +4 -4
  43. data/lib/openc3/microservices/queue_microservice.rb +11 -1
  44. data/lib/openc3/microservices/reducer_microservice.rb +1 -1
  45. data/lib/openc3/microservices/router_microservice.rb +28 -25
  46. data/lib/openc3/models/activity_model.rb +18 -17
  47. data/lib/openc3/models/cvt_model.rb +12 -9
  48. data/lib/openc3/models/interface_model.rb +70 -12
  49. data/lib/openc3/models/metadata_model.rb +2 -2
  50. data/lib/openc3/models/microservice_status_model.rb +2 -2
  51. data/lib/openc3/models/model.rb +4 -4
  52. data/lib/openc3/models/note_model.rb +2 -2
  53. data/lib/openc3/models/plugin_model.rb +9 -4
  54. data/lib/openc3/models/queue_model.rb +1 -1
  55. data/lib/openc3/models/reaction_model.rb +6 -6
  56. data/lib/openc3/models/script_engine_model.rb +1 -1
  57. data/lib/openc3/models/script_status_model.rb +3 -3
  58. data/lib/openc3/models/sorted_model.rb +5 -5
  59. data/lib/openc3/models/target_model.rb +11 -11
  60. data/lib/openc3/models/timeline_model.rb +2 -2
  61. data/lib/openc3/models/tool_model.rb +1 -1
  62. data/lib/openc3/models/trigger_group_model.rb +3 -3
  63. data/lib/openc3/models/trigger_model.rb +6 -6
  64. data/lib/openc3/models/widget_model.rb +1 -1
  65. data/lib/openc3/operators/operator.rb +2 -2
  66. data/lib/openc3/packets/json_packet.rb +1 -1
  67. data/lib/openc3/packets/packet.rb +1 -1
  68. data/lib/openc3/script/calendar.rb +2 -2
  69. data/lib/openc3/script/metadata.rb +4 -4
  70. data/lib/openc3/script/queue.rb +2 -2
  71. data/lib/openc3/script/script_runner.rb +9 -9
  72. data/lib/openc3/script/storage.rb +1 -1
  73. data/lib/openc3/script/tables.rb +2 -2
  74. data/lib/openc3/script/web_socket_api.rb +7 -7
  75. data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +0 -12
  76. data/lib/openc3/tools/table_manager/table_manager_core.rb +1 -1
  77. data/lib/openc3/topics/command_decom_topic.rb +3 -3
  78. data/lib/openc3/topics/command_topic.rb +1 -1
  79. data/lib/openc3/topics/interface_topic.rb +45 -5
  80. data/lib/openc3/topics/limits_event_topic.rb +8 -8
  81. data/lib/openc3/topics/router_topic.rb +42 -3
  82. data/lib/openc3/topics/system_events_topic.rb +1 -1
  83. data/lib/openc3/topics/telemetry_decom_topic.rb +1 -1
  84. data/lib/openc3/utilities/authentication.rb +1 -1
  85. data/lib/openc3/utilities/cosmos_rails_formatter.rb +2 -3
  86. data/lib/openc3/utilities/local_mode.rb +8 -8
  87. data/lib/openc3/utilities/logger.rb +3 -3
  88. data/lib/openc3/utilities/running_script.rb +8 -8
  89. data/lib/openc3/version.rb +6 -6
  90. data/templates/plugin/README.md +3 -3
  91. data/templates/plugin/Rakefile +3 -3
  92. data/templates/plugin/plugin.gemspec +1 -0
  93. data/templates/tool_angular/.gitignore +1 -1
  94. data/templates/tool_angular/package.json +2 -48
  95. data/templates/tool_react/.gitignore +1 -2
  96. data/templates/tool_react/package.json +1 -51
  97. data/templates/tool_svelte/.gitignore +1 -2
  98. data/templates/tool_svelte/package.json +1 -49
  99. data/templates/tool_vue/package.json +3 -36
  100. data/templates/widget/Rakefile +1 -1
  101. data/templates/widget/package.json +2 -28
  102. metadata +9 -9
@@ -108,5 +108,19 @@ module OpenC3
108
108
  @data_bits = option_values[0].to_i
109
109
  end
110
110
  end
111
+
112
+ def details
113
+ result = super()
114
+ result['write_port_name'] = @write_port_name
115
+ result['read_port_name'] = @read_port_name
116
+ result['baud_rate'] = @baud_rate
117
+ result['parity'] = @parity
118
+ result['stop_bits'] = @stop_bits
119
+ result['write_timeout'] = @write_timeout
120
+ result['read_timeout'] = @read_timeout
121
+ result['flow_control'] = @flow_control
122
+ result['data_bits'] = @data_bits
123
+ return result
124
+ end
111
125
  end
112
126
  end
@@ -158,7 +158,7 @@ module OpenC3
158
158
  super()
159
159
  end
160
160
 
161
- protected
161
+ # protected
162
162
 
163
163
  def first_pending_packet
164
164
  packet = nil
@@ -49,9 +49,13 @@ module OpenC3
49
49
 
50
50
  @hostname = hostname
51
51
  @write_port = ConfigParser.handle_nil(write_port)
52
+ @write_port = Integer(@write_port) if @write_port
52
53
  @read_port = ConfigParser.handle_nil(read_port)
53
- @write_timeout = write_timeout
54
- @read_timeout = read_timeout
54
+ @read_port = Integer(@read_port) if @read_port
55
+ @write_timeout = ConfigParser.handle_nil(write_timeout)
56
+ @write_timeout = Float(@write_timeout) if @write_timeout
57
+ @read_timeout = ConfigParser.handle_nil(read_timeout)
58
+ @read_timeout = Float(@read_timeout) if @read_timeout
55
59
  @read_allowed = false unless @read_port
56
60
  @write_allowed = false unless @write_port
57
61
  @write_raw_allowed = false unless @write_port
@@ -90,5 +94,15 @@ module OpenC3
90
94
  end
91
95
  super()
92
96
  end
97
+
98
+ def details
99
+ result = super()
100
+ result['hostname'] = @hostname
101
+ result['write_port'] = @write_port
102
+ result['read_port'] = @read_port
103
+ result['write_timeout'] = @write_timeout
104
+ result['read_timeout'] = @read_timeout
105
+ return result
106
+ end
93
107
  end
94
108
  end
@@ -297,7 +297,7 @@ module OpenC3
297
297
  end
298
298
  end
299
299
 
300
- protected
300
+ # protected
301
301
 
302
302
  def shutdown_interfaces(interface_infos)
303
303
  @connection_mutex.synchronize do
@@ -626,5 +626,15 @@ module OpenC3
626
626
  end
627
627
  end # connection_mutex.synchronize
628
628
  end
629
+
630
+ def details
631
+ result = super()
632
+ result['write_port'] = @write_port
633
+ result['read_port'] = @read_port
634
+ result['write_timeout'] = @write_timeout
635
+ result['read_timeout'] = @read_timeout
636
+ result['listen_address'] = @listen_address
637
+ return result
638
+ end
629
639
  end
630
640
  end
@@ -189,5 +189,19 @@ module OpenC3
189
189
  @write_socket.write(data, @write_timeout)
190
190
  return data, extra
191
191
  end
192
+
193
+ def details
194
+ result = super()
195
+ result['hostname'] = @hostname
196
+ result['write_dest_port'] = @write_dest_port
197
+ result['read_port'] = @read_port
198
+ result['write_src_port'] = @write_src_port
199
+ result['interface_address'] = @interface_address
200
+ result['ttl'] = @ttl
201
+ result['write_timeout'] = @write_timeout
202
+ result['read_timeout'] = @read_timeout
203
+ result['bind_address'] = @bind_address
204
+ return result
205
+ end
192
206
  end
193
207
  end
@@ -184,7 +184,7 @@ module OpenC3
184
184
  if !data.nil? and !data.is_a?(Hash) and !data.is_a?(String)
185
185
  raise JsonApiError, "incorrect type for keyword 'data' MUST be Hash or String: #{data}"
186
186
  end
187
- return kwargs[:json] ? JSON.generate(data) : data
187
+ return kwargs[:json] ? JSON.generate(data, allow_nan: true) : data
188
188
  end
189
189
 
190
190
  # NOTE: This is a helper method and should not be called directly
@@ -336,7 +336,7 @@ module OpenC3
336
336
  protected
337
337
 
338
338
  def process_response(response, start_time)
339
- response_data = response.to_json(:allow_nan => true)
339
+ response_data = response.to_json(allow_nan: true)
340
340
  STDOUT.puts response_data if JsonDRb.debug?
341
341
  end_time = Time.now.sys
342
342
  request_time = end_time - start_time
@@ -62,7 +62,7 @@ module OpenC3
62
62
  @log = [nil, nil, nil]
63
63
  connect() if !@http
64
64
  json_rpc_request = JsonRpcRequest.new(method_name, method_params, keyword_params, @id)
65
- data = json_rpc_request.to_json(:allow_nan => true)
65
+ data = json_rpc_request.to_json(allow_nan: true)
66
66
  token = keyword_params[:token]
67
67
  response_body = make_request(data: data, token: token)
68
68
  if !response_body or response_body.to_s.length < 1
@@ -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 2024, OpenC3, Inc.
17
+ # All changes Copyright 2025, 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 'json'
24
+ require 'json/add/string'
24
25
  require 'date'
25
26
  require 'openc3/core_ext/string'
26
27
 
@@ -196,7 +197,7 @@ module OpenC3
196
197
  def <=>(other)
197
198
  return nil unless other.respond_to?(:as_json)
198
199
 
199
- self.as_json(:allow_nan => true) <=> other.as_json(:allow_nan => true)
200
+ self.as_json() <=> other.as_json()
200
201
  end
201
202
 
202
203
  # @param a [Array] Array of options
@@ -267,7 +268,7 @@ module OpenC3
267
268
  # @param request_headers [Hash] Request Header to include the auth token
268
269
  # @return [JsonRpcRequest]
269
270
  def self.from_json(request_data, request_headers)
270
- hash = JSON.parse(request_data, :allow_nan => true, :create_additions => true)
271
+ hash = JSON.parse(request_data, allow_nan: true, create_additions: true)
271
272
  hash['keyword_params']['token'] = request_headers['HTTP_AUTHORIZATION'] if request_headers['HTTP_AUTHORIZATION']
272
273
  hash['keyword_params']['manual'] = request_headers['HTTP_MANUAL'] if request_headers['HTTP_MANUAL']
273
274
  # Verify the jsonrpc version is correct and there is a method and id
@@ -306,7 +307,7 @@ module OpenC3
306
307
  def self.from_json(response_data)
307
308
  msg = "Invalid JSON-RPC 2.0 Response#{response_data.inspect}\n"
308
309
  begin
309
- hash = JSON.parse(response_data, :allow_nan => true, :create_additions => true)
310
+ hash = JSON.parse(response_data, allow_nan: true, create_additions: true)
310
311
  rescue
311
312
  raise $!, msg, $!.backtrace
312
313
  end
@@ -201,7 +201,7 @@ module OpenC3
201
201
  if cbor
202
202
  key_map = CBOR.decode(entry[4..(key_map_length + 3)])
203
203
  else
204
- key_map = JSON.parse(entry[4..(key_map_length + 3)], :allow_nan => true, :create_additions => true)
204
+ key_map = JSON.parse(entry[4..(key_map_length + 3)], allow_nan: true, create_additions: true)
205
205
  end
206
206
  @packets[packet_index] << key_map
207
207
  return read(identify_and_define)
@@ -215,7 +215,7 @@ module OpenC3
215
215
  key_map = @key_map_table[packet_index]
216
216
  unless key_map
217
217
  parsed = data
218
- parsed = JSON.parse(data, :allow_nan => true, :create_additions => true) if String === parsed
218
+ parsed = JSON.parse(data, allow_nan: true, create_additions: true) if String === parsed
219
219
  keys = parsed.keys
220
220
  key_map = {}
221
221
  reverse_key_map = {}
@@ -227,7 +227,7 @@ module OpenC3
227
227
  if @data_format == :CBOR
228
228
  write_entry(:KEY_MAP, cmd_or_tlm, target_name, packet_name, nil, nil, key_map.to_cbor, nil)
229
229
  else # JSON
230
- write_entry(:KEY_MAP, cmd_or_tlm, target_name, packet_name, nil, nil, JSON.generate(key_map, :allow_nan => true), nil)
230
+ write_entry(:KEY_MAP, cmd_or_tlm, target_name, packet_name, nil, nil, JSON.generate(key_map, allow_nan: true), nil)
231
231
  end
232
232
  end
233
233
  end
@@ -292,7 +292,7 @@ module OpenC3
292
292
  key_map = @key_map_table[packet_index]
293
293
  if key_map
294
294
  # Compress data using key map
295
- data = JSON.parse(data, :allow_nan => true, :create_additions => true) if String === data
295
+ data = JSON.parse(data, allow_nan: true, create_additions: true) if String === data
296
296
  compressed = {}
297
297
  data.each do |key, value|
298
298
  compressed_key = key_map[key]
@@ -303,7 +303,7 @@ module OpenC3
303
303
  flags |= OPENC3_CBOR_FLAG_MASK
304
304
  data = compressed.to_cbor
305
305
  else
306
- data = JSON.generate(compressed, :allow_nan => true)
306
+ data = JSON.generate(compressed, allow_nan: true)
307
307
  end
308
308
  end
309
309
  end
@@ -317,12 +317,12 @@ module OpenC3
317
317
  extra_encoded = nil
318
318
  if extra
319
319
  flags |= OPENC3_EXTRA_FLAG_MASK
320
- extra = JSON.parse(extra, :allow_nan => true, :create_additions => true) if String === extra
320
+ extra = JSON.parse(extra, allow_nan: true, create_additions: true) if String === extra
321
321
  length += OPENC3_EXTRA_LENGTH_FIXED_SIZE
322
322
  if @data_format == :CBOR
323
323
  extra_encoded = extra.as_json.to_cbor
324
324
  else
325
- extra_encoded = JSON.generate(extra.as_json, :allow_nan => true)
325
+ extra_encoded = JSON.generate(extra.as_json, allow_nan: true)
326
326
  end
327
327
  length += extra_encoded.length
328
328
  end
@@ -202,7 +202,11 @@ module OpenC3
202
202
  def limits_change_callback(packet, item, old_limits_state, value, log_change)
203
203
  return if @cancel_thread
204
204
  # Make a copy because packet_time is frozen
205
- packet_time = packet.packet_time.dup
205
+ if packet.packet_time
206
+ packet_time = packet.packet_time.dup
207
+ else
208
+ packet_time = Time.now.utc
209
+ end
206
210
  if value
207
211
  message = "#{packet.target_name} #{packet.packet_name} #{item.name} = #{value} is #{item.limits.state}"
208
212
  if item.limits.values
@@ -116,7 +116,7 @@ module OpenC3
116
116
  @logger.info "#{@interface.name}: Connect requested"
117
117
  params = []
118
118
  if msg_hash['params']
119
- params = JSON.parse(msg_hash['params'], :allow_nan => true, :create_additions => true)
119
+ params = JSON.parse(msg_hash['params'], allow_nan: true, create_additions: true)
120
120
  end
121
121
  @interface = @tlm.attempting(*params)
122
122
  next 'SUCCESS'
@@ -163,7 +163,7 @@ module OpenC3
163
163
  begin
164
164
  @logger.info "#{@interface.name}: interface_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
165
165
  @interface.interface_cmd(params['cmd_name'], *params['cmd_params'])
166
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
166
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
167
167
  rescue => e
168
168
  @logger.error "#{@interface.name}: interface_cmd: #{e.formatted}"
169
169
  next e.message
@@ -175,7 +175,7 @@ module OpenC3
175
175
  begin
176
176
  @logger.info "#{@interface.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
177
177
  @interface.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
178
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
178
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
179
179
  rescue => e
180
180
  @logger.error "#{@interface.name}: protocol_cmd: #{e.formatted}"
181
181
  next e.message
@@ -196,16 +196,45 @@ module OpenC3
196
196
  next "Critical command #{msg_hash['release_critical']} not found"
197
197
  end
198
198
  end
199
+ if msg_hash.key?('target_control')
200
+ begin
201
+ params = JSON.parse(msg_hash['target_control'], allow_nan: true, create_additions: true)
202
+ target_name = params['target_name']
203
+ cmd_only = params['cmd_only']
204
+ tlm_only = params['tlm_only']
205
+ action = params['action']
206
+ if action == 'disable'
207
+ @interface.cmd_target_enabled[target_name] = false unless tlm_only
208
+ @interface.tlm_target_enabled[target_name] = false unless cmd_only
209
+ @logger.info "#{@interface.name}: target_disable: #{target_name} cmd_only:#{cmd_only} tlm_only:#{tlm_only}"
210
+ else # enable
211
+ @interface.cmd_target_enabled[target_name] = true unless tlm_only
212
+ @interface.tlm_target_enabled[target_name] = true unless cmd_only
213
+ @logger.info "#{@interface.name}: target_enable: #{target_name} cmd_only:#{cmd_only} tlm_only:#{tlm_only}"
214
+ end
215
+ rescue => e
216
+ @logger.error "#{@interface.name}: target_control: #{e.formatted}"
217
+ next e.message
218
+ end
219
+ next 'SUCCESS'
220
+ end
221
+ if msg_hash.key?('interface_details')
222
+ next @interface.details.as_json.to_json(allow_nan: true)
223
+ end
199
224
  end
200
225
 
201
226
  target_name = msg_hash['target_name']
227
+ if target_name and not @interface.cmd_target_enabled[target_name]
228
+ next nil # Return and don't ack given target_name if disabled
229
+ end
230
+
202
231
  cmd_name = msg_hash['cmd_name']
203
232
  manual = ConfigParser.handle_true_false(msg_hash['manual'])
204
233
  cmd_params = nil
205
234
  cmd_buffer = nil
206
235
  hazardous_check = nil
207
236
  if msg_hash['cmd_params']
208
- cmd_params = JSON.parse(msg_hash['cmd_params'], :allow_nan => true, :create_additions => true)
237
+ cmd_params = JSON.parse(msg_hash['cmd_params'], allow_nan: true, create_additions: true)
209
238
  range_check = ConfigParser.handle_true_false(msg_hash['range_check'])
210
239
  raw = ConfigParser.handle_true_false(msg_hash['raw'])
211
240
  hazardous_check = ConfigParser.handle_true_false(msg_hash['hazardous_check'])
@@ -230,10 +259,15 @@ module OpenC3
230
259
  else
231
260
  raise "Invalid command received:\n #{msg_hash}"
232
261
  end
233
- orig_command = System.commands.packet(command.target_name, command.packet_name)
234
- orig_command.received_count = TargetModel.increment_command_count(command.target_name, command.packet_name, 1, scope: @scope)
235
- command.received_count = orig_command.received_count
236
- command.received_time = Time.now
262
+
263
+ if @interface.cmd_target_enabled[command.target_name]
264
+ orig_command = System.commands.packet(command.target_name, command.packet_name)
265
+ orig_command.received_count = TargetModel.increment_command_count(command.target_name, command.packet_name, 1, scope: @scope)
266
+ command.received_count = orig_command.received_count
267
+ command.received_time = Time.now
268
+ else
269
+ next nil # Don't ack disabled targets
270
+ end
237
271
  rescue => e
238
272
  @logger.error "#{@interface.name}: #{msg_hash}"
239
273
  @logger.error "#{@interface.name}: #{e.formatted}"
@@ -312,7 +346,7 @@ module OpenC3
312
346
 
313
347
  CommandDecomTopic.write_packet(command, scope: @scope)
314
348
  CommandTopic.write_packet(command, scope: @scope)
315
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
349
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
316
350
 
317
351
  # Explicitly check for false to allow nil to represent unknown
318
352
  if result == false
@@ -391,7 +425,7 @@ module OpenC3
391
425
  @logger.info "#{@router.name}: Connect requested"
392
426
  params = []
393
427
  if msg_hash['params']
394
- params = JSON.parse(msg_hash['params'], :allow_nan => true, :create_additions => true)
428
+ params = JSON.parse(msg_hash['params'], allow_nan: true, create_additions: true)
395
429
  end
396
430
  @router = @tlm.attempting(*params)
397
431
  end
@@ -413,7 +447,7 @@ module OpenC3
413
447
  begin
414
448
  @logger.info "#{@router.name}: router_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
415
449
  @router.interface_cmd(params['cmd_name'], *params['cmd_params'])
416
- RouterStatusModel.set(@router.as_json(:allow_nan => true), queued: true, scope: @scope)
450
+ RouterStatusModel.set(@router.as_json(), queued: true, scope: @scope)
417
451
  rescue => e
418
452
  @logger.error "#{@router.name}: router_cmd: #{e.formatted}"
419
453
  next e.message
@@ -425,13 +459,38 @@ module OpenC3
425
459
  begin
426
460
  @logger.info "#{@router.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
427
461
  @router.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
428
- RouterStatusModel.set(@router.as_json(:allow_nan => true), queued: true, scope: @scope)
462
+ RouterStatusModel.set(@router.as_json(), queued: true, scope: @scope)
463
+ rescue => e
464
+ @logger.error "#{@router.name}: protocol_cmd: #{e.formatted}"
465
+ next e.message
466
+ end
467
+ next 'SUCCESS'
468
+ end
469
+ if msg_hash.key?('target_control')
470
+ begin
471
+ params = JSON.parse(msg_hash['target_control'], allow_nan: true, create_additions: true)
472
+ target_name = params['target_name']
473
+ cmd_only = params['cmd_only']
474
+ tlm_only = params['tlm_only']
475
+ action = params['action']
476
+ if action == 'disable'
477
+ @router.cmd_target_enabled[target_name] = false unless tlm_only
478
+ @router.tlm_target_enabled[target_name] = false unless cmd_only
479
+ @logger.info "#{@router.name}: target_disable: #{target_name} cmd_only:#{cmd_only} tlm_only:#{tlm_only}"
480
+ else # enable
481
+ @router.cmd_target_enabled[target_name] = true unless tlm_only
482
+ @router.tlm_target_enabled[target_name] = true unless cmd_only
483
+ @logger.info "#{@router.name}: target_enable: #{target_name} cmd_only:#{cmd_only} tlm_only:#{tlm_only}"
484
+ end
429
485
  rescue => e
430
- @logger.error "#{@router.name}: protoco_cmd: #{e.formatted}"
486
+ @logger.error "#{@router.name}: target_control: #{e.formatted}"
431
487
  next e.message
432
488
  end
433
489
  next 'SUCCESS'
434
490
  end
491
+ if msg_hash.key?('router_details')
492
+ next @router.details.as_json.to_json(allow_nan: true)
493
+ end
435
494
  next 'SUCCESS'
436
495
  end
437
496
 
@@ -442,20 +501,24 @@ module OpenC3
442
501
  target_name = msg_hash["target_name"]
443
502
  packet_name = msg_hash["packet_name"]
444
503
 
445
- packet = System.telemetry.packet(target_name, packet_name)
446
- packet.stored = ConfigParser.handle_true_false(msg_hash["stored"])
447
- packet.received_time = Time.from_nsec_from_epoch(msg_hash["time"].to_i)
448
- packet.received_count = msg_hash["received_count"].to_i
449
- packet.buffer = msg_hash["buffer"]
504
+ if @router.tlm_target_enabled[target_name]
505
+ packet = System.telemetry.packet(target_name, packet_name)
506
+ packet.stored = ConfigParser.handle_true_false(msg_hash["stored"])
507
+ packet.received_time = Time.from_nsec_from_epoch(msg_hash["time"].to_i)
508
+ packet.received_count = msg_hash["received_count"].to_i
509
+ packet.buffer = msg_hash["buffer"]
450
510
 
451
- begin
452
- @router.write(packet)
453
- RouterStatusModel.set(@router.as_json(:allow_nan => true), queued: true, scope: @scope)
454
- next 'SUCCESS'
455
- rescue => e
456
- @logger.error "#{@router.name}: #{e.formatted}"
457
- next e.message
511
+ begin
512
+ @router.write(packet)
513
+ RouterStatusModel.set(@router.as_json(), queued: true, scope: @scope)
514
+ next 'SUCCESS'
515
+ rescue => e
516
+ @logger.error "#{@router.name}: #{e.formatted}"
517
+ next e.message
518
+ end
458
519
  end
520
+ else
521
+ next nil # Don't ack disabled targets
459
522
  end
460
523
  end
461
524
  end
@@ -510,9 +573,9 @@ module OpenC3
510
573
  @interface.state = 'DISCONNECTED'
511
574
  end
512
575
  if @interface_or_router == 'INTERFACE'
513
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
576
+ InterfaceStatusModel.set(@interface.as_json(), scope: @scope)
514
577
  else
515
- RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
578
+ RouterStatusModel.set(@interface.as_json(), scope: @scope)
516
579
  end
517
580
 
518
581
  @queued = false
@@ -576,9 +639,9 @@ module OpenC3
576
639
 
577
640
  @interface.state = 'ATTEMPTING'
578
641
  if @interface_or_router == 'INTERFACE'
579
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
642
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
580
643
  else
581
- RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
644
+ RouterStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
582
645
  end
583
646
  @interface # Return the interface/router since we may have recreated it
584
647
  # Need to rescue Exception so we cover LoadError
@@ -651,15 +714,15 @@ module OpenC3
651
714
  disconnect(false)
652
715
  end
653
716
  if @interface_or_router == 'INTERFACE'
654
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
717
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
655
718
  else
656
- RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
719
+ RouterStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
657
720
  end
658
721
  @logger.info "#{@interface.name}: Stopped packet reading"
659
722
  end
660
723
 
661
724
  def handle_packet(packet)
662
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
725
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
663
726
  packet.received_time = Time.now.sys unless packet.received_time
664
727
 
665
728
  if packet.stored
@@ -709,8 +772,10 @@ module OpenC3
709
772
  end
710
773
 
711
774
  # Write to stream
712
- sync_tlm_packet_counts(packet)
713
- TelemetryTopic.write_packet(packet, queued: @queued, scope: @scope)
775
+ if @interface.tlm_target_enabled[packet.target_name]
776
+ sync_tlm_packet_counts(packet)
777
+ TelemetryTopic.write_packet(packet, queued: @queued, scope: @scope)
778
+ end
714
779
  end
715
780
 
716
781
  def handle_connection_failed(connection, connect_error)
@@ -774,9 +839,9 @@ module OpenC3
774
839
  end
775
840
  @interface.state = 'CONNECTED'
776
841
  if @interface_or_router == 'INTERFACE'
777
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
842
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
778
843
  else
779
- RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
844
+ RouterStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
780
845
  end
781
846
  @logger.info "#{@interface.name}: Connection Success"
782
847
  end
@@ -806,9 +871,9 @@ module OpenC3
806
871
  else
807
872
  @interface.state = 'DISCONNECTED'
808
873
  if @interface_or_router == 'INTERFACE'
809
- InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
874
+ InterfaceStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
810
875
  else
811
- RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
876
+ RouterStatusModel.set(@interface.as_json(), queued: true, scope: @scope)
812
877
  end
813
878
  end
814
879
  end
@@ -52,7 +52,7 @@ module OpenC3
52
52
  microservice = self.new(name)
53
53
  thread = Thread.new do
54
54
  begin
55
- MicroserviceStatusModel.set(microservice.as_json(:allow_nan => true), scope: microservice.scope)
55
+ MicroserviceStatusModel.set(microservice.as_json(), scope: microservice.scope)
56
56
  microservice.state = 'RUNNING'
57
57
  microservice.run
58
58
  microservice.state = 'FINISHED'
@@ -66,7 +66,7 @@ module OpenC3
66
66
  end
67
67
  microservice.shutdown # Dying in crash so should try to shutdown
68
68
  ensure
69
- MicroserviceStatusModel.set(microservice.as_json(:allow_nan => true), scope: microservice.scope)
69
+ MicroserviceStatusModel.set(microservice.as_json(), scope: microservice.scope)
70
70
  end
71
71
  end
72
72
  ThreadManager.instance.register(thread, shutdown_object: microservice)
@@ -192,7 +192,7 @@ module OpenC3
192
192
  @microservice_status_period_seconds = 5
193
193
  @microservice_status_thread = Thread.new do
194
194
  until @cancel_thread
195
- MicroserviceStatusModel.set(as_json(:allow_nan => true), scope: @scope) unless @cancel_thread
195
+ MicroserviceStatusModel.set(as_json(), scope: @scope) unless @cancel_thread
196
196
  break if @microservice_status_sleeper.sleep(@microservice_status_period_seconds)
197
197
  end
198
198
  rescue Exception => e
@@ -214,7 +214,7 @@ module OpenC3
214
214
  @state = state
215
215
  @cancel_thread = true
216
216
  @microservice_status_sleeper.cancel if @microservice_status_sleeper
217
- MicroserviceStatusModel.set(as_json(:allow_nan => true), scope: @scope)
217
+ MicroserviceStatusModel.set(as_json(), scope: @scope)
218
218
  FileUtils.remove_entry_secure(@temp_dir, true)
219
219
  @metric.shutdown
220
220
  @logger.debug("Shutting down microservice complete: #{@name}")
@@ -22,6 +22,14 @@ require 'openc3/utilities/authentication'
22
22
  require 'openc3/script'
23
23
 
24
24
  module OpenC3
25
+ module Script
26
+ private
27
+ # Override the prompt_for_hazardous method to always return true since there is no user to prompt
28
+ def prompt_for_hazardous(target_name, cmd_name, hazardous_description)
29
+ return true
30
+ end
31
+ end
32
+
25
33
  # The queue processor runs in a single thread and processes commands via cmd_api.
26
34
  class QueueProcessor
27
35
  attr_accessor :state
@@ -73,7 +81,9 @@ module OpenC3
73
81
  token = get_token(username)
74
82
  # It's important to set queue: false here to avoid infinite recursion when
75
83
  # OPENC3_DEFAULT_QUEUE is set because commands would be re-queued to the default queue
76
- cmd_no_hazardous_check(command['value'], queue: false, scope: @scope, token: token)
84
+ # NOTE: cmd() via script rescues hazardous errors and calls prompt_for_hazardous()
85
+ # but we've overridden it to always return true and go straight to cmd_no_hazardous_check()
86
+ cmd(command['value'], queue: false, scope: @scope, token: token)
77
87
  end
78
88
  rescue StandardError => e
79
89
  @logger.error "QueueProcessor failed to process command from queue #{@name}\n#{e.message}"
@@ -522,7 +522,7 @@ module OpenC3
522
522
  reduce(type, state.raw_keys, state.converted_keys, state.reduced)
523
523
  state.reduced.merge!(state.entry_samples)
524
524
  time = state.entry_time
525
- data = JSON.generate(state.reduced.as_json(:allow_nan => true))
525
+ data = JSON.generate(state.reduced.as_json, allow_nan: true)
526
526
  if type == "minute"
527
527
  redis_topic, redis_offset = TelemetryReducedMinuteTopic.write(target_name: target_name, packet_name: packet_name, stored: stored, time: time, data: data, scope: @scope)
528
528
  elsif type == "hour"