openc3 5.8.1 → 5.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/ext/openc3/ext/crc/crc.c +1 -1
- data/lib/openc3/api/cmd_api.rb +1 -1
- data/lib/openc3/microservices/decom_microservice.rb +10 -2
- data/lib/openc3/microservices/reaction_microservice.rb +152 -81
- data/lib/openc3/microservices/timeline_microservice.rb +1 -1
- data/lib/openc3/microservices/trigger_group_microservice.rb +188 -118
- data/lib/openc3/migrations/20230615000000_autonomic.rb +86 -0
- data/lib/openc3/models/activity_model.rb +2 -4
- data/lib/openc3/models/microservice_model.rb +6 -2
- data/lib/openc3/models/model.rb +1 -3
- data/lib/openc3/models/reaction_model.rb +124 -119
- data/lib/openc3/models/scope_model.rb +15 -3
- data/lib/openc3/models/timeline_model.rb +1 -3
- data/lib/openc3/models/trigger_group_model.rb +16 -50
- data/lib/openc3/models/trigger_model.rb +86 -123
- data/lib/openc3/packets/json_packet.rb +2 -3
- data/lib/openc3/script/commands.rb +10 -0
- data/lib/openc3/script/script.rb +1 -0
- data/lib/openc3/top_level.rb +0 -12
- data/lib/openc3/utilities/authorization.rb +1 -1
- data/lib/openc3/utilities/bucket_require.rb +5 -1
- data/lib/openc3/utilities/bucket_utilities.rb +4 -1
- data/lib/openc3/utilities/cli_generator.rb +56 -4
- data/lib/openc3/utilities/ruby_lex_utils.rb +4 -0
- data/lib/openc3/version.rb +6 -6
- data/templates/plugin/README.md +54 -4
- data/templates/plugin/Rakefile +31 -3
- data/templates/tool_angular/.editorconfig +16 -0
- data/templates/tool_angular/.gitignore +44 -0
- data/templates/tool_angular/.vscode/extensions.json +4 -0
- data/templates/tool_angular/.vscode/launch.json +20 -0
- data/templates/tool_angular/.vscode/tasks.json +42 -0
- data/templates/tool_angular/angular.json +111 -0
- data/templates/tool_angular/extra-webpack.config.js +8 -0
- data/templates/tool_angular/package.json +47 -0
- data/templates/tool_angular/src/app/app-routing.module.ts +15 -0
- data/templates/tool_angular/src/app/app.component.html +31 -0
- data/templates/tool_angular/src/app/app.component.scss +26 -0
- data/templates/tool_angular/src/app/app.component.spec.ts +29 -0
- data/templates/tool_angular/src/app/app.component.ts +51 -0
- data/templates/tool_angular/src/app/app.module.ts +30 -0
- data/templates/tool_angular/src/app/custom-overlay-container.ts +17 -0
- data/templates/tool_angular/src/app/empty-route/empty-route.component.ts +7 -0
- data/templates/tool_angular/src/app/openc3-api.d.ts +1 -0
- data/templates/tool_angular/src/assets/.gitkeep +0 -0
- data/templates/tool_angular/src/environments/environment.prod.ts +3 -0
- data/templates/tool_angular/src/environments/environment.ts +16 -0
- data/templates/tool_angular/src/favicon.ico +0 -0
- data/templates/tool_angular/src/index.html +13 -0
- data/templates/tool_angular/src/main.single-spa.ts +40 -0
- data/templates/tool_angular/src/single-spa/asset-url.ts +12 -0
- data/templates/tool_angular/src/single-spa/single-spa-props.ts +8 -0
- data/templates/tool_angular/src/styles.scss +1 -0
- data/templates/tool_angular/tsconfig.app.json +13 -0
- data/templates/tool_angular/tsconfig.json +33 -0
- data/templates/tool_angular/tsconfig.spec.json +14 -0
- data/templates/tool_angular/yarn.lock +8080 -0
- data/templates/tool_react/.eslintrc +7 -0
- data/templates/tool_react/.gitignore +72 -0
- data/templates/tool_react/.prettierignore +8 -0
- data/templates/tool_react/babel.config.json +29 -0
- data/templates/tool_react/jest.config.js +12 -0
- data/templates/tool_react/package.json +53 -0
- data/templates/tool_react/src/openc3-tool_name.js +24 -0
- data/templates/tool_react/src/root.component.js +88 -0
- data/templates/tool_react/src/root.component.test.js +9 -0
- data/templates/tool_react/webpack.config.js +27 -0
- data/templates/tool_react/yarn.lock +6854 -0
- data/templates/tool_svelte/.gitignore +72 -0
- data/templates/tool_svelte/.prettierignore +8 -0
- data/templates/tool_svelte/babel.config.js +12 -0
- data/templates/tool_svelte/build/smui.css +5 -0
- data/templates/tool_svelte/jest.config.js +9 -0
- data/templates/tool_svelte/package.json +46 -0
- data/templates/tool_svelte/rollup.config.js +72 -0
- data/templates/tool_svelte/src/App.svelte +42 -0
- data/templates/tool_svelte/src/App.test.js +9 -0
- data/templates/tool_svelte/src/services/api.js +92 -0
- data/templates/tool_svelte/src/services/axios.js +85 -0
- data/templates/tool_svelte/src/services/cable.js +65 -0
- data/templates/tool_svelte/src/services/config-parser.js +199 -0
- data/templates/tool_svelte/src/services/openc3-api.js +647 -0
- data/templates/tool_svelte/src/theme/_smui-theme.scss +25 -0
- data/templates/tool_svelte/src/tool_name.js +17 -0
- data/templates/tool_svelte/yarn.lock +5052 -0
- data/templates/tool_vue/.browserslistrc +16 -0
- data/templates/tool_vue/.env.standalone +1 -0
- data/templates/tool_vue/.eslintrc.js +43 -0
- data/templates/tool_vue/.gitignore +2 -0
- data/templates/tool_vue/.nycrc +3 -0
- data/templates/tool_vue/.prettierrc.js +5 -0
- data/templates/tool_vue/babel.config.json +11 -0
- data/templates/tool_vue/jsconfig.json +6 -0
- data/templates/tool_vue/package.json +52 -0
- data/templates/tool_vue/src/App.vue +15 -0
- data/templates/tool_vue/src/main.js +38 -0
- data/templates/tool_vue/src/router.js +29 -0
- data/templates/tool_vue/src/tools/tool_name/tool_name.vue +63 -0
- data/templates/tool_vue/vue.config.js +30 -0
- data/templates/tool_vue/yarn.lock +9145 -0
- data/templates/widget/package.json +9 -9
- data/templates/widget/yarn.lock +77 -73
- metadata +76 -2
|
@@ -26,14 +26,8 @@ require 'openc3/topics/autonomic_topic'
|
|
|
26
26
|
|
|
27
27
|
module OpenC3
|
|
28
28
|
class TriggerGroupError < StandardError; end
|
|
29
|
-
|
|
30
29
|
class TriggerGroupInputError < TriggerGroupError; end
|
|
31
30
|
|
|
32
|
-
# INPUT:
|
|
33
|
-
# {
|
|
34
|
-
# "name": "FOOBAR",
|
|
35
|
-
# "color": "#000000",
|
|
36
|
-
# }
|
|
37
31
|
class TriggerGroupModel < Model
|
|
38
32
|
PRIMARY_KEY = '__TRIGGER__GROUP'.freeze
|
|
39
33
|
|
|
@@ -59,67 +53,39 @@ module OpenC3
|
|
|
59
53
|
def self.delete(name:, scope:)
|
|
60
54
|
model = self.get(name: name, scope: scope)
|
|
61
55
|
if model.nil?
|
|
62
|
-
raise TriggerGroupInputError.new "
|
|
56
|
+
raise TriggerGroupInputError.new "group '#{name}' does not exist"
|
|
63
57
|
end
|
|
64
58
|
triggers = TriggerModel.names(scope: scope, group: name)
|
|
65
59
|
if triggers.empty?
|
|
66
60
|
Store.hdel("#{scope}#{PRIMARY_KEY}", name)
|
|
67
61
|
model.notify(kind: 'deleted')
|
|
68
62
|
else
|
|
69
|
-
raise TriggerGroupError.new "
|
|
63
|
+
raise TriggerGroupError.new "group '#{name}' has dependent triggers: #{triggers}"
|
|
70
64
|
end
|
|
71
65
|
end
|
|
72
66
|
|
|
73
|
-
attr_reader :name, :scope, :
|
|
67
|
+
attr_reader :name, :scope, :updated_at
|
|
74
68
|
|
|
75
|
-
def initialize(name:, scope:,
|
|
76
|
-
if name.nil? || scope.nil?
|
|
77
|
-
raise GroupTriggerInputError.new "name, or scope must not be nil"
|
|
78
|
-
end
|
|
69
|
+
def initialize(name:, scope:, updated_at: nil)
|
|
79
70
|
unless name.is_a?(String)
|
|
80
|
-
raise TriggerGroupInputError.new "invalid name: '#{name}'"
|
|
71
|
+
raise TriggerGroupInputError.new "invalid group name: '#{name}'"
|
|
81
72
|
end
|
|
82
73
|
if name.include?('_')
|
|
83
|
-
raise TriggerGroupInputError.new "
|
|
74
|
+
raise TriggerGroupInputError.new "group name '#{name}' can not include an underscore"
|
|
84
75
|
end
|
|
85
76
|
super("#{scope}#{PRIMARY_KEY}", name: name, scope: scope)
|
|
86
77
|
@microservice_name = "#{scope}__TRIGGER_GROUP__#{name}"
|
|
87
|
-
update_color(color: color)
|
|
88
78
|
@updated_at = updated_at
|
|
89
79
|
end
|
|
90
80
|
|
|
91
|
-
def
|
|
92
|
-
|
|
93
|
-
color = '#%06x' % (rand * 0xffffff)
|
|
94
|
-
end
|
|
95
|
-
valid_color = color =~ /[0-9a-fA-F]{6}/
|
|
96
|
-
if valid_color.nil?
|
|
97
|
-
raise TriggerGroupInputError.new "invalid color must be in hex format. #FF0000"
|
|
98
|
-
end
|
|
99
|
-
unless color.start_with?('#')
|
|
100
|
-
color = "##{color}"
|
|
101
|
-
end
|
|
102
|
-
@color = color
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def create
|
|
106
|
-
unless Store.hget(@primary_key, @name).nil?
|
|
107
|
-
raise TriggerGroupInputError.new "exsisting TriggerGroup found: #{@name}"
|
|
108
|
-
end
|
|
109
|
-
@updated_at = Time.now.to_nsec_from_epoch
|
|
110
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
81
|
+
def create(update: false)
|
|
82
|
+
super(update: update)
|
|
111
83
|
notify(kind: 'created')
|
|
112
84
|
end
|
|
113
85
|
|
|
114
|
-
|
|
115
|
-
@updated_at = Time.now.to_nsec_from_epoch
|
|
116
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
117
|
-
notify(kind: 'updated')
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# @return [String] generated from the TriggerGroupModel
|
|
86
|
+
# @return [String] generated from the TriggerModel
|
|
121
87
|
def to_s
|
|
122
|
-
return "
|
|
88
|
+
return "OpenC3::TriggerGroupModel:#{@scope}:#{@name})"
|
|
123
89
|
end
|
|
124
90
|
|
|
125
91
|
# @return [Hash] generated from the TriggerGroupModel
|
|
@@ -127,7 +93,6 @@ module OpenC3
|
|
|
127
93
|
return {
|
|
128
94
|
'name' => @name,
|
|
129
95
|
'scope' => @scope,
|
|
130
|
-
'color' => @color,
|
|
131
96
|
'updated_at' => @updated_at,
|
|
132
97
|
}
|
|
133
98
|
end
|
|
@@ -136,9 +101,7 @@ module OpenC3
|
|
|
136
101
|
def self.from_json(json, name:, scope:)
|
|
137
102
|
json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json
|
|
138
103
|
raise "json data is nil" if json.nil?
|
|
139
|
-
|
|
140
|
-
json.transform_keys!(&:to_sym)
|
|
141
|
-
self.new(**json, name: name, scope: scope)
|
|
104
|
+
self.new(**json.transform_keys(&:to_sym), name: name, scope: scope)
|
|
142
105
|
end
|
|
143
106
|
|
|
144
107
|
# @return [] update the redis stream / trigger topic that something has changed
|
|
@@ -173,15 +136,18 @@ module OpenC3
|
|
|
173
136
|
topics = ["#{@scope}__openc3_autonomic"]
|
|
174
137
|
if MicroserviceModel.get_model(name: @microservice_name, scope: @scope).nil?
|
|
175
138
|
create_microservice(topics: topics)
|
|
139
|
+
notify(kind: 'deployed')
|
|
176
140
|
end
|
|
177
141
|
end
|
|
178
142
|
|
|
179
143
|
def undeploy
|
|
180
144
|
if TriggerModel.names(scope: scope, group: name).empty?
|
|
181
145
|
model = MicroserviceModel.get_model(name: @microservice_name, scope: @scope)
|
|
182
|
-
|
|
146
|
+
if model
|
|
147
|
+
model.destroy
|
|
148
|
+
notify(kind: 'undeployed')
|
|
149
|
+
end
|
|
183
150
|
end
|
|
184
151
|
end
|
|
185
|
-
|
|
186
152
|
end
|
|
187
153
|
end
|
|
@@ -17,17 +17,18 @@
|
|
|
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'
|
|
24
24
|
require 'openc3/models/microservice_model'
|
|
25
25
|
require 'openc3/models/target_model'
|
|
26
|
+
require 'openc3/models/trigger_group_model'
|
|
27
|
+
require 'openc3/models/reaction_model'
|
|
26
28
|
require 'openc3/topics/autonomic_topic'
|
|
27
29
|
|
|
28
30
|
module OpenC3
|
|
29
31
|
class TriggerError < StandardError; end
|
|
30
|
-
|
|
31
32
|
class TriggerInputError < TriggerError; end
|
|
32
33
|
|
|
33
34
|
# INPUT:
|
|
@@ -38,6 +39,7 @@ module OpenC3
|
|
|
38
39
|
# "target": "INST",
|
|
39
40
|
# "packet": "ADCS",
|
|
40
41
|
# "item": "POSX",
|
|
42
|
+
# "valueType": "RAW",
|
|
41
43
|
# },
|
|
42
44
|
# "operator": ">",
|
|
43
45
|
# "right": {
|
|
@@ -51,13 +53,16 @@ module OpenC3
|
|
|
51
53
|
LIMIT_TYPE = 'limit'.freeze
|
|
52
54
|
FLOAT_TYPE = 'float'.freeze
|
|
53
55
|
STRING_TYPE = 'string'.freeze
|
|
56
|
+
REGEX_TYPE = 'regex'.freeze
|
|
54
57
|
TRIGGER_TYPE = 'trigger'.freeze
|
|
55
58
|
|
|
56
|
-
def self.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
def self.create_unique_name(group:, scope:)
|
|
60
|
+
trigger_names = self.names(group: group, scope: scope) # comes back sorted
|
|
61
|
+
num = 1 # Users count with 1
|
|
62
|
+
if trigger_names[-1]
|
|
63
|
+
num = trigger_names[-1][4..-1].to_i + 1
|
|
64
|
+
end
|
|
65
|
+
return "TRIG#{num}"
|
|
61
66
|
end
|
|
62
67
|
|
|
63
68
|
# @return [TriggerModel] Return the object with the name at
|
|
@@ -82,10 +87,10 @@ module OpenC3
|
|
|
82
87
|
def self.delete(name:, group:, scope:)
|
|
83
88
|
model = self.get(name: name, group: group, scope: scope)
|
|
84
89
|
if model.nil?
|
|
85
|
-
raise TriggerInputError.new "
|
|
90
|
+
raise TriggerInputError.new "trigger #{group}:#{name} does not exist"
|
|
86
91
|
end
|
|
87
92
|
unless model.dependents.empty?
|
|
88
|
-
raise TriggerError.new "
|
|
93
|
+
raise TriggerError.new "#{group}:#{name} has dependents: #{model.dependents}"
|
|
89
94
|
end
|
|
90
95
|
model.roots.each do | trigger |
|
|
91
96
|
trigger_model = self.get(name: trigger, group: group, scope: scope)
|
|
@@ -93,24 +98,67 @@ module OpenC3
|
|
|
93
98
|
trigger_model.update()
|
|
94
99
|
end
|
|
95
100
|
Store.hdel("#{scope}#{PRIMARY_KEY}#{group}", name)
|
|
96
|
-
|
|
101
|
+
# No notification as this is only called via trigger_controller which already notifies
|
|
97
102
|
end
|
|
98
103
|
|
|
99
|
-
|
|
104
|
+
attr_reader :name, :scope, :state, :group, :enabled, :left, :operator, :right, :dependents, :roots
|
|
105
|
+
|
|
106
|
+
def initialize(
|
|
107
|
+
name:,
|
|
108
|
+
scope:,
|
|
109
|
+
group:,
|
|
110
|
+
left:,
|
|
111
|
+
operator:,
|
|
112
|
+
right:,
|
|
113
|
+
state: false,
|
|
114
|
+
enabled: true,
|
|
115
|
+
dependents: nil,
|
|
116
|
+
updated_at: nil
|
|
117
|
+
)
|
|
118
|
+
super("#{scope}#{PRIMARY_KEY}#{group}", name: name, scope: scope)
|
|
119
|
+
@roots = []
|
|
120
|
+
@group = group
|
|
121
|
+
@state = state
|
|
122
|
+
@enabled = enabled
|
|
123
|
+
@left = validate_operand(operand: left)
|
|
124
|
+
@operator = validate_operator(operator: operator)
|
|
125
|
+
@right = validate_operand(operand: right, right: true)
|
|
126
|
+
@dependents = dependents
|
|
127
|
+
@updated_at = updated_at
|
|
128
|
+
selected_group = TriggerGroupModel.get(name: @group, scope: @scope)
|
|
129
|
+
if selected_group.nil?
|
|
130
|
+
raise TriggerInputError.new "failed to find group: '#{@group}'"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Modifiers for the trigger_controller update action
|
|
135
|
+
def left=(left)
|
|
136
|
+
@left = validate_operand(operand: left)
|
|
137
|
+
end
|
|
138
|
+
def right=(right)
|
|
139
|
+
@right = validate_operand(operand: right, right: true)
|
|
140
|
+
end
|
|
141
|
+
def operator=(operator)
|
|
142
|
+
@operator = validate_operator(operator: operator)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def validate_operand(operand:, right: false)
|
|
146
|
+
return operand if right and @operator.include?('CHANGE')
|
|
100
147
|
unless operand.is_a?(Hash)
|
|
101
148
|
raise TriggerInputError.new "invalid operand: #{operand}"
|
|
102
149
|
end
|
|
103
|
-
operand_types = [ITEM_TYPE, LIMIT_TYPE, FLOAT_TYPE, STRING_TYPE, TRIGGER_TYPE]
|
|
150
|
+
operand_types = [ITEM_TYPE, LIMIT_TYPE, FLOAT_TYPE, STRING_TYPE, REGEX_TYPE, TRIGGER_TYPE]
|
|
104
151
|
unless operand_types.include?(operand['type'])
|
|
105
|
-
raise TriggerInputError.new "invalid operand type
|
|
152
|
+
raise TriggerInputError.new "invalid operand, type '#{operand['type']}' must be one of #{operand_types}"
|
|
106
153
|
end
|
|
107
154
|
if operand[operand['type']].nil?
|
|
108
|
-
raise TriggerInputError.new "invalid operand must
|
|
155
|
+
raise TriggerInputError.new "invalid operand, type value '#{operand['type']}' must be a key: #{operand}"
|
|
109
156
|
end
|
|
110
157
|
case operand['type']
|
|
111
158
|
when ITEM_TYPE
|
|
112
|
-
|
|
113
|
-
|
|
159
|
+
# We don't need to check for 'item' because the above check already does it
|
|
160
|
+
if operand['target'].nil? || operand['packet'].nil? || operand['valueType'].nil?
|
|
161
|
+
raise TriggerInputError.new "invalid operand, must contain target, packet, item and valueType: #{operand}"
|
|
114
162
|
end
|
|
115
163
|
when TRIGGER_TYPE
|
|
116
164
|
@roots << operand[operand['type']]
|
|
@@ -119,85 +167,25 @@ module OpenC3
|
|
|
119
167
|
end
|
|
120
168
|
|
|
121
169
|
def validate_operator(operator:)
|
|
122
|
-
|
|
123
|
-
raise TriggerInputError.new "invalid operator: #{operator}"
|
|
124
|
-
end
|
|
125
|
-
operators = ['>', '<', '>=', '<=']
|
|
126
|
-
match_operators = ['==', '!=']
|
|
170
|
+
operators = ['>', '<', '>=', '<=', '==', '!=', 'CHANGES', 'DOES NOT CHANGE']
|
|
127
171
|
trigger_operators = ['AND', 'OR']
|
|
128
172
|
if @roots.empty? && operators.include?(operator)
|
|
129
173
|
return operator
|
|
130
|
-
elsif
|
|
131
|
-
return operator
|
|
132
|
-
elsif @roots.size() == 2 && trigger_operators.include?(operator)
|
|
174
|
+
elsif !@roots.empty? && trigger_operators.include?(operator)
|
|
133
175
|
return operator
|
|
134
176
|
elsif operators.include?(operator)
|
|
135
|
-
raise TriggerInputError.new "invalid operator
|
|
177
|
+
raise TriggerInputError.new "invalid operator for triggers: '#{operator}' must be one of #{trigger_operators}"
|
|
136
178
|
else
|
|
137
|
-
raise TriggerInputError.new "invalid operator: '#{operator}' must be of
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def validate_description(description:)
|
|
142
|
-
if description.nil?
|
|
143
|
-
left_type = @left['type']
|
|
144
|
-
right_type = @right['type']
|
|
145
|
-
return "#{@left[left_type]} #{@operator} #{@right[right_type]}"
|
|
146
|
-
end
|
|
147
|
-
unless description.is_a?(String)
|
|
148
|
-
raise TriggerInputError.new "invalid description: #{description}"
|
|
149
|
-
end
|
|
150
|
-
return description
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
attr_reader :name, :scope, :state, :group, :active, :left, :operator, :right, :dependents, :roots
|
|
154
|
-
|
|
155
|
-
#
|
|
156
|
-
def initialize(
|
|
157
|
-
name:,
|
|
158
|
-
scope:,
|
|
159
|
-
group:,
|
|
160
|
-
left:,
|
|
161
|
-
operator:,
|
|
162
|
-
right:,
|
|
163
|
-
state: false,
|
|
164
|
-
active: true,
|
|
165
|
-
description: nil,
|
|
166
|
-
dependents: nil,
|
|
167
|
-
updated_at: nil
|
|
168
|
-
)
|
|
169
|
-
if name.nil? || scope.nil? || group.nil? || left.nil? || operator.nil? || right.nil?
|
|
170
|
-
raise TriggerInputError.new "#{name}, #{scope}, #{group}, #{left}, #{operator}, or #{right} must not be nil"
|
|
179
|
+
raise TriggerInputError.new "invalid operator: '#{operator}' must be one of #{operators}"
|
|
171
180
|
end
|
|
172
|
-
super("#{scope}#{PRIMARY_KEY}#{group}", name: name, scope: scope)
|
|
173
|
-
@roots = []
|
|
174
|
-
@group = group
|
|
175
|
-
@state = state
|
|
176
|
-
@active = active
|
|
177
|
-
@left = validate_operand(operand: left)
|
|
178
|
-
@right = validate_operand(operand: right)
|
|
179
|
-
@operator = validate_operator(operator: operator)
|
|
180
|
-
@description = validate_description(description: description)
|
|
181
|
-
@dependents = dependents
|
|
182
|
-
@updated_at = updated_at
|
|
183
181
|
end
|
|
184
182
|
|
|
185
183
|
def verify_triggers
|
|
186
|
-
unless @group.is_a?(String)
|
|
187
|
-
raise TriggerInputError.new "invalid group: #{@group}"
|
|
188
|
-
end
|
|
189
|
-
selected_group = OpenC3::TriggerGroupModel.get(name: @group, scope: @scope)
|
|
190
|
-
if selected_group.nil?
|
|
191
|
-
raise TriggerGroupInputError.new "failed to find group: #{@group}"
|
|
192
|
-
end
|
|
193
184
|
@dependents = [] if @dependents.nil?
|
|
194
185
|
@roots.each do | trigger |
|
|
195
186
|
model = TriggerModel.get(name: trigger, group: @group, scope: @scope)
|
|
196
187
|
if model.nil?
|
|
197
|
-
raise TriggerInputError.new "failed to find dependent trigger: #{trigger}"
|
|
198
|
-
end
|
|
199
|
-
if model.group != @group
|
|
200
|
-
raise TriggerInputError.new "failed group dependent trigger: #{trigger}"
|
|
188
|
+
raise TriggerInputError.new "failed to find dependent trigger: '#{@group}:#{trigger}'"
|
|
201
189
|
end
|
|
202
190
|
unless model.dependents.include?(@name)
|
|
203
191
|
model.update_dependents(dependent: @name)
|
|
@@ -208,7 +196,7 @@ module OpenC3
|
|
|
208
196
|
|
|
209
197
|
def create
|
|
210
198
|
unless Store.hget(@primary_key, @name).nil?
|
|
211
|
-
raise TriggerInputError.new "
|
|
199
|
+
raise TriggerInputError.new "existing trigger found: '#{@name}'"
|
|
212
200
|
end
|
|
213
201
|
verify_triggers()
|
|
214
202
|
@updated_at = Time.now.to_nsec_from_epoch
|
|
@@ -220,40 +208,31 @@ module OpenC3
|
|
|
220
208
|
verify_triggers()
|
|
221
209
|
@updated_at = Time.now.to_nsec_from_epoch
|
|
222
210
|
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
223
|
-
|
|
211
|
+
# No notification as this is only called via trigger_controller which already notifies
|
|
224
212
|
end
|
|
225
213
|
|
|
226
|
-
def
|
|
227
|
-
@state =
|
|
214
|
+
def state=(value)
|
|
215
|
+
@state = value
|
|
228
216
|
@updated_at = Time.now.to_nsec_from_epoch
|
|
229
217
|
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
218
|
+
notify(kind: @state.to_s)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def notify_enable
|
|
222
|
+
@enabled = true
|
|
230
223
|
notify(kind: 'enabled')
|
|
231
224
|
end
|
|
232
225
|
|
|
233
|
-
def
|
|
226
|
+
def notify_disable
|
|
227
|
+
@enabled = false
|
|
234
228
|
@state = false
|
|
235
|
-
@updated_at = Time.now.to_nsec_from_epoch
|
|
236
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
237
229
|
notify(kind: 'disabled')
|
|
238
230
|
end
|
|
239
231
|
|
|
240
|
-
def
|
|
241
|
-
|
|
242
|
-
@updated_at = Time.now.to_nsec_from_epoch
|
|
243
|
-
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
244
|
-
notify(kind: 'activated')
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
def deactivate
|
|
248
|
-
@active = false
|
|
249
|
-
@state = false
|
|
232
|
+
def disable
|
|
233
|
+
notify_disable()
|
|
250
234
|
@updated_at = Time.now.to_nsec_from_epoch
|
|
251
235
|
Store.hset(@primary_key, @name, JSON.generate(as_json(:allow_nan => true)))
|
|
252
|
-
notify(kind: 'deactivated')
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
def modify
|
|
256
|
-
raise "TODO"
|
|
257
236
|
end
|
|
258
237
|
|
|
259
238
|
# ["#{@scope}__DECOM__{#{@target}}__#{@packet}"]
|
|
@@ -262,7 +241,7 @@ module OpenC3
|
|
|
262
241
|
if @left['type'] == ITEM_TYPE
|
|
263
242
|
topics["#{@scope}__DECOM__{#{left['target']}}__#{left['packet']}"] = 1
|
|
264
243
|
end
|
|
265
|
-
if @right['type'] == ITEM_TYPE
|
|
244
|
+
if @right and @right['type'] == ITEM_TYPE
|
|
266
245
|
topics["#{@scope}__DECOM__{#{right['target']}}__#{right['packet']}"] = 1
|
|
267
246
|
end
|
|
268
247
|
return topics.keys
|
|
@@ -278,7 +257,7 @@ module OpenC3
|
|
|
278
257
|
|
|
279
258
|
# @return [String] generated from the TriggerModel
|
|
280
259
|
def to_s
|
|
281
|
-
return "
|
|
260
|
+
return "OpenC3::TriggerModel:#{@scope}:#{group}:#{@name})"
|
|
282
261
|
end
|
|
283
262
|
|
|
284
263
|
# @return [Hash] generated from the TriggerModel
|
|
@@ -287,9 +266,8 @@ module OpenC3
|
|
|
287
266
|
'name' => @name,
|
|
288
267
|
'scope' => @scope,
|
|
289
268
|
'state' => @state,
|
|
290
|
-
'
|
|
269
|
+
'enabled' => @enabled,
|
|
291
270
|
'group' => @group,
|
|
292
|
-
'description' => @description,
|
|
293
271
|
'dependents' => @dependents,
|
|
294
272
|
'left' => @left,
|
|
295
273
|
'operator' => @operator,
|
|
@@ -302,9 +280,7 @@ module OpenC3
|
|
|
302
280
|
def self.from_json(json, name:, scope:)
|
|
303
281
|
json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json
|
|
304
282
|
raise "json data is nil" if json.nil?
|
|
305
|
-
|
|
306
|
-
json.transform_keys!(&:to_sym)
|
|
307
|
-
self.new(**json, name: name, scope: scope)
|
|
283
|
+
self.new(**json.transform_keys(&:to_sym), name: name, scope: scope)
|
|
308
284
|
end
|
|
309
285
|
|
|
310
286
|
# @return [] update the redis stream / trigger topic that something has changed
|
|
@@ -316,18 +292,5 @@ module OpenC3
|
|
|
316
292
|
}
|
|
317
293
|
AutonomicTopic.write_notification(notification, scope: @scope)
|
|
318
294
|
end
|
|
319
|
-
|
|
320
|
-
# @param [String] kind - the status such as "event" or "error"
|
|
321
|
-
# @param [String] message - an optional message to include in the event
|
|
322
|
-
def log(kind:, message: nil)
|
|
323
|
-
notification = {
|
|
324
|
-
'kind' => kind,
|
|
325
|
-
'type' => 'log',
|
|
326
|
-
'time' => Time.now.to_i,
|
|
327
|
-
'name' => @name,
|
|
328
|
-
}
|
|
329
|
-
notification['message'] = message unless message.nil?
|
|
330
|
-
AutonomicTopic.write_notification(notification, scope: @scope)
|
|
331
|
-
end
|
|
332
295
|
end
|
|
333
296
|
end
|
|
@@ -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'
|
|
@@ -110,8 +110,7 @@ module OpenC3
|
|
|
110
110
|
value = @json_hash["#{name}__C"]
|
|
111
111
|
return value if value
|
|
112
112
|
end
|
|
113
|
-
|
|
114
|
-
return value if value
|
|
113
|
+
return @json_hash[name]
|
|
115
114
|
end
|
|
116
115
|
|
|
117
116
|
def read_with_limits_state(name, value_type = :CONVERTED, reduced_type = nil)
|
|
@@ -168,6 +168,16 @@ module OpenC3
|
|
|
168
168
|
_cmd('cmd_raw_no_checks', nil, *args, **kwargs)
|
|
169
169
|
end
|
|
170
170
|
|
|
171
|
+
# Builds a command binary
|
|
172
|
+
#
|
|
173
|
+
# Accepts two different calling styles:
|
|
174
|
+
# build_command("TGT CMD with PARAM1 val, PARAM2 val")
|
|
175
|
+
# build_command('TGT','CMD',{'PARAM1'=>val,'PARAM2'=>val})
|
|
176
|
+
def build_command(*args, **kwargs)
|
|
177
|
+
extract_string_kwargs_to_args(args, kwargs)
|
|
178
|
+
$api_server.build_command(*args)
|
|
179
|
+
end
|
|
180
|
+
|
|
171
181
|
# Returns whether the specified command is hazardous
|
|
172
182
|
#
|
|
173
183
|
# Accepts two different calling styles:
|
data/lib/openc3/script/script.rb
CHANGED
data/lib/openc3/top_level.rb
CHANGED
|
@@ -349,17 +349,6 @@ module OpenC3
|
|
|
349
349
|
return log_file
|
|
350
350
|
end
|
|
351
351
|
|
|
352
|
-
# Catch fatal exceptions within the block
|
|
353
|
-
# This is intended to catch exceptions before the GUI is available
|
|
354
|
-
def self.catch_fatal_exception
|
|
355
|
-
yield
|
|
356
|
-
rescue Exception => error
|
|
357
|
-
unless SystemExit === error or SignalException === error
|
|
358
|
-
Logger.level = Logger::FATAL
|
|
359
|
-
OpenC3.handle_fatal_exception(error, false)
|
|
360
|
-
end
|
|
361
|
-
end
|
|
362
|
-
|
|
363
352
|
# Write a message to the Logger, write an exception file, and popup a GUI
|
|
364
353
|
# window if try_gui. Finally 'exit 1' is called to end the calling program.
|
|
365
354
|
#
|
|
@@ -369,7 +358,6 @@ module OpenC3
|
|
|
369
358
|
unless SystemExit === error or SignalException === error
|
|
370
359
|
$openc3_fatal_exception = error
|
|
371
360
|
self.write_exception_file(error)
|
|
372
|
-
Logger.level = Logger::FATAL
|
|
373
361
|
Logger.fatal "Fatal Exception! Exiting..."
|
|
374
362
|
Logger.fatal error.formatted
|
|
375
363
|
if $stdout != STDOUT
|
|
@@ -43,7 +43,7 @@ rescue LoadError
|
|
|
43
43
|
if $openc3_authorize
|
|
44
44
|
raise AuthError.new("Token is required") unless token
|
|
45
45
|
unless OpenC3::AuthModel.verify(token, permission: permission)
|
|
46
|
-
raise AuthError.new("
|
|
46
|
+
raise AuthError.new("Password is invalid for '#{permission}' permission")
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
@@ -39,6 +39,8 @@ OpenC3.disable_warnings do
|
|
|
39
39
|
@bucket_require_cache[args[0]] = true
|
|
40
40
|
return true
|
|
41
41
|
end
|
|
42
|
+
rescue LoadError => err
|
|
43
|
+
raise err
|
|
42
44
|
rescue Exception => err
|
|
43
45
|
raise LoadError, "#{err.class}:#{err.message}", err.backtrace
|
|
44
46
|
end
|
|
@@ -57,7 +59,9 @@ OpenC3.disable_warnings do
|
|
|
57
59
|
scope = $openc3_scope
|
|
58
60
|
end
|
|
59
61
|
OpenC3::BucketUtilities.bucket_load(*args, scope: scope)
|
|
60
|
-
rescue
|
|
62
|
+
rescue LoadError => err
|
|
63
|
+
raise err
|
|
64
|
+
rescue Exception => err
|
|
61
65
|
raise LoadError, "#{err.class}:#{err.message}", err.backtrace
|
|
62
66
|
end
|
|
63
67
|
end
|
|
@@ -31,17 +31,20 @@ module OpenC3
|
|
|
31
31
|
DIRECTORY_TIMESTAMP_FORMAT = "%Y%m%d"
|
|
32
32
|
|
|
33
33
|
def self.bucket_load(*args, scope: $openc3_scope)
|
|
34
|
+
scope = ENV['OPENC3_SCOPE'] unless scope
|
|
35
|
+
scope = 'DEFAULT' unless scope
|
|
34
36
|
path = args[0]
|
|
35
37
|
|
|
36
38
|
# Only support TARGET files
|
|
37
39
|
if path[0] == '/' or path.split('/')[0].to_s.upcase != path.split('/')[0]
|
|
38
|
-
raise LoadError
|
|
40
|
+
raise LoadError, "only relative TARGET files are allowed -- #{path}"
|
|
39
41
|
end
|
|
40
42
|
extension = File.extname(path)
|
|
41
43
|
path = path + '.rb' if extension == ""
|
|
42
44
|
|
|
43
45
|
# Retrieve the text of the script from S3
|
|
44
46
|
text = TargetFile.body(scope, path)
|
|
47
|
+
raise LoadError, "Bucket file #{path} not found for scope #{scope}" unless text
|
|
45
48
|
|
|
46
49
|
# Execute the script directly without instrumentation because we are doing require/load
|
|
47
50
|
Object.class_eval(text, path, 1)
|