openc3 5.8.1 → 5.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,92 @@
1
+ /*
2
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
3
+ # All Rights Reserved.
4
+ #
5
+ # This program is free software; you can modify and/or redistribute it
6
+ # under the terms of the GNU Affero General Public License
7
+ # as published by the Free Software Foundation; version 3 with
8
+ # attribution addendums as found in the LICENSE.txt
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+
15
+ # Modified by OpenC3, Inc.
16
+ # All changes Copyright 2022, OpenC3, Inc.
17
+ # All Rights Reserved
18
+ #
19
+ # This file may also be used under the terms of a commercial license
20
+ # if purchased from OpenC3, Inc.
21
+ */
22
+
23
+ import axios from './axios.js'
24
+
25
+ const request = async function (
26
+ method,
27
+ url,
28
+ { data, params = {}, headers, noAuth = false, noScope = false } = {}
29
+ ) {
30
+ if (!noAuth) {
31
+ try {
32
+ let refreshed = await OpenC3Auth.updateToken(
33
+ OpenC3Auth.defaultMinValidity
34
+ )
35
+ if (refreshed) {
36
+ OpenC3Auth.setTokens()
37
+ }
38
+ } catch (error) {
39
+ OpenC3Auth.login()
40
+ }
41
+ headers['Authorization'] = localStorage.openc3Token
42
+ }
43
+ if (!noScope && !params['scope']) {
44
+ params['scope'] = window.openc3Scope
45
+ }
46
+ return axios({
47
+ method,
48
+ url,
49
+ data,
50
+ params,
51
+ headers,
52
+ })
53
+ }
54
+
55
+ const acceptOnlyDefaultHeaders = {
56
+ Accept: 'application/json',
57
+ }
58
+
59
+ const fullDefaultHeaders = {
60
+ ...acceptOnlyDefaultHeaders,
61
+ 'Content-Type': 'application/json',
62
+ }
63
+
64
+ export default {
65
+ get: function (
66
+ path,
67
+ { params, headers = acceptOnlyDefaultHeaders, noScope, noAuth } = {}
68
+ ) {
69
+ return request('get', path, { params, headers, noScope, noAuth })
70
+ },
71
+
72
+ put: function (
73
+ path,
74
+ { data, params, headers = fullDefaultHeaders, noScope, noAuth } = {}
75
+ ) {
76
+ return request('put', path, { data, params, headers, noScope, noAuth })
77
+ },
78
+
79
+ post: function (
80
+ path,
81
+ { data, params, headers = fullDefaultHeaders, noScope, noAuth } = {}
82
+ ) {
83
+ return request('post', path, { data, params, headers, noScope, noAuth })
84
+ },
85
+
86
+ delete: function (
87
+ path,
88
+ { params, headers = acceptOnlyDefaultHeaders, noScope, noAuth } = {}
89
+ ) {
90
+ return request('delete', path, { params, headers, noScope, noAuth })
91
+ },
92
+ }
@@ -0,0 +1,85 @@
1
+ /*
2
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
3
+ # All Rights Reserved.
4
+ #
5
+ # This program is free software; you can modify and/or redistribute it
6
+ # under the terms of the GNU Affero General Public License
7
+ # as published by the Free Software Foundation; version 3 with
8
+ # attribution addendums as found in the LICENSE.txt
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+
15
+ # Modified by OpenC3, Inc.
16
+ # All changes Copyright 2022, OpenC3, Inc.
17
+ # All Rights Reserved
18
+ #
19
+ # This file may also be used under the terms of a commercial license
20
+ # if purchased from OpenC3, Inc.
21
+ */
22
+
23
+ import axios from 'axios'
24
+
25
+ const axiosInstance = axios.create({
26
+ baseURL: location.origin,
27
+ timeout: 60000,
28
+ params: {},
29
+ })
30
+
31
+ axiosInstance.interceptors.response.use(
32
+ (response) => response,
33
+ (error) => {
34
+ if (error.response) {
35
+ if (error.response.status === 401) {
36
+ OpenC3Auth.updateToken(OpenC3Auth.defaultMinValidity, true).then(
37
+ function (refreshed) {
38
+ if (refreshed) {
39
+ OpenC3Auth.setTokens()
40
+ }
41
+ }
42
+ )
43
+ }
44
+ // Individual tools can set 'Ignore-Errors' to an error code
45
+ // they potentially expect, e.g. '500', in which case we ignore it
46
+ // For example in CommandSender.vue:
47
+ // obs = this.api.cmd(targetName, commandName, paramList, {
48
+ // 'Ignore-Errors': '500',
49
+ // })
50
+ if (
51
+ error.response.headers['ignore-errors'] &&
52
+ error.response.headers['ignore-errors'].includes(
53
+ error.response.status.toString()
54
+ )
55
+ ) {
56
+ return Promise.reject(error)
57
+ }
58
+ let body = `HTTP ${error.response.status} - `
59
+ if (error.response?.statusText) {
60
+ body += `${error.response.statusText} `
61
+ }
62
+ if (error.response?.config?.data) {
63
+ body += `${error.response.config.data} `
64
+ }
65
+ if (error.response?.data?.message) {
66
+ body += `${error.response.data.message}`
67
+ } else if (error.response?.data?.exception) {
68
+ body += `${error.response.data.exception}`
69
+ } else if (error.response?.data?.error?.message) {
70
+ if (error.response.data.error.class) {
71
+ body += `${error.response.data.error.class} `
72
+ }
73
+ body += `${error.response.data.error.message}`
74
+ } else {
75
+ body += `${error.response?.data}`
76
+ }
77
+ alert(`Network error: ${body}`)
78
+ throw error
79
+ } else {
80
+ throw error
81
+ }
82
+ }
83
+ )
84
+
85
+ export default axiosInstance
@@ -0,0 +1,65 @@
1
+ /*
2
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
3
+ # All Rights Reserved.
4
+ #
5
+ # This program is free software; you can modify and/or redistribute it
6
+ # under the terms of the GNU Affero General Public License
7
+ # as published by the Free Software Foundation; version 3 with
8
+ # attribution addendums as found in the LICENSE.txt
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+
15
+ # Modified by OpenC3, Inc.
16
+ # All changes Copyright 2022, OpenC3, Inc.
17
+ # All Rights Reserved
18
+ #
19
+ # This file may also be used under the terms of a commercial license
20
+ # if purchased from OpenC3, Inc.
21
+ */
22
+
23
+ import * as ActionCable from '@rails/actioncable'
24
+ //ActionCable.logger.enabled = true
25
+ ActionCable.ConnectionMonitor.staleThreshold = 10
26
+
27
+ export default class Cable {
28
+ constructor(url = '/openc3-api/cable') {
29
+ this._cable = null
30
+ this._url = url
31
+ }
32
+ disconnect() {
33
+ if (this._cable) {
34
+ this._cable.disconnect()
35
+ }
36
+ }
37
+ createSubscription(channel, scope, callbacks = {}, additionalOptions = {}) {
38
+ return OpenC3Auth.updateToken(OpenC3Auth.defaultMinValidity).then(
39
+ (refreshed) => {
40
+ if (refreshed) {
41
+ OpenC3Auth.setTokens()
42
+ }
43
+ if (this._cable == null) {
44
+ let final_url =
45
+ this._url +
46
+ '?scope=' +
47
+ window.openc3Scope +
48
+ '&authorization=' +
49
+ localStorage.openc3Token
50
+ this._cable = ActionCable.createConsumer(final_url)
51
+ }
52
+ return this._cable.subscriptions.create(
53
+ {
54
+ channel,
55
+ ...additionalOptions,
56
+ },
57
+ callbacks
58
+ )
59
+ }
60
+ )
61
+ }
62
+ recordPing() {
63
+ this._cable.connection.monitor.recordPing()
64
+ }
65
+ }
@@ -0,0 +1,199 @@
1
+ /*
2
+ # Copyright 2022 Ball Aerospace & Technologies Corp.
3
+ # All Rights Reserved.
4
+ #
5
+ # This program is free software; you can modify and/or redistribute it
6
+ # under the terms of the GNU Affero General Public License
7
+ # as published by the Free Software Foundation; version 3 with
8
+ # attribution addendums as found in the LICENSE.txt
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+
15
+ # Modified by OpenC3, Inc.
16
+ # All changes Copyright 2022, OpenC3, Inc.
17
+ # All Rights Reserved
18
+ #
19
+ # This file may also be used under the terms of a commercial license
20
+ # if purchased from OpenC3, Inc.
21
+ */
22
+
23
+ export class ConfigParserError {
24
+ constructor(config_parser, message, usage = '', url = '') {
25
+ this.keyword = config_parser.keyword
26
+ this.parameters = config_parser.parameters
27
+ this.filename = config_parser.filename
28
+ this.line = config_parser.line
29
+ this.lineNumber = config_parser.lineNumber
30
+ this.message = message
31
+ this.usage = usage
32
+ this.url = url
33
+ }
34
+ }
35
+
36
+ export class ConfigParserService {
37
+ keyword = null
38
+ parameters = []
39
+ filename = ''
40
+ line = ''
41
+ lineNumber = 0
42
+ url = 'https://openc3.com/docs/v5'
43
+
44
+ constructor() {}
45
+
46
+ verify_num_parameters(min_num_params, max_num_params, usage = '') {
47
+ // This syntax works with 0 because each doesn't return any values
48
+ // for a backwards range
49
+ for (let index = 1; index <= min_num_params; index++) {
50
+ // If the parameter is nil (0 based) then we have a problem
51
+ if (this.parameters[index - 1] === undefined) {
52
+ throw new ConfigParserError(
53
+ this,
54
+ `Not enough parameters for ${this.keyword}.`,
55
+ usage,
56
+ this.url
57
+ )
58
+ }
59
+ }
60
+ // If they pass null for max_params we don't check for a maximum number
61
+ if (max_num_params && !this.parameters[max_num_params] === undefined) {
62
+ throw new ConfigParserError(
63
+ this,
64
+ `Too many parameters for ${this.keyword}.`,
65
+ usage,
66
+ this.url
67
+ )
68
+ }
69
+ }
70
+
71
+ remove_quotes(string) {
72
+ if (string.length < 2) {
73
+ return string
74
+ }
75
+ let first_char = string.charAt(0)
76
+ if (first_char !== '"' && first_char !== "'") {
77
+ return string
78
+ }
79
+ let last_char = string.charAt(string.length - 1)
80
+ if (first_char !== last_char) {
81
+ return string
82
+ }
83
+ return string.substring(1, string.length - 1)
84
+ }
85
+
86
+ scan_string(string, rx) {
87
+ if (!rx.global) throw "rx must have 'global' flag set"
88
+ let r = []
89
+ string.replace(rx, function (match) {
90
+ r.push(match)
91
+ return match
92
+ })
93
+ return r
94
+ }
95
+
96
+ parse_string(
97
+ input_string,
98
+ original_filename,
99
+ yield_non_keyword_lines,
100
+ remove_quotes,
101
+ handler
102
+ ) {
103
+ let string_concat = false
104
+ this.line = ''
105
+ this.keyword = null
106
+ this.parameters = []
107
+ this.filename = original_filename
108
+
109
+ // Break string into lines
110
+ let lines = input_string.split('\n')
111
+ let numLines = lines.length
112
+
113
+ for (let i = 0; i < numLines; i++) {
114
+ this.lineNumber = i + 1
115
+ let line = lines[i].trim()
116
+ // Ensure the line length is not 0
117
+ if (line.length === 0) {
118
+ continue
119
+ }
120
+
121
+ if (string_concat === true) {
122
+ // Skip comment lines after a string concatenation
123
+ if (line[0] === '#') {
124
+ continue
125
+ }
126
+ // Remove the opening quote if we're continuing the line
127
+ line = line.substring(1, line.length)
128
+ }
129
+
130
+ // Check for string continuation
131
+ let last_char = line.charAt(line.length - 1)
132
+ let newline = false
133
+ switch (last_char) {
134
+ case '+': // String concatenation with newlines
135
+ newline = true
136
+ // Deliberate fall through
137
+ case '\\': // String concatenation
138
+ // Trim off the concat character plus any spaces, e.g. "line" \
139
+ let trim = line.substring(0, line.length - 1).trim()
140
+ // Now trim off the last quote so it will flow into the next line
141
+ this.line += trim.substring(0, trim.length - 1)
142
+ if (newline) {
143
+ this.line += '\n'
144
+ }
145
+ string_concat = true
146
+ continue
147
+ case '&': // Line continuation
148
+ this.line += line.substring(0, line.length - 1)
149
+ continue
150
+ default:
151
+ this.line += line
152
+ }
153
+ string_concat = false
154
+
155
+ let rx = /("([^\\"]|\\.)*")|('([^\\']|\\.)*')|\S+/g
156
+ let data = this.scan_string(this.line, rx)
157
+ let first_item = ''
158
+ if (data.length > 0) {
159
+ first_item = first_item + data[0]
160
+ }
161
+
162
+ if (first_item.length === 0 || first_item.charAt(0) === '#') {
163
+ this.keyword = null
164
+ } else {
165
+ this.keyword = first_item.toUpperCase()
166
+ }
167
+ this.parameters = []
168
+
169
+ // Ignore lines without keywords: comments and blank lines
170
+ if (this.keyword === null) {
171
+ if (yield_non_keyword_lines) {
172
+ handler(this.keyword, this.parameters, this.line, this.lineNumber)
173
+ }
174
+ this.line = ''
175
+ continue
176
+ }
177
+
178
+ let length = data.length
179
+ if (length > 1) {
180
+ for (let index = 1; index < length; index++) {
181
+ let string = data[index]
182
+
183
+ // Don't process trailing comments such as:
184
+ // KEYWORD PARAM #This is a comment
185
+ if (string.length > 0 && string.charAt(0) === '#') {
186
+ break
187
+ }
188
+ if (remove_quotes) {
189
+ this.parameters.push(this.remove_quotes(string))
190
+ } else {
191
+ this.parameters.push(string)
192
+ }
193
+ }
194
+ }
195
+ handler(this.keyword, this.parameters, this.line, this.lineNumber)
196
+ this.line = ''
197
+ } // for all the lines
198
+ } // parse_string
199
+ } // class ConfigParserService