openc3 5.10.1 → 5.11.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -2
  3. data/data/config/target.yaml +9 -0
  4. data/ext/openc3/ext/packet/packet.c +3 -0
  5. data/ext/openc3/ext/reducer_microservice/extconf.rb +13 -0
  6. data/ext/openc3/ext/reducer_microservice/reducer_microservice.c +165 -0
  7. data/ext/openc3/ext/structure/structure.c +7 -9
  8. data/lib/openc3/accessors/accessor.rb +53 -3
  9. data/lib/openc3/accessors/binary_accessor.rb +16 -0
  10. data/lib/openc3/accessors/cbor_accessor.rb +3 -3
  11. data/lib/openc3/accessors/form_accessor.rb +78 -0
  12. data/lib/openc3/accessors/http_accessor.rb +145 -0
  13. data/lib/openc3/accessors/json_accessor.rb +19 -3
  14. data/lib/openc3/accessors/xml_accessor.rb +18 -1
  15. data/lib/openc3/accessors.rb +3 -1
  16. data/lib/openc3/config/config_parser.rb +7 -5
  17. data/lib/openc3/config/meta_config_parser.rb +1 -1
  18. data/lib/openc3/core_ext/string.rb +16 -1
  19. data/lib/openc3/interfaces/http_client_interface.rb +202 -0
  20. data/lib/openc3/interfaces/http_server_interface.rb +183 -0
  21. data/lib/openc3/interfaces/interface.rb +86 -16
  22. data/lib/openc3/interfaces/mqtt_interface.rb +6 -5
  23. data/lib/openc3/interfaces/protocols/burst_protocol.rb +11 -11
  24. data/lib/openc3/interfaces/protocols/cobs_protocol.rb +7 -7
  25. data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -7
  26. data/lib/openc3/interfaces/protocols/length_protocol.rb +6 -6
  27. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +9 -5
  28. data/lib/openc3/interfaces/protocols/protocol.rb +8 -6
  29. data/lib/openc3/interfaces/protocols/slip_protocol.rb +8 -8
  30. data/lib/openc3/interfaces/protocols/template_protocol.rb +6 -7
  31. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +4 -4
  32. data/lib/openc3/interfaces/simulated_target_interface.rb +2 -0
  33. data/lib/openc3/interfaces/stream_interface.rb +6 -4
  34. data/lib/openc3/interfaces/tcpip_server_interface.rb +2 -0
  35. data/lib/openc3/interfaces/udp_interface.rb +8 -5
  36. data/lib/openc3/interfaces.rb +2 -0
  37. data/lib/openc3/logs/buffered_packet_log_writer.rb +6 -7
  38. data/lib/openc3/logs/log_writer.rb +2 -10
  39. data/lib/openc3/logs/packet_log_constants.rb +13 -3
  40. data/lib/openc3/logs/packet_log_reader.rb +35 -98
  41. data/lib/openc3/logs/packet_log_writer.rb +24 -62
  42. data/lib/openc3/logs/text_log_writer.rb +32 -6
  43. data/lib/openc3/microservices/cleanup_microservice.rb +23 -16
  44. data/lib/openc3/microservices/decom_microservice.rb +8 -20
  45. data/lib/openc3/microservices/log_microservice.rb +3 -1
  46. data/lib/openc3/microservices/reaction_microservice.rb +22 -11
  47. data/lib/openc3/microservices/reducer_microservice.rb +174 -130
  48. data/lib/openc3/{models/notification_model.rb → microservices/scope_cleanup_microservice.rb} +20 -21
  49. data/lib/openc3/microservices/text_log_microservice.rb +2 -5
  50. data/lib/openc3/microservices/timeline_microservice.rb +0 -1
  51. data/lib/openc3/microservices/trigger_group_microservice.rb +0 -1
  52. data/lib/openc3/migrations/20230915000002_no_scope_log_messages.rb +44 -0
  53. data/lib/openc3/models/microservice_model.rb +1 -1
  54. data/lib/openc3/models/scope_model.rb +65 -34
  55. data/lib/openc3/models/target_model.rb +25 -5
  56. data/lib/openc3/models/tool_model.rb +14 -2
  57. data/lib/openc3/models/widget_model.rb +1 -1
  58. data/lib/openc3/packets/json_packet.rb +10 -2
  59. data/lib/openc3/packets/packet.rb +30 -9
  60. data/lib/openc3/packets/packet_config.rb +6 -2
  61. data/lib/openc3/packets/parsers/packet_item_parser.rb +11 -6
  62. data/lib/openc3/packets/structure.rb +19 -12
  63. data/lib/openc3/script/storage.rb +1 -1
  64. data/lib/openc3/script/web_socket_api.rb +17 -14
  65. data/lib/openc3/topics/telemetry_topic.rb +2 -1
  66. data/lib/openc3/utilities/bucket_utilities.rb +2 -0
  67. data/lib/openc3/utilities/cli_generator.rb +1 -1
  68. data/lib/openc3/utilities/logger.rb +62 -47
  69. data/lib/openc3/utilities/metric.rb +19 -1
  70. data/lib/openc3/utilities/sleeper.rb +3 -1
  71. data/lib/openc3/utilities/throttle.rb +76 -0
  72. data/lib/openc3/version.rb +6 -6
  73. data/templates/tool_angular/package.json +20 -20
  74. data/templates/tool_angular/yarn.lock +112 -106
  75. data/templates/tool_react/package.json +16 -18
  76. data/templates/tool_react/yarn.lock +977 -664
  77. data/templates/tool_svelte/.prettierrc.js +5 -0
  78. data/templates/tool_svelte/package.json +18 -18
  79. data/templates/tool_svelte/src/services/cable.js +1 -1
  80. data/templates/tool_svelte/src/services/openc3-api.js +173 -173
  81. data/templates/tool_svelte/yarn.lock +767 -665
  82. data/templates/tool_vue/package.json +10 -10
  83. data/templates/tool_vue/yarn.lock +225 -43
  84. data/templates/widget/package.json +10 -10
  85. data/templates/widget/yarn.lock +223 -46
  86. metadata +41 -4
  87. data/lib/openc3/topics/notifications_topic.rb +0 -31
