openc3 5.9.0 → 5.10.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.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- 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'
|