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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/ext/openc3/ext/crc/crc.c +1 -1
  3. data/lib/openc3/api/cmd_api.rb +1 -1
  4. data/lib/openc3/microservices/decom_microservice.rb +10 -2
  5. data/lib/openc3/microservices/reaction_microservice.rb +152 -81
  6. data/lib/openc3/microservices/timeline_microservice.rb +1 -1
  7. data/lib/openc3/microservices/trigger_group_microservice.rb +188 -118
  8. data/lib/openc3/migrations/20230615000000_autonomic.rb +86 -0
  9. data/lib/openc3/models/activity_model.rb +2 -4
  10. data/lib/openc3/models/microservice_model.rb +6 -2
  11. data/lib/openc3/models/model.rb +1 -3
  12. data/lib/openc3/models/reaction_model.rb +124 -119
  13. data/lib/openc3/models/scope_model.rb +15 -3
  14. data/lib/openc3/models/timeline_model.rb +1 -3
  15. data/lib/openc3/models/trigger_group_model.rb +16 -50
  16. data/lib/openc3/models/trigger_model.rb +86 -123
  17. data/lib/openc3/packets/json_packet.rb +2 -3
  18. data/lib/openc3/script/commands.rb +10 -0
  19. data/lib/openc3/script/script.rb +1 -0
  20. data/lib/openc3/top_level.rb +0 -12
  21. data/lib/openc3/utilities/authorization.rb +1 -1
  22. data/lib/openc3/utilities/bucket_require.rb +5 -1
  23. data/lib/openc3/utilities/bucket_utilities.rb +4 -1
  24. data/lib/openc3/utilities/cli_generator.rb +56 -4
  25. data/lib/openc3/utilities/ruby_lex_utils.rb +4 -0
  26. data/lib/openc3/version.rb +6 -6
  27. data/templates/plugin/README.md +54 -4
  28. data/templates/plugin/Rakefile +31 -3
  29. data/templates/tool_angular/.editorconfig +16 -0
  30. data/templates/tool_angular/.gitignore +44 -0
  31. data/templates/tool_angular/.vscode/extensions.json +4 -0
  32. data/templates/tool_angular/.vscode/launch.json +20 -0
  33. data/templates/tool_angular/.vscode/tasks.json +42 -0
  34. data/templates/tool_angular/angular.json +111 -0
  35. data/templates/tool_angular/extra-webpack.config.js +8 -0
  36. data/templates/tool_angular/package.json +47 -0
  37. data/templates/tool_angular/src/app/app-routing.module.ts +15 -0
  38. data/templates/tool_angular/src/app/app.component.html +31 -0
  39. data/templates/tool_angular/src/app/app.component.scss +26 -0
  40. data/templates/tool_angular/src/app/app.component.spec.ts +29 -0
  41. data/templates/tool_angular/src/app/app.component.ts +51 -0
  42. data/templates/tool_angular/src/app/app.module.ts +30 -0
  43. data/templates/tool_angular/src/app/custom-overlay-container.ts +17 -0
  44. data/templates/tool_angular/src/app/empty-route/empty-route.component.ts +7 -0
  45. data/templates/tool_angular/src/app/openc3-api.d.ts +1 -0
  46. data/templates/tool_angular/src/assets/.gitkeep +0 -0
  47. data/templates/tool_angular/src/environments/environment.prod.ts +3 -0
  48. data/templates/tool_angular/src/environments/environment.ts +16 -0
  49. data/templates/tool_angular/src/favicon.ico +0 -0
  50. data/templates/tool_angular/src/index.html +13 -0
  51. data/templates/tool_angular/src/main.single-spa.ts +40 -0
  52. data/templates/tool_angular/src/single-spa/asset-url.ts +12 -0
  53. data/templates/tool_angular/src/single-spa/single-spa-props.ts +8 -0
  54. data/templates/tool_angular/src/styles.scss +1 -0
  55. data/templates/tool_angular/tsconfig.app.json +13 -0
  56. data/templates/tool_angular/tsconfig.json +33 -0
  57. data/templates/tool_angular/tsconfig.spec.json +14 -0
  58. data/templates/tool_angular/yarn.lock +8080 -0
  59. data/templates/tool_react/.eslintrc +7 -0
  60. data/templates/tool_react/.gitignore +72 -0
  61. data/templates/tool_react/.prettierignore +8 -0
  62. data/templates/tool_react/babel.config.json +29 -0
  63. data/templates/tool_react/jest.config.js +12 -0
  64. data/templates/tool_react/package.json +53 -0
  65. data/templates/tool_react/src/openc3-tool_name.js +24 -0
  66. data/templates/tool_react/src/root.component.js +88 -0
  67. data/templates/tool_react/src/root.component.test.js +9 -0
  68. data/templates/tool_react/webpack.config.js +27 -0
  69. data/templates/tool_react/yarn.lock +6854 -0
  70. data/templates/tool_svelte/.gitignore +72 -0
  71. data/templates/tool_svelte/.prettierignore +8 -0
  72. data/templates/tool_svelte/babel.config.js +12 -0
  73. data/templates/tool_svelte/build/smui.css +5 -0
  74. data/templates/tool_svelte/jest.config.js +9 -0
  75. data/templates/tool_svelte/package.json +46 -0
  76. data/templates/tool_svelte/rollup.config.js +72 -0
  77. data/templates/tool_svelte/src/App.svelte +42 -0
  78. data/templates/tool_svelte/src/App.test.js +9 -0
  79. data/templates/tool_svelte/src/services/api.js +92 -0
  80. data/templates/tool_svelte/src/services/axios.js +85 -0
  81. data/templates/tool_svelte/src/services/cable.js +65 -0
  82. data/templates/tool_svelte/src/services/config-parser.js +199 -0
  83. data/templates/tool_svelte/src/services/openc3-api.js +647 -0
  84. data/templates/tool_svelte/src/theme/_smui-theme.scss +25 -0
  85. data/templates/tool_svelte/src/tool_name.js +17 -0
  86. data/templates/tool_svelte/yarn.lock +5052 -0
  87. data/templates/tool_vue/.browserslistrc +16 -0
  88. data/templates/tool_vue/.env.standalone +1 -0
  89. data/templates/tool_vue/.eslintrc.js +43 -0
  90. data/templates/tool_vue/.gitignore +2 -0
  91. data/templates/tool_vue/.nycrc +3 -0
  92. data/templates/tool_vue/.prettierrc.js +5 -0
  93. data/templates/tool_vue/babel.config.json +11 -0
  94. data/templates/tool_vue/jsconfig.json +6 -0
  95. data/templates/tool_vue/package.json +52 -0
  96. data/templates/tool_vue/src/App.vue +15 -0
  97. data/templates/tool_vue/src/main.js +38 -0
  98. data/templates/tool_vue/src/router.js +29 -0
  99. data/templates/tool_vue/src/tools/tool_name/tool_name.vue +63 -0
  100. data/templates/tool_vue/vue.config.js +30 -0
  101. data/templates/tool_vue/yarn.lock +9145 -0
  102. data/templates/widget/package.json +9 -9
  103. data/templates/widget/yarn.lock +77 -73
  104. 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 "invalid group: #{name} not found"
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 "failed to delete #{name} triggers: #{triggers}"
63
+ raise TriggerGroupError.new "group '#{name}' has dependent triggers: #{triggers}"
70
64
  end