@@ -190,7 +190,7 @@ module OpenC3
190
190
 
191
191
  # Base class for script-runner-api websockets - Do not use directly
192
192
  class ScriptWebSocketApi < WebSocketApi
193
- def initialize(url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_token)
193
+ def initialize(url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
194
194
  url = generate_url() unless url
195
195
  super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
196
196
  end
@@ -217,23 +217,15 @@ module OpenC3
217
217
 
218
218
  # Log Messages WebSocket
219
219
  class MessagesWebSocketApi < CmdTlmWebSocketApi
220
- def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
220
+ def initialize(history_count: 0, start_time: nil, end_time: nil, severity: nil, types: nil, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
221
221
  @identifier = {
222
222
  channel: "MessagesChannel",
223
223
  history_count: history_count
224
224
  }
225
- super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
226
- end
227
- end
228
-
229
- # Notifications WebSocket
230
- class NotificationsWebSocketApi < CmdTlmWebSocketApi
231
- def initialize(history_count: 0, start_offset: nil, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
232
- @identifier = {
233
- channel: "NotificationsChannel",
234
- history_count: history_count,
235
- start_offset: start_offset
236
- }
225
+ @identifier['start_time'] = start_time if start_time
226
+ @identifier['end_time'] = end_time if end_time
227
+ @identifier['severity'] = severity if severity
228
+ @identifier['types'] = types if types
237
229
  super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
238
230
  end
239
231
  end
@@ -425,3 +417,14 @@ end
425
417
  #
426
418
  # # Warning this saves all data to RAM. Do not use for large queries
427
419
  # data = OpenC3::StreamingWebSocketApi.read_all(items: ['DECOM__TLM__INST__HEALTH_STATUS__TEMP1__CONVERTED', 'DECOM__TLM__INST__HEALTH_STATUS__TEMP2__CONVERTED'], start_time: Time.now - 30, end_time: Time.now + 30)
420
+
421
+ # $openc3_scope = 'DEFAULT'
422
+ # OpenC3::MessagesWebSocketApi.new(history_count: 0, start_time: (Time.now - 86400).to_nsec_from_epoch, end_time: (Time.now - 60).to_nsec_from_epoch) do |api|
423
+ # 500.times do
424
+ # # Note returns batch array
425
+ # data = api.read
426
+ # return if not data or data.length == 0
427
+ # puts "\nReceived #{data.length} log messages:"
428
+ # puts data
429
+ # end
430
+ # end
@@ -32,8 +32,9 @@ module OpenC3
32
32
  :target_name => packet.target_name,
33
33
  :packet_name => packet.packet_name,
34
34
  :received_count => packet.received_count,
35
- :buffer => packet.buffer(false),
35
+ :buffer => packet.buffer(false)
36
36
  }
37
+ msg_hash[:extra] = JSON.generate(packet.extra.as_json, allow_nan: true) if packet.extra
37
38
  Topic.write_topic("#{scope}__TELEMETRY__{#{packet.target_name}}__#{packet.packet_name}", msg_hash)
38
39
  end
39
40
  end
@@ -58,6 +58,8 @@ module OpenC3
58
58
  # @param start_time [Time|nil] Ruby time to find files after. nil means no start (first file on).
59
59
  # @param end_time [Time|nil] Ruby time to find files before. nil means no end (up to last file).
60
60
  # @param overlap [Boolean] Whether to include files which overlap the start and end time
61
+ # if true, file can be partially in the time range
62
+ # if false, file must be completely in the time range
61
63
  # @param max_request [Integer] How many files to request in each API call
62
64
  # @param max_total [Integer] Total number of files before stopping API requests
63
65
  def self.files_between_time(bucket, prefix, start_time, end_time, file_suffix: nil,
@@ -51,7 +51,7 @@ module OpenC3
51
51
  FileUtils.mkdir(base_name) unless File.exist?(base_name)
52
52
  next
53
53
  end
54
- output = ERB.new(File.read(file), trim_mode: "-").result(the_binding)
54
+ output = ERB.new(File.read(file).comment_erb(), trim_mode: "-").result(the_binding)
55
55
  File.open(base_name, 'w') do |file|
56
56
  file.write output
57
57
  end
@@ -14,7 +14,7 @@
14
14
  # GNU Affero General Public License for more details.
15
15
 
16
16
  # Modified by OpenC3, Inc.
17
- # All changes Copyright 2022, OpenC3, Inc.
17
+ # All changes Copyright 2023, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -44,11 +44,9 @@ module OpenC3
44
44
  # @return [String] Microservice name
45
45
  attr_reader :microservice_name
46
46
 
47
- # @return [String] Scope
48
- instance_attr_accessor :scope
49
-
50
47
  @@mutex = Mutex.new
51
48
  @@instance = nil
49
+ @@scope = ENV['OPENC3_SCOPE']
52
50
 
53
51
  # DEBUG only prints DEBUG messages
54
52
  DEBUG = ::Logger::DEBUG
@@ -67,11 +65,15 @@ module OpenC3
67
65
  ERROR_SEVERITY_STRING = 'ERROR'
68
66
  FATAL_SEVERITY_STRING = 'FATAL'
69
67
 
68
+ # Types
69
+ LOG = 'log'
70
+ NOTIFICATION = 'notification'
71
+ ALERT = 'alert'
72
+
70
73
  # @param level [Integer] The initial logging level
71
74
  def initialize(level = Logger::INFO)
72
75
  @stdout = true
73
76
  @level = level
74
- @scope = nil
75
77
  @detail_string = nil
76
78
  @container_name = Socket.gethostname
77
79
  @microservice_name = nil
@@ -95,68 +97,53 @@ module OpenC3
95
97
  # below the method name log level.
96
98
  # @param block [Proc] Block to call which should return a string to append
97
99
  # to the log message
98
- def debug(message = nil, scope: @scope, user: nil, &block)
99
- log_message(DEBUG_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= DEBUG
100
+ def debug(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
101
+ log_message(DEBUG_SEVERITY_STRING, message, scope: scope, user: user, type: type, url: url, &block) if @level <= DEBUG
100
102
  end
101
103
 
102
104
  # (see #debug)
103
- def info(message = nil, scope: @scope, user: nil, &block)
104
- log_message(INFO_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= INFO
105
+ def info(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
106
+ log_message(INFO_SEVERITY_STRING, message, scope: scope, user: user, type: type, url: url, &block) if @level <= INFO
105
107
  end
106
108
 
107
109
  # (see #debug)
108
- def warn(message = nil, scope: @scope, user: nil, &block)
109
- log_message(WARN_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= WARN
110
+ def warn(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
111
+ log_message(WARN_SEVERITY_STRING, message, scope: scope, user: user, type: type, url: url, &block) if @level <= WARN
110
112
  end
111
113
 
112
114
  # (see #debug)
113
- def error(message = nil, scope: @scope, user: nil, &block)
114
- log_message(ERROR_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= ERROR
115
+ def error(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
116
+ log_message(ERROR_SEVERITY_STRING, message, scope: scope, user: user, type: type, url: url, &block) if @level <= ERROR
115
117
  end
116
118
 
117
119
  # (see #debug)
118
- def fatal(message = nil, scope: @scope, user: nil, &block)
119
- log_message(FATAL_SEVERITY_STRING, message, scope: scope, user: user, &block) if @level <= FATAL
120
+ def fatal(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
121
+ log_message(FATAL_SEVERITY_STRING, message, scope: scope, user: user, type: type, url: url, &block) if @level <= FATAL
120
122
  end
121
123
 
122
124
  # (see #debug)
123
- def self.debug(message = nil, scope: nil, user: nil, &block)
124
- args = {}
125
- args[:scope] = scope if scope
126
- args[:user] = user if user
127
- self.instance.debug(message, **args, &block)
125
+ def self.debug(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
126
+ self.instance.debug(message, scope: scope, user: user, type: type, url: url, &block)
128
127
  end
129
128
 
130
129
  # (see #debug)
131
- def self.info(message = nil, scope: nil, user: nil, &block)
132
- args = {}
133
- args[:scope] = scope if scope
134
- args[:user] = user if user
135
- self.instance.info(message, **args, &block)
130
+ def self.info(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
131
+ self.instance.info(message, scope: scope, user: user, type: type, url: url, &block)
136
132
  end
137
133
 
138
134
  # (see #debug)
139
- def self.warn(message = nil, scope: nil, user: nil, &block)
140
- args = {}
141
- args[:scope] = scope if scope
142
- args[:user] = user if user
143
- self.instance.warn(message, **args, &block)
135
+ def self.warn(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
136
+ self.instance.warn(message, scope: scope, user: user, type: type, url: url, &block)
144
137
  end
145
138
 
146
139
  # (see #debug)
147
- def self.error(message = nil, scope: nil, user: nil, &block)
148
- args = {}
149
- args[:scope] = scope if scope
150
- args[:user] = user if user
151
- self.instance.error(message, **args, &block)
140
+ def self.error(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
141
+ self.instance.error(message, scope: scope, user: user, type: type, url: url, &block)
152
142
  end
153
143
 
154
144
  # (see #debug)
155
- def self.fatal(message = nil, scope: nil, user: nil, &block)
156
- args = {}
157
- args[:scope] = scope if scope
158
- args[:user] = user if user
159
- self.instance.fatal(message, **args, &block)
145
+ def self.fatal(message = nil, scope: @@scope, user: nil, type: LOG, url: nil, &block)
146
+ self.instance.fatal(message, scope: scope, user: user, type: type, url: url, &block)
160
147
  end
161
148
 
162
149
  # @return [Logger] The logger instance
@@ -169,11 +156,28 @@ module OpenC3
169
156
  @@instance
170
157
  end
171
158
 
159
+ def self.scope
160
+ return @@scope
161
+ end
162
+
163
+ def self.scope=(scope)
164
+ @@scope = scope
165
+ end
166
+
167
+ def scope
168
+ return @@scope
169
+ end
170
+
171
+ def scope=(scope)
172
+ @@scope = scope
173
+ end
174
+
172
175
  protected
173
176
 
174
- def log_message(severity_string, message, scope:, user:)
177
+ def log_message(severity_string, message, scope:, user:, type:, url:)
175
178
  @@mutex.synchronize do
176
- data = { time: Time.now.to_nsec_from_epoch, '@timestamp' => Time.now.xmlschema(3), severity: severity_string }
179
+ time = Time.now
180
+ data = { time: time.to_nsec_from_epoch, '@timestamp' => time.xmlschema(3), severity: severity_string }
177
181
  data[:microservice_name] = @microservice_name if @microservice_name
178
182
  data[:detail] = @detail_string if @detail_string
179
183
  data[:user] = user['username'] || 'Unknown' if user # EE: If a user is passed, put its name ('Unknown' if it doesn't have a name). Don't include user data if no user was passed
@@ -182,17 +186,28 @@ module OpenC3
182
186
  end
183
187
  data[:container_name] = @container_name
184
188
  data[:log] = message
189
+ data[:type] = type
190
+ data[:url] = url if url
185
191
  if @stdout
186
- puts data.as_json(:allow_nan => true).to_json(:allow_nan => true)
187
- $stdout.flush
192
+ case severity_string
193
+ when WARN_SEVERITY_STRING, ERROR_SEVERITY_STRING, FATAL_SEVERITY_STRING
194
+ if ENV['OPENC3_LOG_STDERR']
195
+ $stderr.puts data.as_json(:allow_nan => true).to_json(:allow_nan => true)
196
+ $stderr.flush
197
+ else
198
+ $stdout.puts data.as_json(:allow_nan => true).to_json(:allow_nan => true)
199
+ $stdout.flush
200
+ end
201
+ else
202
+ $stdout.puts data.as_json(:allow_nan => true).to_json(:allow_nan => true)
203
+ $stdout.flush
204
+ end
188
205
  end
189
206
  unless @no_store
190
207
  if scope
191
208
  Topic.write_topic("#{scope}__openc3_log_messages", data)
192
209
  else
193
- # The base openc3_log_messages doesn't have an associated logger
194
- # so it must be limited to prevent unbounded stream growth
195
- Topic.write_topic("openc3_log_messages", data, '*', 1000)
210
+ Topic.write_topic("NOSCOPE__openc3_log_messages", data)
196
211
  end
197
212
  end
198
213
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2022 OpenC3, Inc.
3
+ # Copyright 2023 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is free software; you can modify and/or redistribute it
@@ -38,6 +38,9 @@ module OpenC3
38
38
  # Sleeper used to delay update thread
39
39
  @@update_sleeper = nil
40
40
 
41
+ # Objects with a generate method to be called on each metric cycle (to generate metrics)
42
+ @@update_generators = []
43
+
41
44
  attr_reader :microservice
42
45
  attr_reader :scope
43
46
  attr_reader :data
@@ -83,7 +86,12 @@ module OpenC3
83
86
  @@update_sleeper = Sleeper.new
84
87
  while true
85
88
  start_time = Time.now
89
+
86
90
  @@mutex.synchronize do
91
+ @@update_generators.each do |generator|
92
+ generator.generate(@@instances[0])
93
+ end
94
+
87
95
  @@instances.each do |instance|
88
96
  instance.mutex.synchronize do
89
97
  json = {}
@@ -116,5 +124,15 @@ module OpenC3
116
124
 
117
125
  def graceful_kill
118
126
  end
127
+
128
+ def self.add_update_generator(object)
129
+ @@update_generators << object
130
+ end
119
131
  end
120
132
  end
133
+
134
+ begin
135
+ require 'openc3-enterprise/utilities/metric'
136
+ rescue LoadError
137
+ # Open Source Edition - Do nothing here
138
+ 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
  module OpenC3
@@ -37,6 +37,7 @@ module OpenC3
37
37
  def sleep(seconds)
38
38
  read_ready, _ = IO.select(@readers, nil, nil, seconds)
39
39
  if read_ready && read_ready.include?(@pipe_reader)
40
+ @pipe_reader.close unless @pipe_reader.closed?
40
41
  return true
41
42
  else
42
43
  return false
@@ -48,6 +49,7 @@ module OpenC3
48
49
  if !@canceled
49
50
  @canceled = true
50
51
  @pipe_writer.write('.')
52
+ @pipe_writer.close
51
53
  end
52
54
  end
53
55
  end
@@ -0,0 +1,76 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2023 OpenC3, Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # This file may also be used under the terms of a commercial license
17
+ # if purchased from OpenC3, Inc.
18
+
19
+ # Usage:
20
+ # throttle = OpenC3::Throttle.new(50.0) # Use max 50% cpu for work
21
+ #
22
+ # throttle.reset # Necessary if there are large periods of idle between hard work
23
+ # 1000.times do
24
+ # throttle.start
25
+ # # Do one iteration of cpu itensive work here
26
+ # # complete will sleep if necessary to not use too much CPU
27
+ # throttle.complete
28
+ # end
29
+
30
+ module OpenC3
31
+ class Throttle
32
+ MIN_SLEEP_SECONDS = 0.001
33
+ MAX_SLEEP_SECONDS = 0.100
34
+
35
+ attr_reader :reset_time
36
+ attr_reader :total_sleep_time
37
+
38
+ # @param max_cpu_utilization [Float] 0.0-100.0
39
+ def initialize(max_cpu_utilization)
40
+ @max_cpu_utilization = Float(max_cpu_utilization)
41
+ raise ArgumentError "max_cpu_utilization must be between 0.0 and 100.0" if @max_cpu_utilization > 100.0 or @max_cpu_utilization < 0.0
42
+ @max_cpu_utilization /= 100.0 # Normalize
43
+ reset()
44
+ end
45
+
46
+ def reset
47
+ @reset_time = Time.now
48
+ @total_sleep_time = 0
49
+ end
50
+
51
+ def throttle_sleep
52
+ return if @max_cpu_utilization >= 1.0
53
+ total_time = Time.now - @reset_time
54
+ if total_time > 0
55
+ cpu_utilization = 1.0 - (@total_sleep_time / total_time)
56
+ if cpu_utilization > @max_cpu_utilization
57
+ # Need to throttle
58
+ # max_cpu_utilization = sleep_time + total_sleep_time
59
+ # ----------------------------
60
+ # total_time
61
+ #
62
+ # (max_cpu_utilization * total_time) = sleep_time + total_sleep_time
63
+ #
64
+ # sleep_time = (max_cpu_utilization * total_time) - total_sleep_time
65
+ #
66
+ sleep_time = (@max_cpu_utilization * total_time) - @total_sleep_time
67
+ if sleep_time > MIN_SLEEP_SECONDS
68
+ sleep_time = MAX_SLEEP_SECONDS if sleep_time > MAX_SLEEP_SECONDS
69
+ sleep(sleep_time)
70
+ @total_sleep_time += sleep_time
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,14 +1,14 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- OPENC3_VERSION = '5.10.1'
3
+ OPENC3_VERSION = '5.11.0'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '5'
7
- MINOR = '10'
8
- PATCH = '1'
7
+ MINOR = '11'
8
+ PATCH = '0'
9
9
  OTHER = ''
10
- BUILD = 'b248056bc6fa7af79757e21f3b79601118eec0e5'
10
+ BUILD = 'f994eee0c2fadfc67ffbf0865ba798ed11ec1f5c'
11
11
  end
12
- VERSION = '5.10.1'
13
- GEM_VERSION = '5.10.1'
12
+ VERSION = '5.11.0'
13
+ GEM_VERSION = '5.11.0'
14
14
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "5.10.1",
3
+ "version": "5.11.0",
4
4
  "scripts": {
5
5
  "ng": "ng",
6
6
  "start": "ng serve",
@@ -12,36 +12,36 @@
12
12
  },
13
13
  "private": true,
14
14
  "dependencies": {
15
- "@openc3/tool-common": "5.10.1",
16
- "@angular/animations": "^16.2.0",
17
- "@angular/cdk": "^16.2.0",
18
- "@angular/common": "^16.2.0",
19
- "@angular/compiler": "^16.2.0",
20
- "@angular/core": "^16.2.0",
21
- "@angular/forms": "^16.2.0",
22
- "@angular/material": "16.2.0",
23
- "@angular/platform-browser": "^16.2.0",
24
- "@angular/platform-browser-dynamic": "^16.2.0",
25
- "@angular/router": "^16.2.0",
15
+ "@openc3/tool-common": "5.11.0",
16
+ "@angular/animations": "^16.2.4",
17
+ "@angular/cdk": "^16.2.3",
18
+ "@angular/common": "^16.2.4",
19
+ "@angular/compiler": "^16.2.4",
20
+ "@angular/core": "^16.2.4",
21
+ "@angular/forms": "^16.2.4",
22
+ "@angular/material": "16.2.3",
23
+ "@angular/platform-browser": "^16.2.4",
24
+ "@angular/platform-browser-dynamic": "^16.2.4",
25
+ "@angular/router": "^16.2.4",
26
26
  "rxjs": "~7.8.0",
27
27
  "single-spa": ">=5.9.5",
28
28
  "single-spa-angular": "^8.1.0",
29
- "tslib": "^2.6.1",
30
- "zone.js": "~0.13.1"
29
+ "tslib": "^2.6.2",
30
+ "zone.js": "~0.13.3"
31
31
  },
32
32
  "devDependencies": {
33
- "@angular-builders/custom-webpack": "16.0.0",
34
- "@angular-devkit/build-angular": "^16.2.0",
35
- "@angular/cli": "~16.2.0",
36
- "@angular/compiler-cli": "^16.2.0",
33
+ "@angular-builders/custom-webpack": "16.0.1",
34
+ "@angular-devkit/build-angular": "^16.2.1",
35
+ "@angular/cli": "~16.2.1",
36
+ "@angular/compiler-cli": "^16.2.4",
37
37
  "@types/jasmine": "~4.3.0",
38
- "jasmine-core": "~5.1.0",
38
+ "jasmine-core": "~5.1.1",
39
39
  "karma": "~6.4.0",
40
40
  "karma-chrome-launcher": "~3.2.0",
41
41
  "karma-coverage": "~2.2.0",
42
42
  "karma-jasmine": "~5.1.0",
43
43
  "karma-jasmine-html-reporter": "~2.1.0",
44
44
  "style-loader": "^3.3.1",
45
- "typescript": "~5.1.6"
45
+ "typescript": "~5.2.2"
46
46
  }
47
47
  }