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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/bin/openc3cli +5 -5
- data/data/config/command_modifiers.yaml +9 -1
- data/data/config/screen.yaml +1 -1
- data/lib/openc3/accessors/json_accessor.rb +5 -5
- data/lib/openc3/api/interface_api.rb +71 -4
- data/lib/openc3/api/router_api.rb +98 -8
- data/lib/openc3/api/stash_api.rb +3 -3
- data/lib/openc3/api/tlm_api.rb +1 -1
- data/lib/openc3/bridge/bridge_config.rb +1 -1
- data/lib/openc3/interfaces/file_interface.rb +18 -0
- data/lib/openc3/interfaces/http_client_interface.rb +11 -0
- data/lib/openc3/interfaces/http_server_interface.rb +8 -0
- data/lib/openc3/interfaces/interface.rb +90 -21
- data/lib/openc3/interfaces/mqtt_interface.rb +19 -0
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +20 -0
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +16 -0
- data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +18 -0
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +19 -0
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +17 -1
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +14 -0
- data/lib/openc3/interfaces/protocols/length_protocol.rb +25 -1
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +16 -3
- data/lib/openc3/interfaces/protocols/protocol.rb +79 -1
- data/lib/openc3/interfaces/protocols/slip_protocol.rb +23 -0
- data/lib/openc3/interfaces/protocols/template_protocol.rb +38 -0
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +14 -1
- data/lib/openc3/interfaces/serial_interface.rb +14 -0
- data/lib/openc3/interfaces/simulated_target_interface.rb +1 -1
- data/lib/openc3/interfaces/tcpip_client_interface.rb +16 -2
- data/lib/openc3/interfaces/tcpip_server_interface.rb +11 -1
- data/lib/openc3/interfaces/udp_interface.rb +14 -0
- data/lib/openc3/io/json_api_object.rb +1 -1
- data/lib/openc3/io/json_drb.rb +1 -1
- data/lib/openc3/io/json_drb_object.rb +1 -1
- data/lib/openc3/io/json_rpc.rb +5 -4
- data/lib/openc3/logs/packet_log_reader.rb +1 -1
- data/lib/openc3/logs/packet_log_writer.rb +6 -6
- data/lib/openc3/microservices/decom_microservice.rb +5 -1
- data/lib/openc3/microservices/interface_microservice.rb +103 -38
- data/lib/openc3/microservices/microservice.rb +4 -4
- data/lib/openc3/microservices/queue_microservice.rb +11 -1
- data/lib/openc3/microservices/reducer_microservice.rb +1 -1
- data/lib/openc3/microservices/router_microservice.rb +28 -25
- data/lib/openc3/models/activity_model.rb +18 -17
- data/lib/openc3/models/cvt_model.rb +12 -9
- data/lib/openc3/models/interface_model.rb +70 -12
- data/lib/openc3/models/metadata_model.rb +2 -2
- data/lib/openc3/models/microservice_status_model.rb +2 -2
- data/lib/openc3/models/model.rb +4 -4
- data/lib/openc3/models/note_model.rb +2 -2
- data/lib/openc3/models/plugin_model.rb +9 -4
- data/lib/openc3/models/queue_model.rb +1 -1
- data/lib/openc3/models/reaction_model.rb +6 -6
- data/lib/openc3/models/script_engine_model.rb +1 -1
- data/lib/openc3/models/script_status_model.rb +3 -3
- data/lib/openc3/models/sorted_model.rb +5 -5
- data/lib/openc3/models/target_model.rb +11 -11
- data/lib/openc3/models/timeline_model.rb +2 -2
- data/lib/openc3/models/tool_model.rb +1 -1
- data/lib/openc3/models/trigger_group_model.rb +3 -3
- data/lib/openc3/models/trigger_model.rb +6 -6
- data/lib/openc3/models/widget_model.rb +1 -1
- data/lib/openc3/operators/operator.rb +2 -2
- data/lib/openc3/packets/json_packet.rb +1 -1
- data/lib/openc3/packets/packet.rb +1 -1
- data/lib/openc3/script/calendar.rb +2 -2
- data/lib/openc3/script/metadata.rb +4 -4
- data/lib/openc3/script/queue.rb +2 -2
- data/lib/openc3/script/script_runner.rb +9 -9
- data/lib/openc3/script/storage.rb +1 -1
- data/lib/openc3/script/tables.rb +2 -2
- data/lib/openc3/script/web_socket_api.rb +7 -7
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +0 -12
- data/lib/openc3/tools/table_manager/table_manager_core.rb +1 -1
- data/lib/openc3/topics/command_decom_topic.rb +3 -3
- data/lib/openc3/topics/command_topic.rb +1 -1
- data/lib/openc3/topics/interface_topic.rb +45 -5
- data/lib/openc3/topics/limits_event_topic.rb +8 -8
- data/lib/openc3/topics/router_topic.rb +42 -3
- data/lib/openc3/topics/system_events_topic.rb +1 -1
- data/lib/openc3/topics/telemetry_decom_topic.rb +1 -1
- data/lib/openc3/utilities/authentication.rb +1 -1
- data/lib/openc3/utilities/cosmos_rails_formatter.rb +2 -3
- data/lib/openc3/utilities/local_mode.rb +8 -8
- data/lib/openc3/utilities/logger.rb +3 -3
- data/lib/openc3/utilities/running_script.rb +8 -8
- data/lib/openc3/version.rb +6 -6
- data/templates/plugin/README.md +3 -3
- data/templates/plugin/Rakefile +3 -3
- data/templates/plugin/plugin.gemspec +1 -0
- data/templates/tool_angular/.gitignore +1 -1
- data/templates/tool_angular/package.json +2 -48
- data/templates/tool_react/.gitignore +1 -2
- data/templates/tool_react/package.json +1 -51
- data/templates/tool_svelte/.gitignore +1 -2
- data/templates/tool_svelte/package.json +1 -49
- data/templates/tool_vue/package.json +3 -36
- data/templates/widget/Rakefile +1 -1
- data/templates/widget/package.json +2 -28
- metadata +9 -9
@@ -25,7 +25,7 @@ require 'openc3/microservices/interface_microservice'
|
|
25
25
|
module OpenC3
|
26
26
|
class RouterMicroservice < InterfaceMicroservice
|
27
27
|
def handle_packet(packet)
|
28
|
-
RouterStatusModel.set(@interface.as_json(
|
28
|
+
RouterStatusModel.set(@interface.as_json(), scope: @scope)
|
29
29
|
if !packet.identified?
|
30
30
|
# Need to identify so we can find the target
|
31
31
|
identified_packet = System.commands.identify(packet.buffer(false), @interface.cmd_target_names)
|
@@ -50,37 +50,40 @@ module OpenC3
|
|
50
50
|
target_name = 'UNKNOWN' unless target_name
|
51
51
|
target = System.targets[target_name]
|
52
52
|
|
53
|
-
|
53
|
+
# Don't route disabled target names
|
54
|
+
if @interface.cmd_target_enabled[target_name]
|
54
55
|
begin
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
56
|
+
begin
|
57
|
+
log_message = true # Default is true
|
58
|
+
# If the packet has the DISABLE_MESSAGES keyword then no messages by default
|
59
|
+
log_message = false if packet.messages_disabled
|
60
|
+
# Check if any of the parameters have DISABLE_MESSAGES
|
61
|
+
packet.sorted_items.each do |item|
|
62
|
+
if item.states and item.messages_disabled
|
63
|
+
value = packet.read_item(item)
|
64
|
+
if item.messages_disabled[value]
|
65
|
+
log_message = false
|
66
|
+
break
|
67
|
+
end
|
65
68
|
end
|
66
69
|
end
|
67
|
-
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
if log_message
|
72
|
+
if target and target_name != 'UNKNOWN'
|
73
|
+
@logger.info System.commands.format(packet, target.ignored_parameters)
|
74
|
+
else
|
75
|
+
@logger.warn "Unidentified packet of #{packet.length} bytes being routed to target #{@interface.cmd_target_names[0]}"
|
76
|
+
end
|
74
77
|
end
|
78
|
+
rescue => err
|
79
|
+
@logger.error "Problem formatting command from router:\n#{err.formatted}"
|
75
80
|
end
|
76
|
-
rescue => err
|
77
|
-
@logger.error "Problem formatting command from router:\n#{err.formatted}"
|
78
|
-
end
|
79
81
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
RouterTopic.route_command(packet, @interface.cmd_target_names, scope: @scope)
|
83
|
+
rescue Exception => err
|
84
|
+
@error = err
|
85
|
+
@logger.error "Error routing command from #{@interface.name}\n#{err.formatted}"
|
86
|
+
end
|
84
87
|
end
|
85
88
|
end
|
86
89
|
end
|
@@ -56,13 +56,13 @@ module OpenC3
|
|
56
56
|
raise ActivityInputError.new "start: #{start} must be <= stop: #{stop}"
|
57
57
|
end
|
58
58
|
array = Store.zrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", start, stop, :limit => [0, limit])
|
59
|
-
return array.map { |value| JSON.parse(value, :
|
59
|
+
return array.map { |value| JSON.parse(value, allow_nan: true, create_additions: true) }
|
60
60
|
end
|
61
61
|
|
62
62
|
# @return [Array<Hash>] Array up to the limit of the models (as Hash objects) stored under the primary key
|
63
63
|
def self.all(name:, scope:, limit: 100)
|
64
64
|
array = Store.zrange("#{scope}#{PRIMARY_KEY}__#{name}", 0, -1, :limit => [0, limit])
|
65
|
-
return array.map { |value| JSON.parse(value, :
|
65
|
+
return array.map { |value| JSON.parse(value, allow_nan: true, create_additions: true) }
|
66
66
|
end
|
67
67
|
|
68
68
|
# @return [String|nil] String of the saved json or nil if score not found under primary_key
|
@@ -108,7 +108,7 @@ module OpenC3
|
|
108
108
|
|
109
109
|
# First find all the activities at the score
|
110
110
|
json = Store.zrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", score, score, :limit => [0, 100])
|
111
|
-
parsed = json.map { |value| JSON.parse(value, :
|
111
|
+
parsed = json.map { |value| JSON.parse(value, allow_nan: true, create_additions: true) }
|
112
112
|
parsed.each_with_index do |value, index|
|
113
113
|
if uuid
|
114
114
|
# If the uuid is given then only delete activities that match the uuid
|
@@ -128,7 +128,7 @@ module OpenC3
|
|
128
128
|
|
129
129
|
notification = {
|
130
130
|
# start / stop to match SortedModel
|
131
|
-
'data' => JSON.generate({'start' => score, 'uuid' => uuid}),
|
131
|
+
'data' => JSON.generate({'start' => score, 'uuid' => uuid}, allow_nan: true),
|
132
132
|
'kind' => 'deleted',
|
133
133
|
'type' => 'activity',
|
134
134
|
'timeline' => name
|
@@ -143,7 +143,7 @@ module OpenC3
|
|
143
143
|
result = Store.zremrangebyscore("#{scope}#{PRIMARY_KEY}__#{name}", min, max)
|
144
144
|
notification = {
|
145
145
|
# start / stop to match SortedModel
|
146
|
-
'data' => JSON.generate({'start' => min, 'stop' => max}),
|
146
|
+
'data' => JSON.generate({'start' => min, 'stop' => max}, allow_nan: true),
|
147
147
|
'kind' => 'deleted',
|
148
148
|
'type' => 'activity',
|
149
149
|
'timeline' => name
|
@@ -154,7 +154,7 @@ module OpenC3
|
|
154
154
|
|
155
155
|
# @return [ActivityModel] Model generated from the passed JSON
|
156
156
|
def self.from_json(json, name:, scope:)
|
157
|
-
json = JSON.parse(json, :
|
157
|
+
json = JSON.parse(json, allow_nan: true, create_additions: true) if String === json
|
158
158
|
raise "json data is nil" if json.nil?
|
159
159
|
self.new(**json.transform_keys(&:to_sym), name: name, scope: scope)
|
160
160
|
end
|
@@ -204,7 +204,7 @@ module OpenC3
|
|
204
204
|
# Adding a '(' makes the max value exclusive
|
205
205
|
array = Store.zrevrangebyscore(@primary_key, "(#{stop}", start - MAX_DURATION)
|
206
206
|
array.each do |value|
|
207
|
-
activity = JSON.parse(value, :
|
207
|
+
activity = JSON.parse(value, allow_nan: true, create_additions: true)
|
208
208
|
if ignore_score == activity['start']
|
209
209
|
next
|
210
210
|
elsif activity['stop'] > start
|
@@ -289,7 +289,7 @@ module OpenC3
|
|
289
289
|
# Get all the existing events in the recurring time range as well as those before
|
290
290
|
# the start of the recurring time range to ensure we don't start inside an existing event
|
291
291
|
existing = Store.zrevrangebyscore(@primary_key, @recurring['end'] - 1, @recurring['start'] - MAX_DURATION)
|
292
|
-
existing.map! {|value| JSON.parse(value, :
|
292
|
+
existing.map! {|value| JSON.parse(value, allow_nan: true, create_additions: true) }
|
293
293
|
end
|
294
294
|
last_stop = nil
|
295
295
|
|
@@ -315,7 +315,7 @@ module OpenC3
|
|
315
315
|
end
|
316
316
|
end
|
317
317
|
end
|
318
|
-
multi.zadd(@primary_key, @start, JSON.generate(self.as_json
|
318
|
+
multi.zadd(@primary_key, @start, JSON.generate(self.as_json, allow_nan: true))
|
319
319
|
last_stop = @stop
|
320
320
|
end
|
321
321
|
end
|
@@ -331,7 +331,7 @@ module OpenC3
|
|
331
331
|
end
|
332
332
|
@updated_at = Time.now.to_nsec_from_epoch
|
333
333
|
add_event(status: 'created')
|
334
|
-
Store.zadd(@primary_key, @start, JSON.generate(self.as_json
|
334
|
+
Store.zadd(@primary_key, @start, JSON.generate(self.as_json, allow_nan: true))
|
335
335
|
notify(kind: 'created')
|
336
336
|
end
|
337
337
|
end
|
@@ -359,12 +359,12 @@ module OpenC3
|
|
359
359
|
|
360
360
|
add_event(status: 'updated')
|
361
361
|
json = Store.zrangebyscore(@primary_key, old_start, old_start)
|
362
|
-
parsed = json.map { |value| JSON.parse(value, :
|
362
|
+
parsed = json.map { |value| JSON.parse(value, allow_nan: true, create_additions: true) }
|
363
363
|
parsed.each_with_index do |value, index|
|
364
364
|
if value['uuid'] == old_uuid
|
365
365
|
Store.multi do |multi|
|
366
366
|
multi.zrem(@primary_key, json[index])
|
367
|
-
multi.zadd(@primary_key, @start, JSON.generate(self.as_json
|
367
|
+
multi.zadd(@primary_key, @start, JSON.generate(self.as_json, allow_nan: true))
|
368
368
|
end
|
369
369
|
end
|
370
370
|
end
|
@@ -375,9 +375,10 @@ module OpenC3
|
|
375
375
|
# commit will make an event and save the object to the redis database
|
376
376
|
# @param [String] status - the event status such as "complete" or "failed"
|
377
377
|
# @param [String] message - an optional message to include in the event
|
378
|
-
|
378
|
+
# @param [Time] timestamp - optional timestamp to use instead of current time
|
379
|
+
def commit(status:, message: nil, fulfillment: nil, timestamp: nil)
|
379
380
|
event = {
|
380
|
-
'time' => Time.now.to_i,
|
381
|
+
'time' => timestamp ? timestamp.to_i : Time.now.to_i,
|
381
382
|
'event' => status,
|
382
383
|
'commit' => true
|
383
384
|
}
|
@@ -386,12 +387,12 @@ module OpenC3
|
|
386
387
|
@events << event
|
387
388
|
|
388
389
|
json = Store.zrangebyscore(@primary_key, @start, @start)
|
389
|
-
parsed = json.map { |value| JSON.parse(value, :
|
390
|
+
parsed = json.map { |value| JSON.parse(value, allow_nan: true, create_additions: true) }
|
390
391
|
parsed.each_with_index do |value, index|
|
391
392
|
if value['uuid'] == @uuid
|
392
393
|
Store.multi do |multi|
|
393
394
|
multi.zrem(@primary_key, json[index])
|
394
|
-
multi.zadd(@primary_key, @start, JSON.generate(self.as_json
|
395
|
+
multi.zadd(@primary_key, @start, JSON.generate(self.as_json, allow_nan: true))
|
395
396
|
end
|
396
397
|
end
|
397
398
|
end
|
@@ -411,7 +412,7 @@ module OpenC3
|
|
411
412
|
# update the redis stream / timeline topic that something has changed
|
412
413
|
def notify(kind:, extra: nil)
|
413
414
|
notification = {
|
414
|
-
'data' => JSON.generate(as_json
|
415
|
+
'data' => JSON.generate(as_json, allow_nan: true),
|
415
416
|
'kind' => kind,
|
416
417
|
'type' => 'activity',
|
417
418
|
'timeline' => @name
|
@@ -48,7 +48,7 @@ module OpenC3
|
|
48
48
|
|
49
49
|
# Set the current value table for a target, packet
|
50
50
|
def self.set(hash, target_name:, packet_name:, queued: false, scope: $openc3_scope)
|
51
|
-
packet_json = JSON.generate(hash.as_json
|
51
|
+
packet_json = JSON.generate(hash.as_json, allow_nan: true)
|
52
52
|
key = "#{scope}__tlm__#{target_name}"
|
53
53
|
tgt_pkt_key = key + "__#{packet_name}"
|
54
54
|
@@packet_cache[tgt_pkt_key] = [Time.now, hash]
|
@@ -71,7 +71,7 @@ module OpenC3
|
|
71
71
|
end
|
72
72
|
packet = Store.hget(key, packet_name)
|
73
73
|
raise "Packet '#{target_name} #{packet_name}' does not exist" unless packet
|
74
|
-
hash = JSON.parse(packet, :
|
74
|
+
hash = JSON.parse(packet, allow_nan: true, create_additions: true)
|
75
75
|
@@packet_cache[tgt_pkt_key] = [now, hash]
|
76
76
|
hash
|
77
77
|
end
|
@@ -310,7 +310,7 @@ module OpenC3
|
|
310
310
|
all = Store.hgetall("#{scope}__override__#{target_name}")
|
311
311
|
next if all.nil? or all.empty?
|
312
312
|
all.each do |packet_name, hash|
|
313
|
-
items = JSON.parse(hash, :
|
313
|
+
items = JSON.parse(hash, allow_nan: true, create_additions: true)
|
314
314
|
items.each do |key, value|
|
315
315
|
item = {}
|
316
316
|
item['target_name'] = target_name
|
@@ -339,7 +339,7 @@ module OpenC3
|
|
339
339
|
# for the given type
|
340
340
|
def self.override(target_name, packet_name, item_name, value, type: :ALL, scope: $openc3_scope)
|
341
341
|
hash = Store.hget("#{scope}__override__#{target_name}", packet_name)
|
342
|
-
hash = JSON.parse(hash, :
|
342
|
+
hash = JSON.parse(hash, allow_nan: true, create_additions: true) if hash
|
343
343
|
hash ||= {} # In case the above didn't create anything
|
344
344
|
case type
|
345
345
|
when :ALL
|
@@ -361,13 +361,13 @@ module OpenC3
|
|
361
361
|
|
362
362
|
tgt_pkt_key = "#{scope}__tlm__#{target_name}__#{packet_name}"
|
363
363
|
@@override_cache[tgt_pkt_key] = [Time.now, hash]
|
364
|
-
Store.hset("#{scope}__override__#{target_name}", packet_name, JSON.generate(hash.as_json
|
364
|
+
Store.hset("#{scope}__override__#{target_name}", packet_name, JSON.generate(hash.as_json, allow_nan: true))
|
365
365
|
end
|
366
366
|
|
367
367
|
# Normalize a current value table item such that it returns the actual value
|
368
368
|
def self.normalize(target_name, packet_name, item_name, type: :ALL, scope: $openc3_scope)
|
369
369
|
hash = Store.hget("#{scope}__override__#{target_name}", packet_name)
|
370
|
-
hash = JSON.parse(hash, :
|
370
|
+
hash = JSON.parse(hash, allow_nan: true, create_additions: true) if hash
|
371
371
|
hash ||= {} # In case the above didn't create anything
|
372
372
|
case type
|
373
373
|
when :ALL
|
@@ -393,7 +393,7 @@ module OpenC3
|
|
393
393
|
Store.hdel("#{scope}__override__#{target_name}", packet_name)
|
394
394
|
else
|
395
395
|
@@override_cache[tgt_pkt_key] = [Time.now, hash]
|
396
|
-
Store.hset("#{scope}__override__#{target_name}", packet_name, JSON.generate(hash.as_json
|
396
|
+
Store.hset("#{scope}__override__#{target_name}", packet_name, JSON.generate(hash.as_json, allow_nan: true))
|
397
397
|
end
|
398
398
|
end
|
399
399
|
|
@@ -411,7 +411,10 @@ module OpenC3
|
|
411
411
|
latest_packet_name = packet_name
|
412
412
|
end
|
413
413
|
end
|
414
|
-
|
414
|
+
# Return the first packet name if no packets have been received
|
415
|
+
if latest == -1
|
416
|
+
latest_packet_name = packet_names[0]
|
417
|
+
end
|
415
418
|
return latest_packet_name
|
416
419
|
end
|
417
420
|
|
@@ -453,7 +456,7 @@ module OpenC3
|
|
453
456
|
end
|
454
457
|
override_data = Store.hget("#{scope}__override__#{target_name}", packet_name)
|
455
458
|
if override_data
|
456
|
-
hash = JSON.parse(override_data, :
|
459
|
+
hash = JSON.parse(override_data, allow_nan: true, create_additions: true)
|
457
460
|
overrides[tgt_pkt_key] = hash
|
458
461
|
else
|
459
462
|
hash = {}
|
@@ -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
|
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
|
@@ -33,6 +33,8 @@ module OpenC3
|
|
33
33
|
attr_accessor :target_names # Redundant superset of cmd_target_names and tlm_target_names for backwards compat
|
34
34
|
attr_accessor :cmd_target_names
|
35
35
|
attr_accessor :tlm_target_names
|
36
|
+
attr_accessor :cmd_target_enabled
|
37
|
+
attr_accessor :tlm_target_enabled
|
36
38
|
attr_accessor :connect_on_startup
|
37
39
|
attr_accessor :auto_reconnect
|
38
40
|
attr_accessor :reconnect_delay
|
@@ -104,6 +106,8 @@ module OpenC3
|
|
104
106
|
target_names: [],
|
105
107
|
cmd_target_names: [],
|
106
108
|
tlm_target_names: [],
|
109
|
+
cmd_target_enabled: nil,
|
110
|
+
tlm_target_enabled: nil,
|
107
111
|
connect_on_startup: true,
|
108
112
|
auto_reconnect: true,
|
109
113
|
reconnect_delay: 5.0,
|
@@ -134,6 +138,22 @@ module OpenC3
|
|
134
138
|
@target_names = target_names
|
135
139
|
@cmd_target_names = cmd_target_names
|
136
140
|
@tlm_target_names = tlm_target_names
|
141
|
+
@cmd_target_enabled = cmd_target_enabled
|
142
|
+
if @cmd_target_enabled.nil?
|
143
|
+
@cmd_target_enabled = {}
|
144
|
+
@cmd_target_names.each do |target_name|
|
145
|
+
@cmd_target_enabled[target_name] = true
|
146
|
+
end
|
147
|
+
@cmd_target_enabled['UNKNOWN'] = true
|
148
|
+
end
|
149
|
+
@tlm_target_enabled = tlm_target_enabled
|
150
|
+
if @tlm_target_enabled.nil?
|
151
|
+
@tlm_target_enabled = {}
|
152
|
+
@tlm_target_names.each do |target_name|
|
153
|
+
@tlm_target_enabled[target_name] = true
|
154
|
+
end
|
155
|
+
@tlm_target_enabled['UNKNOWN'] = true
|
156
|
+
end
|
137
157
|
@connect_on_startup = connect_on_startup
|
138
158
|
@auto_reconnect = auto_reconnect
|
139
159
|
@reconnect_delay = reconnect_delay
|
@@ -178,6 +198,8 @@ module OpenC3
|
|
178
198
|
interface_or_router.target_names = @target_names.dup
|
179
199
|
interface_or_router.cmd_target_names = @cmd_target_names.dup
|
180
200
|
interface_or_router.tlm_target_names = @tlm_target_names.dup
|
201
|
+
interface_or_router.cmd_target_enabled = @cmd_target_enabled.dup
|
202
|
+
interface_or_router.tlm_target_enabled = @tlm_target_enabled.dup
|
181
203
|
interface_or_router.connect_on_startup = @connect_on_startup
|
182
204
|
interface_or_router.auto_reconnect = @auto_reconnect
|
183
205
|
interface_or_router.reconnect_delay = @reconnect_delay
|
@@ -208,6 +230,8 @@ module OpenC3
|
|
208
230
|
'target_names' => @target_names,
|
209
231
|
'cmd_target_names' => @cmd_target_names,
|
210
232
|
'tlm_target_names' => @tlm_target_names,
|
233
|
+
'cmd_target_enabled' => @cmd_target_enabled,
|
234
|
+
'tlm_target_enabled' => @tlm_target_enabled,
|
211
235
|
'connect_on_startup' => @connect_on_startup,
|
212
236
|
'auto_reconnect' => @auto_reconnect,
|
213
237
|
'reconnect_delay' => @reconnect_delay,
|
@@ -236,27 +260,59 @@ module OpenC3
|
|
236
260
|
target
|
237
261
|
end
|
238
262
|
|
263
|
+
def handle_enabled(parser)
|
264
|
+
if parser.parameters[1].nil?
|
265
|
+
return true
|
266
|
+
else
|
267
|
+
enabled = parser.parameters[1].to_s.upcase
|
268
|
+
if enabled == 'ENABLED'
|
269
|
+
return true
|
270
|
+
elsif enabled == 'DISABLED'
|
271
|
+
return false
|
272
|
+
else
|
273
|
+
raise parser.error("MAP_TARGET enabled state must be ENABLED or DISABLED.", usage)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
239
278
|
# Handles Interface/Router specific configuration keywords
|
240
279
|
def handle_config(parser, keyword, parameters)
|
241
280
|
case keyword
|
242
281
|
when 'MAP_TARGET'
|
243
|
-
|
282
|
+
usage = "#{keyword} <Target Name> <ENABLED/DISABLED>"
|
283
|
+
parser.verify_num_parameters(1, 2, usage)
|
244
284
|
target_name = parameters[0].upcase
|
245
|
-
|
246
|
-
|
247
|
-
|
285
|
+
enabled = handle_enabled(parser)
|
286
|
+
|
287
|
+
if target_name != 'UNKNOWN'
|
288
|
+
@target_names << target_name unless @target_names.include?(target_name)
|
289
|
+
@cmd_target_names << target_name unless @cmd_target_names.include?(target_name)
|
290
|
+
@tlm_target_names << target_name unless @tlm_target_names.include?(target_name)
|
291
|
+
end
|
292
|
+
@cmd_target_enabled[target_name] = enabled
|
293
|
+
@tlm_target_enabled[target_name] = enabled
|
248
294
|
|
249
295
|
when 'MAP_CMD_TARGET'
|
250
|
-
parser.verify_num_parameters(1,
|
296
|
+
parser.verify_num_parameters(1, 2, "#{keyword} <Target Name> <ENABLED/DISABLED>")
|
251
297
|
target_name = parameters[0].upcase
|
252
|
-
|
253
|
-
|
298
|
+
enabled = handle_enabled(parser)
|
299
|
+
|
300
|
+
if target_name != 'UNKNOWN'
|
301
|
+
@target_names << target_name unless @target_names.include?(target_name)
|
302
|
+
@cmd_target_names << target_name unless @cmd_target_names.include?(target_name)
|
303
|
+
end
|
304
|
+
@cmd_target_enabled[target_name] = enabled
|
254
305
|
|
255
306
|
when 'MAP_TLM_TARGET'
|
256
|
-
parser.verify_num_parameters(1,
|
307
|
+
parser.verify_num_parameters(1, 2, "#{keyword} <Target Name> <ENABLED/DISABLED>")
|
257
308
|
target_name = parameters[0].upcase
|
258
|
-
|
259
|
-
|
309
|
+
enabled = handle_enabled(parser)
|
310
|
+
|
311
|
+
if target_name != 'UNKNOWN'
|
312
|
+
@target_names << target_name unless @target_names.include?(target_name)
|
313
|
+
@tlm_target_names << target_name unless @tlm_target_names.include?(target_name)
|
314
|
+
end
|
315
|
+
@tlm_target_enabled[target_name] = enabled
|
260
316
|
|
261
317
|
when 'DONT_CONNECT'
|
262
318
|
parser.verify_num_parameters(0, 0, "#{keyword}")
|
@@ -434,7 +490,7 @@ module OpenC3
|
|
434
490
|
microservice.update
|
435
491
|
end
|
436
492
|
|
437
|
-
def map_target(target_name, cmd_only: false, tlm_only: false, unmap_old: true)
|
493
|
+
def map_target(target_name, cmd_only: false, tlm_only: false, unmap_old: true, cmd_enabled: true, tlm_enabled: true)
|
438
494
|
if cmd_only and tlm_only
|
439
495
|
cmd_only = false
|
440
496
|
tlm_only = false
|
@@ -458,6 +514,8 @@ module OpenC3
|
|
458
514
|
@target_names << target_name unless @target_names.include?(target_name)
|
459
515
|
@cmd_target_names << target_name unless @cmd_target_names.include?(target_name) or tlm_only
|
460
516
|
@tlm_target_names << target_name unless @tlm_target_names.include?(target_name) or cmd_only
|
517
|
+
@cmd_target_enabled[target_name] = cmd_enabled if not cmd_enabled.nil? and @cmd_target_names.include?(target_name)
|
518
|
+
@tlm_target_enabled[target_name] = tlm_enabled if not tlm_enabled.nil? and @tlm_target_names.include?(target_name)
|
461
519
|
update()
|
462
520
|
|
463
521
|
# Respawn the microservice
|
@@ -37,7 +37,7 @@ module OpenC3
|
|
37
37
|
json = {'type' => METADATA_TYPE, 'start' => start}
|
38
38
|
json['stop'] = stop if stop
|
39
39
|
notification = {
|
40
|
-
'data' => JSON.generate(json),
|
40
|
+
'data' => JSON.generate(json, allow_nan: true),
|
41
41
|
'kind' => kind,
|
42
42
|
'type' => 'calendar',
|
43
43
|
}
|
@@ -118,7 +118,7 @@ module OpenC3
|
|
118
118
|
validate(update: update)
|
119
119
|
@updated_at = Time.now.to_nsec_from_epoch
|
120
120
|
MetadataModel.destroy(scope: @scope, start: update) if update
|
121
|
-
Store.zadd(@primary_key, @start, JSON.generate(as_json
|
121
|
+
Store.zadd(@primary_key, @start, JSON.generate(as_json, allow_nan: true))
|
122
122
|
if update
|
123
123
|
notify(kind: 'updated')
|
124
124
|
else
|
@@ -67,8 +67,8 @@ module OpenC3
|
|
67
67
|
'name' => @name,
|
68
68
|
'state' => @state,
|
69
69
|
'count' => @count,
|
70
|
-
'error' => @error.as_json(
|
71
|
-
'custom' => @custom.as_json(
|
70
|
+
'error' => @error.as_json(),
|
71
|
+
'custom' => @custom.as_json(),
|
72
72
|
'plugin' => @plugin,
|
73
73
|
'updated_at' => @updated_at
|
74
74
|
}
|
data/lib/openc3/models/model.rb
CHANGED
@@ -46,7 +46,7 @@ module OpenC3
|
|
46
46
|
def self.get(primary_key, name:)
|
47
47
|
json = store.hget(primary_key, name)
|
48
48
|
if json
|
49
|
-
return JSON.parse(json, :
|
49
|
+
return JSON.parse(json, allow_nan: true, create_additions: true)
|
50
50
|
else
|
51
51
|
return nil
|
52
52
|
end
|
@@ -61,7 +61,7 @@ module OpenC3
|
|
61
61
|
def self.all(primary_key)
|
62
62
|
hash = store.hgetall(primary_key)
|
63
63
|
hash.each do |key, value|
|
64
|
-
hash[key] = JSON.parse(value, :
|
64
|
+
hash[key] = JSON.parse(value, allow_nan: true, create_additions: true)
|
65
65
|
end
|
66
66
|
hash
|
67
67
|
end
|
@@ -88,7 +88,7 @@ module OpenC3
|
|
88
88
|
|
89
89
|
# @return [Model] Model generated from the passed JSON
|
90
90
|
def self.from_json(json, scope:)
|
91
|
-
json = JSON.parse(json, :
|
91
|
+
json = JSON.parse(json, allow_nan: true, create_additions: true) if String === json
|
92
92
|
raise "json data is nil" if json.nil?
|
93
93
|
json[:scope] = scope
|
94
94
|
self.new(**json.transform_keys(&:to_sym), scope: scope)
|
@@ -159,7 +159,7 @@ module OpenC3
|
|
159
159
|
else
|
160
160
|
write_store = self.class.store
|
161
161
|
end
|
162
|
-
write_store.hset(@primary_key, @name, JSON.generate(self.as_json(
|
162
|
+
write_store.hset(@primary_key, @name, JSON.generate(self.as_json(), allow_nan: true))
|
163
163
|
end
|
164
164
|
|
165
165
|
# Alias for create(update: true)
|
@@ -37,7 +37,7 @@ module OpenC3
|
|
37
37
|
json = {'type' => NOTE_TYPE, 'start' => start}
|
38
38
|
json['stop'] = stop if stop
|
39
39
|
notification = {
|
40
|
-
'data' => JSON.generate(json),
|
40
|
+
'data' => JSON.generate(json, allow_nan: true),
|
41
41
|
'kind' => kind,
|
42
42
|
'type' => 'calendar',
|
43
43
|
}
|
@@ -101,7 +101,7 @@ module OpenC3
|
|
101
101
|
validate(update: update)
|
102
102
|
@updated_at = Time.now.to_nsec_from_epoch
|
103
103
|
NoteModel.destroy(scope: @scope, start: update) if update
|
104
|
-
Store.zadd(@primary_key, @start, JSON.generate(as_json
|
104
|
+
Store.zadd(@primary_key, @start, JSON.generate(as_json, allow_nan: true))
|
105
105
|
if update
|
106
106
|
notify(kind: 'updated')
|
107
107
|
else
|
@@ -133,7 +133,7 @@ module OpenC3
|
|
133
133
|
|
134
134
|
store_id = Integer(store_id) if store_id
|
135
135
|
model = PluginModel.new(name: gem_name, variables: variables, plugin_txt_lines: plugin_txt_lines, store_id: store_id, scope: scope)
|
136
|
-
result = model.as_json(
|
136
|
+
result = model.as_json()
|
137
137
|
result['existing_plugin_txt_lines'] = existing_plugin_txt_lines if existing_plugin_txt_lines and not process_existing and existing_plugin_txt_lines != result['plugin_txt_lines']
|
138
138
|
return result
|
139
139
|
ensure
|
@@ -293,7 +293,7 @@ module OpenC3
|
|
293
293
|
FileUtils.remove_entry_secure(temp_dir, true)
|
294
294
|
tf.unlink if tf
|
295
295
|
end
|
296
|
-
return plugin_model.as_json(
|
296
|
+
return plugin_model.as_json()
|
297
297
|
end
|
298
298
|
|
299
299
|
def initialize(
|
@@ -313,7 +313,12 @@ module OpenC3
|
|
313
313
|
end
|
314
314
|
|
315
315
|
def create(update: false, force: false, queued: false)
|
316
|
-
|
316
|
+
if not update and not @name.index("__")
|
317
|
+
existing_names = Set.new(self.class.names(scope: @scope))
|
318
|
+
counter = 0
|
319
|
+
counter += 1 while existing_names.include?("#{@name}__#{counter}")
|
320
|
+
@name = "#{@name}__#{counter}"
|
321
|
+
end
|
317
322
|
super(update: update, force: force, queued: queued)
|
318
323
|
end
|
319
324
|
|
@@ -389,7 +394,7 @@ module OpenC3
|
|
389
394
|
|
390
395
|
# Reinstall
|
391
396
|
def restore
|
392
|
-
plugin_hash = self.as_json(
|
397
|
+
plugin_hash = self.as_json()
|
393
398
|
OpenC3::PluginModel.install_phase2(plugin_hash, scope: @scope)
|
394
399
|
@destroyed = false
|
395
400
|
end
|
@@ -98,7 +98,7 @@ module OpenC3
|
|
98
98
|
def notify(kind:)
|
99
99
|
notification = {
|
100
100
|
'kind' => kind,
|
101
|
-
'data' => JSON.generate(as_json
|
101
|
+
'data' => JSON.generate(as_json, allow_nan: true),
|
102
102
|
}
|
103
103
|
QueueTopic.write_notification(notification, scope: @scope)
|
104
104
|
end
|
@@ -206,14 +206,14 @@ module OpenC3
|
|
206
206
|
end
|
207
207
|
verify_triggers()
|
208
208
|
@updated_at = Time.now.to_nsec_from_epoch
|
209
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json
|
209
|
+
Store.hset(@primary_key, @name, JSON.generate(as_json, allow_nan: true))
|
210
210
|
notify(kind: 'created')
|
211
211
|
end
|
212
212
|
|
213
213
|
def update
|
214
214
|
verify_triggers()
|
215
215
|
@updated_at = Time.now.to_nsec_from_epoch
|
216
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json
|
216
|
+
Store.hset(@primary_key, @name, JSON.generate(as_json, allow_nan: true))
|
217
217
|
# No notification as this is only called via reaction_controller which already notifies
|
218
218
|
end
|
219
219
|
|
@@ -241,7 +241,7 @@ module OpenC3
|
|
241
241
|
if @snooze > 0
|
242
242
|
@snoozed_until = Time.now.to_i + @snooze
|
243
243
|
@updated_at = Time.now.to_nsec_from_epoch
|
244
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json
|
244
|
+
Store.hset(@primary_key, @name, JSON.generate(as_json, allow_nan: true))
|
245
245
|
notify(kind: 'snoozed')
|
246
246
|
end
|
247
247
|
end
|
@@ -249,7 +249,7 @@ module OpenC3
|
|
249
249
|
def awaken
|
250
250
|
@snoozed_until = nil
|
251
251
|
@updated_at = Time.now.to_nsec_from_epoch
|
252
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json
|
252
|
+
Store.hset(@primary_key, @name, JSON.generate(as_json, allow_nan: true))
|
253
253
|
notify(kind: 'awakened')
|
254
254
|
end
|
255
255
|
|
@@ -272,7 +272,7 @@ module OpenC3
|
|
272
272
|
|
273
273
|
# @return [ReactionModel] Model generated from the passed JSON
|
274
274
|
def self.from_json(json, name:, scope:)
|
275
|
-
json = JSON.parse(json, :
|
275
|
+
json = JSON.parse(json, allow_nan: true, create_additions: true) if String === json
|
276
276
|
raise "json data is nil" if json.nil?
|
277
277
|
self.new(**json.transform_keys(&:to_sym), name: name, scope: scope)
|
278
278
|
end
|
@@ -282,7 +282,7 @@ module OpenC3
|
|
282
282
|
notification = {
|
283
283
|
'kind' => kind,
|
284
284
|
'type' => 'reaction',
|
285
|
-
'data' => JSON.generate(as_json
|
285
|
+
'data' => JSON.generate(as_json, allow_nan: true),
|
286
286
|
}
|
287
287
|
AutonomicTopic.write_notification(notification, scope: @scope)
|
288
288
|
end
|
@@ -45,7 +45,7 @@ module OpenC3
|
|
45
45
|
def self.all(scope: nil)
|
46
46
|
tools = Store.hgetall(PRIMARY_KEY)
|
47
47
|
tools.each do |key, value|
|
48
|
-
tools[key] = JSON.parse(value, :
|
48
|
+
tools[key] = JSON.parse(value, allow_nan: true, create_additions: true)
|
49
49
|
end
|
50
50
|
return tools
|
51
51
|
end
|