openc3 5.9.0 → 5.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openc3/accessors/binary_accessor.rb +5 -2
- data/lib/openc3/api/limits_api.rb +7 -23
- data/lib/openc3/api/target_api.rb +11 -8
- data/lib/openc3/api/tlm_api.rb +29 -38
- data/lib/openc3/microservices/decom_microservice.rb +5 -1
- data/lib/openc3/models/auth_model.rb +18 -6
- data/lib/openc3/models/cvt_model.rb +113 -50
- data/lib/openc3/models/interface_model.rb +2 -0
- data/lib/openc3/models/microservice_status_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +2 -0
- data/lib/openc3/models/target_model.rb +45 -1
- data/lib/openc3/models/tool_model.rb +2 -0
- data/lib/openc3/models/widget_model.rb +2 -0
- data/lib/openc3/packets/structure.rb +2 -2
- data/lib/openc3/packets/structure_item.rb +7 -24
- data/lib/openc3/script/api_shared.rb +45 -48
- data/lib/openc3/script/web_socket_api.rb +2 -2
- data/lib/openc3/system/target.rb +3 -3
- data/lib/openc3/top_level.rb +1 -1
- data/lib/openc3/utilities/authentication.rb +0 -1
- data/lib/openc3/utilities/aws_bucket.rb +4 -0
- data/lib/openc3/utilities/local_mode.rb +1 -1
- data/lib/openc3/utilities/store_autoload.rb +5 -5
- data/lib/openc3/version.rb +5 -5
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_react/package.json +1 -1
- data/templates/tool_svelte/src/services/openc3-api.js +174 -174
- data/templates/tool_vue/package.json +2 -2
- data/templates/widget/package.json +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c37c79f2062a5921e13c3370ce281c443b9abba929ca36f152df7cd1bcea92e
|
4
|
+
data.tar.gz: 643d74e05f61eb9016eaefbe5dca61316939e3d4e063fcf4150423cee4d95474
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25285376d600c16a3d0b6d485a359998fda7226fc3781f639cdde992370291fa7d23b0ce6ca89e02ddcf4e6386dd596839ed4d8c704003b893e37e726ed1a7e4
|
7
|
+
data.tar.gz: 3ae81b7ea67047a8e23cfb161aeb77b4e7224e44b2c9c1dc4fa2dd78cb06eae50710b0a5c882cfcaf8da9e0214b6b96e517ec2a6af0b7671f5b8e8a0dc1448fe
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
# This file contains the implementation of the BinaryAccessor class.
|
@@ -280,7 +280,10 @@ module OpenC3
|
|
280
280
|
|
281
281
|
if upper_bound > lower_bound
|
282
282
|
# Combine bytes into a FixNum
|
283
|
-
temp_data[1..temp_upper].each_byte
|
283
|
+
temp_data[1..temp_upper].each_byte do |temp_value|
|
284
|
+
temp = temp << 8
|
285
|
+
temp = temp + temp_value
|
286
|
+
end
|
284
287
|
end
|
285
288
|
|
286
289
|
# Shift off unwanted bits at end
|
@@ -172,7 +172,7 @@ module OpenC3
|
|
172
172
|
|
173
173
|
TargetModel.set_packet(target_name, packet_name, packet, scope: scope)
|
174
174
|
|
175
|
-
message = "Disabling Limits
|
175
|
+
message = "Disabling Limits for '#{target_name} #{packet_name} #{item_name}'"
|
176
176
|
Logger.info(message, scope: scope)
|
177
177
|
|
178
178
|
event = { type: :LIMITS_ENABLE_STATE, target_name: target_name, packet_name: packet_name,
|
@@ -344,11 +344,11 @@ module OpenC3
|
|
344
344
|
if action == :enable
|
345
345
|
enabled = true
|
346
346
|
item['limits']['enabled'] = true
|
347
|
-
message = "Enabling Limits
|
347
|
+
message = "Enabling Limits for '#{target_name} #{packet_name} #{item_name}'"
|
348
348
|
elsif action == :disable
|
349
349
|
enabled = false
|
350
350
|
item['limits'].delete('enabled')
|
351
|
-
message = "Disabling Limits
|
351
|
+
message = "Disabling Limits for '#{target_name} #{packet_name} #{item_name}'"
|
352
352
|
end
|
353
353
|
Logger.info(message, scope: scope)
|
354
354
|
|
@@ -373,26 +373,10 @@ module OpenC3
|
|
373
373
|
# @param item_name [String] item name
|
374
374
|
# @param scope [String] scope
|
375
375
|
# @return Hash The requested item based on the packet name
|
376
|
-
def _get_item(target_name, packet_name, item_name, scope:)
|
377
|
-
|
378
|
-
if packet_name == 'LATEST'
|
379
|
-
|
380
|
-
TargetModel.packets(target_name, scope: scope).each do |packet|
|
381
|
-
item = packet['items'].find { |item| item['name'] == item_name }
|
382
|
-
if item
|
383
|
-
hash = CvtModel.get(target_name: target_name, packet_name: packet['packet_name'], scope: scope)
|
384
|
-
if hash['PACKET_TIMESECONDS'] && hash['PACKET_TIMESECONDS'] > latest
|
385
|
-
latest = hash['PACKET_TIMESECONDS']
|
386
|
-
requested_item = item
|
387
|
-
end
|
388
|
-
end
|
389
|
-
end
|
390
|
-
raise "Item '#{target_name} LATEST #{item_name}' does not exist" if latest == -1
|
391
|
-
else
|
392
|
-
# Determine if this item exists, it will raise appropriate errors if not
|
393
|
-
requested_item = TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
|
394
|
-
end
|
395
|
-
return requested_item
|
376
|
+
def _get_item(target_name, packet_name, item_name, cache_timeout: 0.1, scope:)
|
377
|
+
# Determine if this item exists, it will raise appropriate errors if not
|
378
|
+
packet_name = CvtModel.determine_latest_packet_for_item(target_name, item_name, cache_timeout: cache_timeout, scope: $openc3_scope) if packet_name == 'LATEST'
|
379
|
+
return TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
|
396
380
|
end
|
397
381
|
end
|
398
382
|
end
|
@@ -26,19 +26,22 @@ module OpenC3
|
|
26
26
|
module Api
|
27
27
|
WHITELIST ||= []
|
28
28
|
WHITELIST.concat([
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
'get_target_names',
|
30
|
+
'get_target_list', # DEPRECATED
|
31
|
+
'get_target',
|
32
|
+
'get_target_interfaces',
|
33
|
+
'get_all_target_info', # DEPRECATED
|
34
|
+
])
|
34
35
|
|
35
36
|
# Returns the list of all target names
|
36
37
|
#
|
37
38
|
# @return [Array<String>] All target names
|
38
|
-
def
|
39
|
+
def get_target_names(scope: $openc3_scope, token: $openc3_token)
|
39
40
|
authorize(permission: 'tlm', scope: scope, token: token)
|
40
41
|
TargetModel.names(scope: scope)
|
41
42
|
end
|
43
|
+
# get_target_list is DEPRECATED
|
44
|
+
alias get_target_list get_target_names
|
42
45
|
|
43
46
|
# Gets the full target hash
|
44
47
|
#
|
@@ -57,7 +60,7 @@ module OpenC3
|
|
57
60
|
authorize(permission: 'system', scope: scope, token: token)
|
58
61
|
info = []
|
59
62
|
interfaces = InterfaceModel.all(scope: scope)
|
60
|
-
|
63
|
+
get_target_names(scope: scope, token: token).each do |target_name|
|
61
64
|
interface_names = []
|
62
65
|
interfaces.each do |name, interface|
|
63
66
|
if interface['target_names'].include? target_name
|
@@ -76,7 +79,7 @@ module OpenC3
|
|
76
79
|
def get_all_target_info(scope: $openc3_scope, token: $openc3_token)
|
77
80
|
authorize(permission: 'system', scope: scope, token: token)
|
78
81
|
info = []
|
79
|
-
|
82
|
+
get_target_names(scope: scope, token: token).each do |target_name|
|
80
83
|
cmd_cnt = 0
|
81
84
|
packets = TargetModel.packets(target_name, type: :CMD, scope: scope)
|
82
85
|
packets.each do |packet|
|
data/lib/openc3/api/tlm_api.rb
CHANGED
@@ -66,30 +66,30 @@ module OpenC3
|
|
66
66
|
# @param args [String|Array<String>] See the description for calling style
|
67
67
|
# @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
|
68
68
|
# @return [Object] The telemetry value formatted as requested
|
69
|
-
def tlm(*args, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
|
70
|
-
target_name, packet_name, item_name = tlm_process_args(args, 'tlm', scope: scope)
|
69
|
+
def tlm(*args, type: :CONVERTED, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
70
|
+
target_name, packet_name, item_name = tlm_process_args(args, 'tlm', cache_timeout: cache_timeout, scope: scope)
|
71
71
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
72
|
-
CvtModel.get_item(target_name, packet_name, item_name, type: type.intern, scope: scope)
|
72
|
+
CvtModel.get_item(target_name, packet_name, item_name, type: type.intern, cache_timeout: cache_timeout, scope: scope)
|
73
73
|
end
|
74
74
|
|
75
75
|
# @deprecated Use tlm with type: :RAW
|
76
|
-
def tlm_raw(*args, scope: $openc3_scope, token: $openc3_token)
|
77
|
-
tlm(*args, type: :RAW, scope: scope, token: token)
|
76
|
+
def tlm_raw(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
77
|
+
tlm(*args, type: :RAW, cache_timeout: cache_timeout, scope: scope, token: token)
|
78
78
|
end
|
79
79
|
|
80
80
|
# @deprecated Use tlm with type: :FORMATTED
|
81
|
-
def tlm_formatted(*args, scope: $openc3_scope, token: $openc3_token)
|
82
|
-
tlm(*args, type: :FORMATTED, scope: scope, token: token)
|
81
|
+
def tlm_formatted(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
82
|
+
tlm(*args, type: :FORMATTED, cache_timeout: cache_timeout, scope: scope, token: token)
|
83
83
|
end
|
84
84
|
|
85
85
|
# @deprecated Use tlm with type: :WITH_UNITS
|
86
|
-
def tlm_with_units(*args, scope: $openc3_scope, token: $openc3_token)
|
87
|
-
tlm(*args, type: :WITH_UNITS, scope: scope, token: token)
|
86
|
+
def tlm_with_units(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
87
|
+
tlm(*args, type: :WITH_UNITS, cache_timeout: cache_timeout, scope: scope, token: token)
|
88
88
|
end
|
89
89
|
|
90
90
|
# @deprecated Use tlm with type:
|
91
|
-
def tlm_variable(*args, scope: $openc3_scope, token: $openc3_token)
|
92
|
-
tlm(*args[0..-2], type: args[-1].intern, scope: scope, token: token)
|
91
|
+
def tlm_variable(*args, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
92
|
+
tlm(*args[0..-2], type: args[-1].intern, cache_timeout: cache_timeout, scope: scope, token: token)
|
93
93
|
end
|
94
94
|
|
95
95
|
# Set a telemetry item in the current value table.
|
@@ -227,7 +227,7 @@ module OpenC3
|
|
227
227
|
# @return [Array<String, Object, Symbol|nil>] Returns an Array consisting
|
228
228
|
# of [item name, item value, item limits state] where the item limits
|
229
229
|
# state can be one of {OpenC3::Limits::LIMITS_STATES}
|
230
|
-
def get_tlm_packet(target_name, packet_name, stale_time: 30, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
|
230
|
+
def get_tlm_packet(target_name, packet_name, stale_time: 30, type: :CONVERTED, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
231
231
|
target_name = target_name.upcase
|
232
232
|
packet_name = packet_name.upcase
|
233
233
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
@@ -235,8 +235,8 @@ module OpenC3
|
|
235
235
|
t = _validate_tlm_type(type)
|
236
236
|
raise ArgumentError, "Unknown type '#{type}' for #{target_name} #{packet_name}" if t.nil?
|
237
237
|
items = packet['items'].map { | item | item['name'].upcase }
|
238
|
-
cvt_items = items.map { | item |
|
239
|
-
current_values = CvtModel.get_tlm_values(cvt_items, stale_time: stale_time, scope: scope)
|
238
|
+
cvt_items = items.map { | item | [target_name, packet_name, item, type] }
|
239
|
+
current_values = CvtModel.get_tlm_values(cvt_items, stale_time: stale_time, cache_timeout: cache_timeout, scope: scope)
|
240
240
|
items.zip(current_values).map { | item , values | [item, values[0], values[1]]}
|
241
241
|
end
|
242
242
|
|
@@ -250,25 +250,26 @@ module OpenC3
|
|
250
250
|
# @return [Array<Object, Symbol>]
|
251
251
|
# Array consisting of the item value and limits state
|
252
252
|
# given as symbols such as :RED, :YELLOW, :STALE
|
253
|
-
def get_tlm_values(items, stale_time: 30, scope: $openc3_scope, token: $openc3_token)
|
253
|
+
def get_tlm_values(items, stale_time: 30, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
254
254
|
if !items.is_a?(Array) || !items[0].is_a?(String)
|
255
255
|
raise ArgumentError, "items must be array of strings: ['TGT__PKT__ITEM__TYPE', ...]"
|
256
256
|
end
|
257
|
+
packets = []
|
258
|
+
cvt_items = []
|
257
259
|
items.each_with_index do |item, index|
|
258
|
-
|
260
|
+
item_upcase = item.to_s.upcase
|
261
|
+
target_name, packet_name, item_name, value_type = item_upcase.split('__')
|
259
262
|
raise ArgumentError, "items must be formatted as TGT__PKT__ITEM__TYPE" if target_name.nil? || packet_name.nil? || item_name.nil? || value_type.nil?
|
260
|
-
|
261
|
-
packet_name = packet_name.upcase
|
262
|
-
item_name = item_name.upcase
|
263
|
-
value_type = value_type.upcase
|
264
|
-
if packet_name == 'LATEST'
|
265
|
-
_, packet_name, _ = tlm_process_args([target_name, packet_name, item_name], 'get_tlm_values', scope: scope) # Figure out which packet is LATEST
|
266
|
-
end
|
263
|
+
packet_name = CvtModel.determine_latest_packet_for_item(target_name, item_name, cache_timeout: cache_timeout, scope: scope) if packet_name == 'LATEST'
|
267
264
|
# Change packet_name in case of LATEST and ensure upcase
|
268
|
-
|
265
|
+
cvt_items[index] = [target_name, packet_name, item_name, value_type]
|
266
|
+
packets << [target_name, packet_name]
|
267
|
+
end
|
268
|
+
packets.uniq!
|
269
|
+
packets.each do |target_name, packet_name|
|
269
270
|
authorize(permission: 'tlm', target_name: target_name, packet_name: packet_name, scope: scope, token: token)
|
270
271
|
end
|
271
|
-
CvtModel.get_tlm_values(
|
272
|
+
CvtModel.get_tlm_values(cvt_items, stale_time: stale_time, cache_timeout: cache_timeout, scope: scope)
|
272
273
|
end
|
273
274
|
|
274
275
|
# Returns an array of all the telemetry packet hashes
|
@@ -429,7 +430,7 @@ module OpenC3
|
|
429
430
|
return nil
|
430
431
|
end
|
431
432
|
|
432
|
-
def tlm_process_args(args, method_name, scope: $openc3_scope, token: $openc3_token)
|
433
|
+
def tlm_process_args(args, method_name, cache_timeout: 0.1, scope: $openc3_scope, token: $openc3_token)
|
433
434
|
case args.length
|
434
435
|
when 1
|
435
436
|
target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
|
@@ -444,19 +445,9 @@ module OpenC3
|
|
444
445
|
target_name = target_name.upcase
|
445
446
|
packet_name = packet_name.upcase
|
446
447
|
item_name = item_name.upcase
|
448
|
+
|
447
449
|
if packet_name == 'LATEST'
|
448
|
-
|
449
|
-
TargetModel.packets(target_name, scope: scope).each do |packet|
|
450
|
-
item = packet['items'].find { |item| item['name'] == item_name }
|
451
|
-
if item
|
452
|
-
hash = CvtModel.get(target_name: target_name, packet_name: packet['packet_name'], scope: scope)
|
453
|
-
if hash['PACKET_TIMESECONDS'] && hash['PACKET_TIMESECONDS'] > latest
|
454
|
-
latest = hash['PACKET_TIMESECONDS']
|
455
|
-
packet_name = packet['packet_name']
|
456
|
-
end
|
457
|
-
end
|
458
|
-
end
|
459
|
-
raise "Item '#{target_name} LATEST #{item_name}' does not exist" if latest == -1
|
450
|
+
packet_name = CvtModel.determine_latest_packet_for_item(target_name, item_name, cache_timeout: cache_timeout, scope: scope)
|
460
451
|
else
|
461
452
|
# Determine if this item exists, it will raise appropriate errors if not
|
462
453
|
TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
|
@@ -115,7 +115,11 @@ module OpenC3
|
|
115
115
|
def limits_change_callback(packet, item, old_limits_state, value, log_change)
|
116
116
|
return if @cancel_thread
|
117
117
|
packet_time = packet.packet_time
|
118
|
-
|
118
|
+
if value
|
119
|
+
message = "#{packet.target_name} #{packet.packet_name} #{item.name} = #{value} is #{item.limits.state}"
|
120
|
+
else
|
121
|
+
message = "#{packet.target_name} #{packet.packet_name} #{item.name} is disabled"
|
122
|
+
end
|
119
123
|
message << " (#{packet.packet_time.sys.formatted})" if packet_time
|
120
124
|
|
121
125
|
time_nsec = packet_time ? packet_time.to_nsec_from_epoch : Time.now.to_nsec_from_epoch
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'digest'
|
@@ -28,6 +28,12 @@ module OpenC3
|
|
28
28
|
PRIMARY_KEY = 'OPENC3__TOKEN'
|
29
29
|
SERVICE_KEY = 'OPENC3__SERVICE__TOKEN'
|
30
30
|
|
31
|
+
TOKEN_CACHE_TIMEOUT = 5
|
32
|
+
@@token_cache = nil
|
33
|
+
@@token_cache_time = nil
|
34
|
+
@@service_token_cache = nil
|
35
|
+
@@service_token_cache_time = nil
|
36
|
+
|
31
37
|
def self.is_set?(key = PRIMARY_KEY)
|
32
38
|
Store.exists(key) == 1
|
33
39
|
end
|
@@ -36,15 +42,21 @@ module OpenC3
|
|
36
42
|
return false if token.nil? or token.empty?
|
37
43
|
|
38
44
|
token_hash = hash(token)
|
39
|
-
return true if
|
45
|
+
return true if @@token_cache and (Time.now - @@token_cache_time) < TOKEN_CACHE_TIMEOUT and @@token_cache == token_hash
|
46
|
+
return true if @@service_token_cache and (Time.now - @@service_token_cache_time) < TOKEN_CACHE_TIMEOUT and @@service_token_cache == token_hash and permission != 'admin'
|
47
|
+
|
48
|
+
@@token_cache = Store.get(PRIMARY_KEY)
|
49
|
+
@@token_cache_time = Time.now
|
50
|
+
return true if @@token_cache == token_hash
|
40
51
|
|
41
|
-
|
42
|
-
|
52
|
+
@@service_token_cache = Store.get(SERVICE_KEY)
|
53
|
+
@@service_token_cache_time = @@token_cache_time
|
54
|
+
if ENV['OPENC3_SERVICE_PASSWORD'] and hash(ENV['OPENC3_SERVICE_PASSWORD']) != @@service_token_cache
|
43
55
|
set_hash = hash(ENV['OPENC3_SERVICE_PASSWORD'])
|
44
56
|
OpenC3::Store.set(SERVICE_KEY, set_hash)
|
45
|
-
|
57
|
+
@@service_token_cache = set_hash
|
46
58
|
end
|
47
|
-
return true if
|
59
|
+
return true if @@service_token_cache == token_hash and permission != 'admin'
|
48
60
|
return false
|
49
61
|
end
|
50
62
|
|
@@ -25,6 +25,9 @@ require 'openc3/models/target_model'
|
|
25
25
|
|
26
26
|
module OpenC3
|
27
27
|
class CvtModel
|
28
|
+
@@packet_cache = {}
|
29
|
+
@@override_cache = {}
|
30
|
+
|
28
31
|
VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED, :WITH_UNITS]
|
29
32
|
def self.build_json_from_packet(packet)
|
30
33
|
packet.decom
|
@@ -32,24 +35,39 @@ module OpenC3
|
|
32
35
|
|
33
36
|
# Delete the current value table for a target
|
34
37
|
def self.del(target_name:, packet_name:, scope: $openc3_scope)
|
35
|
-
|
38
|
+
key = "#{scope}__tlm__#{target_name}"
|
39
|
+
tgt_pkt_key = key + "__#{packet_name}"
|
40
|
+
@@packet_cache[tgt_pkt_key] = nil
|
41
|
+
Store.hdel(key, packet_name)
|
36
42
|
end
|
37
43
|
|
38
44
|
# Set the current value table for a target, packet
|
39
45
|
def self.set(hash, target_name:, packet_name:, scope: $openc3_scope)
|
40
|
-
|
46
|
+
packet_json = JSON.generate(hash.as_json(:allow_nan => true))
|
47
|
+
key = "#{scope}__tlm__#{target_name}"
|
48
|
+
tgt_pkt_key = key + "__#{packet_name}"
|
49
|
+
@@packet_cache[tgt_pkt_key] = [Time.now, hash]
|
50
|
+
Store.hset(key, packet_name, packet_json)
|
41
51
|
end
|
42
52
|
|
43
53
|
# Get the hash for packet in the CVT
|
44
|
-
|
45
|
-
|
54
|
+
# Note: Does not apply overrides
|
55
|
+
def self.get(target_name:, packet_name:, cache_timeout: 0.1, scope: $openc3_scope)
|
56
|
+
key = "#{scope}__tlm__#{target_name}"
|
57
|
+
tgt_pkt_key = key + "__#{packet_name}"
|
58
|
+
cache_time, hash = @@packet_cache[tgt_pkt_key]
|
59
|
+
now = Time.now
|
60
|
+
return hash if hash and (now - cache_time) < cache_timeout
|
61
|
+
packet = Store.hget(key, packet_name)
|
46
62
|
raise "Packet '#{target_name} #{packet_name}' does not exist" unless packet
|
47
|
-
JSON.parse(packet, :allow_nan => true, :create_additions => true)
|
63
|
+
hash = JSON.parse(packet, :allow_nan => true, :create_additions => true)
|
64
|
+
@@packet_cache[tgt_pkt_key] = [now, hash]
|
65
|
+
hash
|
48
66
|
end
|
49
67
|
|
50
68
|
# Set an item in the current value table
|
51
69
|
def self.set_item(target_name, packet_name, item_name, value, type:, scope: $openc3_scope)
|
52
|
-
hash = get(target_name: target_name, packet_name: packet_name, scope: scope)
|
70
|
+
hash = get(target_name: target_name, packet_name: packet_name, cache_timeout: 0.0, scope: scope)
|
53
71
|
case type
|
54
72
|
when :WITH_UNITS
|
55
73
|
hash["#{item_name}__U"] = value.to_s # WITH_UNITS should always be a string
|
@@ -67,33 +85,13 @@ module OpenC3
|
|
67
85
|
else
|
68
86
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
69
87
|
end
|
70
|
-
|
88
|
+
set(hash, target_name: target_name, packet_name: packet_name, scope: scope)
|
71
89
|
end
|
72
90
|
|
73
91
|
# Get an item from the current value table
|
74
|
-
def self.get_item(target_name, packet_name, item_name, type:, scope: $openc3_scope)
|
75
|
-
|
76
|
-
|
77
|
-
case type
|
78
|
-
when :WITH_UNITS
|
79
|
-
types = ["#{item_name}__U", "#{item_name}__F", "#{item_name}__C", item_name]
|
80
|
-
override_key = "#{item_name}__U"
|
81
|
-
when :FORMATTED
|
82
|
-
types = ["#{item_name}__F", "#{item_name}__C", item_name]
|
83
|
-
override_key = "#{item_name}__F"
|
84
|
-
when :CONVERTED
|
85
|
-
types = ["#{item_name}__C", item_name]
|
86
|
-
override_key = "#{item_name}__C"
|
87
|
-
when :RAW
|
88
|
-
types = [item_name]
|
89
|
-
else
|
90
|
-
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
91
|
-
end
|
92
|
-
overrides = Store.hget("#{scope}__override__#{target_name}", packet_name)
|
93
|
-
if overrides
|
94
|
-
result = JSON.parse(overrides, :allow_nan => true, :create_additions => true)[override_key]
|
95
|
-
return result if result
|
96
|
-
end
|
92
|
+
def self.get_item(target_name, packet_name, item_name, type:, cache_timeout: 0.1, scope: $openc3_scope)
|
93
|
+
result, types = self._handle_item_override(target_name, packet_name, item_name, type: type, cache_timeout: cache_timeout, scope: scope)
|
94
|
+
return result if result
|
97
95
|
hash = get(target_name: target_name, packet_name: packet_name, scope: scope)
|
98
96
|
hash.values_at(*types).each do |result|
|
99
97
|
if result
|
@@ -111,18 +109,19 @@ module OpenC3
|
|
111
109
|
# @param items [Array<String>] Items to return. Must be formatted as TGT__PKT__ITEM__TYPE
|
112
110
|
# @param stale_time [Integer] Time in seconds from Time.now that value will be marked stale
|
113
111
|
# @return [Array] Array of values
|
114
|
-
def self.get_tlm_values(items, stale_time: 30, scope: $openc3_scope)
|
115
|
-
now = Time.now
|
112
|
+
def self.get_tlm_values(items, stale_time: 30, cache_timeout: 0.1, scope: $openc3_scope)
|
113
|
+
now = Time.now
|
116
114
|
results = []
|
117
115
|
lookups = []
|
118
116
|
packet_lookup = {}
|
119
117
|
overrides = {}
|
120
118
|
# First generate a lookup hash of all the items represented so we can query the CVT
|
121
|
-
items.each { |item| _parse_item(lookups, overrides, item, scope: scope) }
|
119
|
+
items.each { |item| _parse_item(now, lookups, overrides, item, cache_timeout: cache_timeout, scope: scope) }
|
122
120
|
|
121
|
+
now = now.to_f
|
123
122
|
lookups.each do |target_packet_key, target_name, packet_name, value_keys|
|
124
123
|
unless packet_lookup[target_packet_key]
|
125
|
-
packet_lookup[target_packet_key] = get(target_name: target_name, packet_name: packet_name, scope: scope)
|
124
|
+
packet_lookup[target_packet_key] = get(target_name: target_name, packet_name: packet_name, cache_timeout: cache_timeout, scope: scope)
|
126
125
|
end
|
127
126
|
hash = packet_lookup[target_packet_key]
|
128
127
|
item_result = []
|
@@ -153,6 +152,7 @@ module OpenC3
|
|
153
152
|
end
|
154
153
|
|
155
154
|
# Return all the overrides
|
155
|
+
# Note: Does not use cache to benefit from hgetall
|
156
156
|
def self.overrides(scope: $openc3_scope)
|
157
157
|
overrides = []
|
158
158
|
TargetModel.names(scope: scope).each do |target_name|
|
@@ -207,6 +207,9 @@ module OpenC3
|
|
207
207
|
else
|
208
208
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
209
209
|
end
|
210
|
+
|
211
|
+
tgt_pkt_key = "#{scope}__tlm__#{target_name}__#{packet_name}"
|
212
|
+
@@override_cache[tgt_pkt_key] = [Time.now, hash]
|
210
213
|
Store.hset("#{scope}__override__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
|
211
214
|
end
|
212
215
|
|
@@ -232,6 +235,9 @@ module OpenC3
|
|
232
235
|
else
|
233
236
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
234
237
|
end
|
238
|
+
|
239
|
+
tgt_pkt_key = "#{scope}__tlm__#{target_name}__#{packet_name}"
|
240
|
+
@@override_cache[tgt_pkt_key] = [Time.now, hash]
|
235
241
|
if hash.empty?
|
236
242
|
Store.hdel("#{scope}__override__#{target_name}", packet_name)
|
237
243
|
else
|
@@ -239,16 +245,78 @@ module OpenC3
|
|
239
245
|
end
|
240
246
|
end
|
241
247
|
|
248
|
+
def self.determine_latest_packet_for_item(target_name, item_name, cache_timeout: 0.1, scope: $openc3_scope)
|
249
|
+
item_map = TargetModel.get_item_to_packet_map(target_name, scope: scope)
|
250
|
+
packet_names = item_map[item_name]
|
251
|
+
raise "Item '#{target_name} LATEST #{item_name}' does not exist for scope: #{scope}" unless packet_names
|
252
|
+
|
253
|
+
latest = -1
|
254
|
+
latest_packet_name = nil
|
255
|
+
packet_names.each do |packet_name|
|
256
|
+
hash = get(target_name: target_name, packet_name: packet_name, cache_timeout: cache_timeout, scope: scope)
|
257
|
+
if hash['PACKET_TIMESECONDS'] && hash['PACKET_TIMESECONDS'] > latest
|
258
|
+
latest = hash['PACKET_TIMESECONDS']
|
259
|
+
latest_packet_name = packet_name
|
260
|
+
end
|
261
|
+
end
|
262
|
+
raise "Item '#{target_name} LATEST #{item_name}' does not exist for scope: #{scope}" if latest == -1
|
263
|
+
return latest_packet_name
|
264
|
+
end
|
265
|
+
|
242
266
|
# PRIVATE METHODS
|
243
267
|
|
268
|
+
def self._handle_item_override(target_name, packet_name, item_name, type:, cache_timeout:, scope: $openc3_scope)
|
269
|
+
override_key = item_name
|
270
|
+
types = []
|
271
|
+
case type
|
272
|
+
when :WITH_UNITS
|
273
|
+
types = ["#{item_name}__U", "#{item_name}__F", "#{item_name}__C", item_name]
|
274
|
+
override_key = "#{item_name}__U"
|
275
|
+
when :FORMATTED
|
276
|
+
types = ["#{item_name}__F", "#{item_name}__C", item_name]
|
277
|
+
override_key = "#{item_name}__F"
|
278
|
+
when :CONVERTED
|
279
|
+
types = ["#{item_name}__C", item_name]
|
280
|
+
override_key = "#{item_name}__C"
|
281
|
+
when :RAW
|
282
|
+
types = [item_name]
|
283
|
+
else
|
284
|
+
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
285
|
+
end
|
286
|
+
|
287
|
+
tgt_pkt_key = "#{scope}__tlm__#{target_name}__#{packet_name}"
|
288
|
+
overrides = _get_overrides(Time.now, tgt_pkt_key, {}, target_name, packet_name, cache_timeout: cache_timeout, scope: scope)
|
289
|
+
result = overrides[override_key]
|
290
|
+
return result, types if result
|
291
|
+
return nil, types
|
292
|
+
end
|
293
|
+
|
294
|
+
def self._get_overrides(now, tgt_pkt_key, overrides, target_name, packet_name, cache_timeout:, scope:)
|
295
|
+
cache_time, hash = @@override_cache[tgt_pkt_key]
|
296
|
+
if hash and (now - cache_time) < cache_timeout
|
297
|
+
overrides[tgt_pkt_key] = hash
|
298
|
+
return hash
|
299
|
+
end
|
300
|
+
override_data = Store.hget("#{scope}__override__#{target_name}", packet_name)
|
301
|
+
if override_data
|
302
|
+
hash = JSON.parse(override_data, :allow_nan => true, :create_additions => true)
|
303
|
+
overrides[tgt_pkt_key] = hash
|
304
|
+
else
|
305
|
+
hash = {}
|
306
|
+
overrides[tgt_pkt_key] = {}
|
307
|
+
end
|
308
|
+
@@override_cache[tgt_pkt_key] = [now, hash] # always update
|
309
|
+
return hash
|
310
|
+
end
|
311
|
+
|
244
312
|
# parse item and update lookups with packet_name and target_name and keys
|
245
313
|
# return an ordered array of hash with keys
|
246
|
-
def self._parse_item(lookups, overrides, item, scope:)
|
247
|
-
target_name, packet_name, item_name, value_type = item
|
314
|
+
def self._parse_item(now, lookups, overrides, item, cache_timeout:, scope:)
|
315
|
+
target_name, packet_name, item_name, value_type = item
|
248
316
|
|
249
317
|
# We build lookup keys by including all the less formatted types to gracefully degrade lookups
|
250
318
|
# This allows the user to specify WITH_UNITS and if there is no conversions it will simply return the RAW value
|
251
|
-
case value_type
|
319
|
+
case value_type.to_s
|
252
320
|
when 'RAW'
|
253
321
|
keys = [item_name]
|
254
322
|
when 'CONVERTED'
|
@@ -260,20 +328,15 @@ module OpenC3
|
|
260
328
|
else
|
261
329
|
raise "Unknown value type '#{value_type}'"
|
262
330
|
end
|
263
|
-
|
331
|
+
|
264
332
|
# Check the overrides cache for this target / packet
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
end
|
273
|
-
if overrides[tgt_pkt_key][keys[0]]
|
274
|
-
# Set the result as a Hash to distingish it from the key array and from an overridden Array value
|
275
|
-
keys = {'value' => overrides[tgt_pkt_key][keys[0]]}
|
276
|
-
end
|
333
|
+
tgt_pkt_key = "#{scope}__tlm__#{target_name}__#{packet_name}"
|
334
|
+
_get_overrides(now, tgt_pkt_key, overrides, target_name, packet_name, cache_timeout: cache_timeout, scope: scope) unless overrides[tgt_pkt_key]
|
335
|
+
|
336
|
+
# Set the result as a Hash to distinguish it from the key array and from an overridden Array value
|
337
|
+
value = overrides[tgt_pkt_key][keys[0]]
|
338
|
+
keys = {'value' => value} if value
|
339
|
+
|
277
340
|
lookups << [tgt_pkt_key, target_name, packet_name, keys]
|
278
341
|
end
|
279
342
|
end
|
@@ -389,6 +389,8 @@ module OpenC3
|
|
389
389
|
status_model = RouterStatusModel.get_model(name: @name, scope: @scope)
|
390
390
|
end
|
391
391
|
status_model.destroy if status_model
|
392
|
+
rescue Exception => error
|
393
|
+
Logger.error("Error undeploying interface/router model #{@name} in scope #{@scope} due to #{error}")
|
392
394
|
end
|
393
395
|
|
394
396
|
def unmap_target(target_name, cmd_only: false, tlm_only: false)
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/models/model'
|