71
65
  end
72
66
 
73
- attr_reader :name, :scope, :color, :updated_at
67
+ attr_reader :name, :scope, :updated_at
74
68
 
75
- def initialize(name:, scope:, color: nil, updated_at: nil)
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 "invalid name: '#{name}' can not include an underscore '_'"
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 update_color(color: nil)
92
- if color.nil?
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
- def update
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 "(TriggerGroupModel :: #{@name})"
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
- model.destroy if model
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.create_mini_id
57
- time = (Time.now.to_f * 10_000_000).to_i
58
- jitter = rand(10_000_000)
59
- key = "#{jitter}#{time}".to_i.to_s(36)
60
- return "TV0-#{key}"
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 "invalid operation group: #{group} trigger: #{name} not found"
90
+ raise TriggerInputError.new "trigger #{group}:#{name} does not exist"
86
91
  end
87
92
  unless model.dependents.empty?
88
- raise TriggerError.new "failed to delete #{name} dependents: #{model.dependents}"
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
- model.notify(kind: 'deleted')
101
+ # No notification as this is only called via trigger_controller which already notifies
97
102
  end
98
103
 
99
- def validate_operand(operand:)
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: #{operand['type']} must be of type: #{operand_types}"
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 contain type: #{operand}"
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
- if operand['target'].nil? || operand['packet'].nil? || operand['raw'].nil?
113
- raise TriggerInputError.new "invalid operand must contain target, packet, item, and raw: #{operand}"
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
- unless operator.is_a?(String)
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 @roots.empty? && match_operators.include?(operator)
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 pair: '#{operator}' must be of type: #{trigger_operators}"
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 type: #{operators}"
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 "exsisting Trigger found: #{@name}"
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
- notify(kind: 'updated')
211
+ # No notification as this is only called via trigger_controller which already notifies
224
212
  end
225
213
 
226
- def enable
227
- @state = true
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 disable
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 activate
241
- @active = true
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 "(TriggerModel :: #{@name} :: #{group} :: #{@description})"
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
- 'active' => @active,
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
- value = @json_hash[name]
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:
@@ -38,6 +38,7 @@ require 'openc3/script/plugins'
38
38
  require 'openc3/utilities/authentication'
39
39
 
40
40
  $api_server = nil
41
+ $script_runner_api_server = nil
41
42
  $disconnect = false
42
43
  $openc3_scope = ENV['OPENC3_SCOPE'] || 'DEFAULT'
43
44
  $openc3_in_cluster = false
@@ -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("Current role is invalid for '#{permission}' permission")
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 Exception
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)