openc3 5.13.0 → 5.14.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openc3 might be problematic. Click here for more details.

Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -3
  3. data/bin/openc3cli +18 -15
  4. data/data/config/command_modifiers.yaml +53 -1
  5. data/lib/openc3/accessors/accessor.rb +42 -29
  6. data/lib/openc3/accessors/binary_accessor.rb +11 -1
  7. data/lib/openc3/accessors/form_accessor.rb +11 -1
  8. data/lib/openc3/accessors/http_accessor.rb +38 -0
  9. data/lib/openc3/accessors/json_accessor.rb +15 -3
  10. data/lib/openc3/accessors/template_accessor.rb +150 -0
  11. data/lib/openc3/accessors/xml_accessor.rb +11 -1
  12. data/lib/openc3/accessors.rb +1 -0
  13. data/lib/openc3/api/limits_api.rb +3 -3
  14. data/lib/openc3/api/tlm_api.rb +8 -8
  15. data/lib/openc3/interfaces/interface.rb +9 -7
  16. data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +116 -0
  17. data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -0
  18. data/lib/openc3/interfaces/tcpip_server_interface.rb +5 -0
  19. data/lib/openc3/interfaces.rb +1 -1
  20. data/lib/openc3/microservices/decom_microservice.rb +1 -0
  21. data/lib/openc3/microservices/interface_microservice.rb +10 -1
  22. data/lib/openc3/models/cvt_model.rb +16 -12
  23. data/lib/openc3/models/gem_model.rb +20 -3
  24. data/lib/openc3/models/microservice_model.rb +1 -1
  25. data/lib/openc3/models/plugin_model.rb +5 -1
  26. data/lib/openc3/models/target_model.rb +69 -8
  27. data/lib/openc3/packets/packet.rb +92 -4
  28. data/lib/openc3/packets/packet_config.rb +25 -1
  29. data/lib/openc3/script/api_shared.rb +11 -0
  30. data/lib/openc3/script/script.rb +6 -12
  31. data/lib/openc3/streams/tcpip_socket_stream.rb +19 -0
  32. data/lib/openc3/system/system.rb +13 -1
  33. data/lib/openc3/utilities/cli_generator.rb +15 -1
  34. data/lib/openc3/utilities/local_mode.rb +1 -1
  35. data/lib/openc3/utilities/store_queued.rb +126 -0
  36. data/lib/openc3/version.rb +5 -5
  37. data/templates/plugin/plugin.gemspec +2 -2
  38. data/templates/target/targets/TARGET/public/README.txt +1 -0
  39. data/templates/tool_angular/package.json +15 -15
  40. data/templates/tool_angular/yarn.lock +184 -78
  41. data/templates/tool_react/package.json +10 -10
  42. data/templates/tool_react/yarn.lock +236 -374
  43. data/templates/tool_svelte/package.json +13 -13
  44. data/templates/tool_svelte/yarn.lock +246 -235
  45. data/templates/tool_vue/package.json +12 -12
  46. data/templates/tool_vue/yarn.lock +63 -55
  47. data/templates/widget/package.json +11 -11
  48. data/templates/widget/yarn.lock +54 -46
  49. metadata +144 -154
  50. data/lib/openc3/io/openc3_snmp.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70d4819352855e3fdb8b4c4d39331968e3e60af59beb0555743b42669d5b4b4a
4
- data.tar.gz: c906a678c11f68b8751000875fe5cfdfdbbe98880e182edc572791246d625491
3
+ metadata.gz: 2b009f636dd8566127001ad9ee48972d584fb03baaf88389646048e7231dc54b
4
+ data.tar.gz: 0ce2ff7aad089eba4794f4f15075bcf5e3087632f776eb76127c80af5256bda6
5
5
  SHA512:
6
- metadata.gz: 2adcf16c91e84be3d1ef2b412ffc57eda1e7ed87e2d808519f9502c2cd937dcc06e766fad4f74b346daa0122a08745442decdbeb9185990206d7098c0331bf51
7
- data.tar.gz: 413edafbcaebcb868c68f1e0ddfeadc4ef32e4950be652a2520858060efd2274d28e9f15f85d944ae48058c1c52cc72ad768f097f5a7830217ae71345869044d
6
+ metadata.gz: 1d87b341b985cca628485419b0406b449289364497e4061024d0407551920fc8f62529fb35897761a1ae471c838cf2ce38d706fcf84eea4960abdd24a7608af5
7
+ data.tar.gz: '0758dfda18babfc4c47f870efe074e5a6bbd371aee1ba2a362f3d851791f20c2f5955e7f144972198a461a314b0a2a334c02d8191c7387503c30a11d8bd53c50'
data/Gemfile CHANGED
@@ -7,11 +7,11 @@ gem 'ruby-termios', '>= 0.9' if RbConfig::CONFIG['target_os'] !~ /mswin|mingw|cy
7
7
  gemspec :name => 'openc3'
8
8
 
9
9
  # Include the rails gems for the convenience of custom microservice plugins
10
- gem 'rails', '~> 7.1.0'
11
10
  gem 'bootsnap', '>= 1.9.3', require: false
11
+ gem 'mock_redis', '0.41'
12
12
  gem 'rack-cors', '~> 2.0'
13
- gem 'tzinfo-data'
13
+ gem 'rails', '~> 7.1.0'
14
14
  gem 'rspec-rails', '~> 6.0'
15
15
  gem 'simplecov', '~> 0.20'
16
16
  gem 'simplecov-cobertura', '~> 2.1'
17
- gem 'mock_redis', '0.40'
17
+ gem 'tzinfo-data'
data/bin/openc3cli CHANGED
@@ -15,7 +15,7 @@
15
15
  # GNU Affero General Public License for more details.
16
16
 
17
17
  # Modified by OpenC3, Inc.
18
- # All changes Copyright 2022, OpenC3, Inc.
18
+ # All changes Copyright 2024, OpenC3, Inc.
19
19
  # All Rights Reserved
20
20
  #
21
21
  # This file may also be used under the terms of a commercial license
@@ -232,7 +232,7 @@ def xtce_converter(args)
232
232
 
233
233
  begin
234
234
  option_parser.parse!(args)
235
- rescue => err
235
+ rescue => e
236
236
  abort(option_parser.to_s)
237
237
  end
238
238
 
@@ -348,10 +348,13 @@ def update_plugin(plugin_file_path, plugin_name, variables: nil, plugin_txt_line
348
348
  else
349
349
  puts "No changes detected - Exiting without change"
350
350
  end
351
- rescue => error
352
- puts error.formatted
353
- plugin_model.restore if plugin_model.destroyed?
354
- raise error
351
+ rescue => e
352
+ puts e.formatted
353
+ if plugin_model.destroyed?
354
+ plugin_model.restore
355
+ # Local mode files should still be good because restore will now reuse the old name
356
+ end
357
+ raise e
355
358
  end
356
359
  end
357
360
 
@@ -408,8 +411,8 @@ def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil, force: false)
408
411
  scope_model = OpenC3::ScopeModel.new(name: scope, scope: scope)
409
412
  scope_model.create
410
413
  scope_model.deploy(".", {})
411
- rescue => err
412
- abort("Error creating scope: #{scope}: #{err.formatted}")
414
+ rescue => e
415
+ abort("Error creating scope: #{scope}: #{e.formatted}")
413
416
  end
414
417
  end
415
418
 
@@ -467,8 +470,8 @@ def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil, force: false)
467
470
  plugin_hash = OpenC3::PluginModel.install_phase2(plugin_hash, scope: scope)
468
471
  OpenC3::LocalMode.update_local_plugin(plugin_file_path, plugin_hash, scope: scope)
469
472
  end
470
- rescue => error
471
- abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{error.message}")
473
+ rescue => e
474
+ abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{e.message}")
472
475
  end
473
476
  else
474
477
  # Outside Cluster
@@ -496,8 +499,8 @@ def unload_plugin(plugin_name, scope:)
496
499
  plugin_model.destroy
497
500
  OpenC3::LocalMode.remove_local_plugin(plugin_name, scope: scope)
498
501
  OpenC3::Logger.info("PluginModel destroyed: #{plugin_name}", scope: scope)
499
- rescue => err
500
- abort("Error uninstalling plugin: #{scope}: #{plugin_name}: #{err.formatted}")
502
+ rescue => e
503
+ abort("Error uninstalling plugin: #{scope}: #{plugin_name}: #{e.formatted}")
501
504
  end
502
505
  else
503
506
  # Outside Cluster
@@ -618,7 +621,7 @@ def run_bridge(filename, params)
618
621
  raise "Invalid variable passed to bridgegem (syntax name=value): #{param}"
619
622
  end
620
623
  end
621
- bridge = OpenC3::Bridge.new(filename, variables)
624
+ OpenC3::Bridge.new(filename, variables)
622
625
  begin
623
626
  while true
624
627
  sleep(1)
@@ -731,7 +734,7 @@ if not ARGV[0].nil? # argument(s) given
731
734
  when 'removebase'
732
735
  # Used to remove tool base to better support enterprise upgrade
733
736
  scopes = OpenC3::ScopeModel.all
734
- scopes.each do |scope_name, scope|
737
+ scopes.each do |scope_name, _scope|
735
738
  plugins = OpenC3::PluginModel.all(scope: scope_name)
736
739
  plugins.each do |plugin_name, plugin|
737
740
  if plugin["name"] =~ /tool-base/ and plugin["name"] !~ /enterprise/
@@ -746,7 +749,7 @@ if not ARGV[0].nil? # argument(s) given
746
749
  when 'removeenterprise'
747
750
  # Used to remove enterprise plugins to better support downgrade
748
751
  scopes = OpenC3::ScopeModel.all
749
- scopes.each do |scope_name, scope|
752
+ scopes.each do |scope_name, _scope|
750
753
  plugins = OpenC3::PluginModel.all(scope: scope_name)
751
754
  plugins.each do |plugin_name, plugin|
752
755
  if plugin["name"] =~ /enterprise/
@@ -192,4 +192,56 @@ TEMPLATE_FILE:
192
192
  required: true
193
193
  description: The relative path to the template file. Filename should generally start with an underscore.
194
194
  values: .+
195
- since: 5.0.10
195
+ since: 5.0.10
196
+ RESPONSE:
197
+ summary: Indicates the expected telemetry packet response to this command
198
+ parameters:
199
+ - name: Target Name
200
+ required: true
201
+ description: Target Name of telemetry response packet
202
+ values: .+
203
+ - name: Packet Name
204
+ required: true
205
+ description: Packet Name of telemetry response packet
206
+ values: .+
207
+ since: 5.14.0
208
+ ERROR_RESPONSE:
209
+ summary: Indicates the expected telemetry packet error response to this command
210
+ parameters:
211
+ - name: Target Name
212
+ required: true
213
+ description: Target Name of telemetry error response packet
214
+ values: .+
215
+ - name: Packet Name
216
+ required: true
217
+ description: Packet Name of telemetry error response packet
218
+ values: .+
219
+ since: 5.14.0
220
+ RELATED_ITEM:
221
+ summary: Defines a related telemetry item to this command
222
+ parameters:
223
+ - name: Target Name
224
+ required: true
225
+ description: Target Name of related telemetry item
226
+ values: .+
227
+ - name: Packet Name
228
+ required: true
229
+ description: Packet Name of related telemetry item
230
+ values: .+
231
+ - name: Item Name
232
+ required: true
233
+ description: Item Name of related telemetry item
234
+ values: .+
235
+ since: 5.14.0
236
+ SCREEN:
237
+ summary: Defines a related telemetry screen to this command
238
+ parameters:
239
+ - name: Target Name
240
+ required: true
241
+ description: Target Name of related telemetry screen
242
+ values: .+
243
+ - name: Screen Name
244
+ required: true
245
+ description: Screen Name of related telemetry screen
246
+ values: .+
247
+ since: 5.14.0
@@ -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
@@ -16,6 +16,8 @@
16
16
  # This file may also be used under the terms of a commercial license
17
17
  # if purchased from OpenC3, Inc.
18
18
 
19
+ require 'json'
20
+
19
21
  module OpenC3
20
22
  class Accessor
21
23
  attr_accessor :packet
@@ -52,27 +54,37 @@ module OpenC3
52
54
  return @args
53
55
  end
54
56
 
57
+ # If this is set it will enforce that buffer data is encoded
58
+ # in a specific encoding
55
59
  def enforce_encoding
56
60
  return 'ASCII-8BIT'.freeze
57
61
  end
58
62
 
63
+ # This affects whether the Packet class enforces the buffer
64
+ # length at all. Set to false to remove any correlation between
65
+ # buffer length and defined sizes of items in COSMOS
59
66
  def enforce_length
60
67
  return true
61
68
  end
62
69
 
70
+ # This sets the short_buffer_allowed flag in the Packet class
71
+ # which allows packets that have a buffer shorter than the defined size.
72
+ # Note that the buffer is still resized to the defined length
63
73
  def enforce_short_buffer_allowed
64
74
  return false
65
75
  end
66
76
 
67
- def enforce_derived_write_conversion(item)
77
+ # If this is true it will enfore that COSMOS DERIVED items must have a
78
+ # write_conversion to be written
79
+ def enforce_derived_write_conversion(_item)
68
80
  return true
69
81
  end
70
82
 
71
- def self.read_item(item, buffer)
83
+ def self.read_item(_item, _buffer)
72
84
  raise "Must be defined by subclass"
73
85
  end
74
86
 
75
- def self.write_item(item, value, buffer)
87
+ def self.write_item(_item, _value, _buffer)
76
88
  raise "Must be defined by subclass"
77
89
  end
78
90
 
@@ -92,33 +104,34 @@ module OpenC3
92
104
  end
93
105
 
94
106
  def self.convert_to_type(value, item)
95
- data_type = item.data_type
96
- if (data_type == :STRING) || (data_type == :BLOCK)
97
- #######################################
98
- # Handle :STRING and :BLOCK data types
99
- #######################################
100
- value = value.to_s
101
-
102
- elsif (data_type == :INT) || (data_type == :UINT)
103
- ###################################
104
- # Handle :INT data type
105
- ###################################
106
- value = Integer(value)
107
-
108
- elsif data_type == :FLOAT
109
- ##########################
110
- # Handle :FLOAT data type
111
- ##########################
112
- value = Float(value)
113
-
107
+ case item.data_type
108
+ when :OBJECT
109
+ # Do nothing for complex object types
110
+ when :STRING, :BLOCK
111
+ if item.array_size
112
+ value = JSON.parse(value) if value.is_a? String
113
+ value = value.map { |v| v.to_s }
114
+ else
115
+ value = value.to_s
116
+ end
117
+ when :UINT, :INT
118
+ if item.array_size
119
+ value = JSON.parse(value) if value.is_a? String
120
+ value = value.map { |v| Integer(v) }
121
+ else
122
+ value = Integer(value)
123
+ end
124
+ when :FLOAT
125
+ if item.array_size
126
+ value = JSON.parse(value) if value.is_a? String
127
+ value = value.map { |v| Float(v) }
128
+ else
129
+ value = Float(value)
130
+ end
114
131
  else
115
- ############################
116
- # Handle Unknown data types
117
- ############################
118
-
119
- raise(ArgumentError, "data_type #{data_type} is not recognized")
132
+ raise(ArgumentError, "data_type #{item.data_type} is not recognized")
120
133
  end
121
134
  return value
122
135
  end
123
136
  end
124
- end
137
+ end
@@ -1229,19 +1229,29 @@ module OpenC3
1229
1229
  values
1230
1230
  end
1231
1231
 
1232
+ # If this is set it will enforce that buffer data is encoded
1233
+ # in a specific encoding
1232
1234
  def enforce_encoding
1233
1235
  return 'ASCII-8BIT'.freeze
1234
1236
  end
1235
1237
 
1238
+ # This affects whether the Packet class enforces the buffer
1239
+ # length at all. Set to false to remove any correlation between
1240
+ # buffer length and defined sizes of items in COSMOS
1236
1241
  def enforce_length
1237
1242
  return true
1238
1243
  end
1239
1244
 
1245
+ # This sets the short_buffer_allowed flag in the Packet class
1246
+ # which allows packets that have a buffer shorter than the defined size.
1247
+ # Note that the buffer is still resized to the defined length
1240
1248
  def enforce_short_buffer_allowed
1241
1249
  return false
1242
1250
  end
1243
1251
 
1244
- def enforce_derived_write_conversion(item)
1252
+ # If this is true it will enfore that COSMOS DERIVED items must have a
1253
+ # write_conversion to be written
1254
+ def enforce_derived_write_conversion(_item)
1245
1255
  return true
1246
1256
  end
1247
1257
  end # class BinaryAccessor
@@ -59,19 +59,29 @@ module OpenC3
59
59
  return value
60
60
  end
61
61
 
62
+ # If this is set it will enforce that buffer data is encoded
63
+ # in a specific encoding
62
64
  def enforce_encoding
63
65
  return nil
64
66
  end
65
67
 
68
+ # This affects whether the Packet class enforces the buffer
69
+ # length at all. Set to false to remove any correlation between
70
+ # buffer length and defined sizes of items in COSMOS
66
71
  def enforce_length
67
72
  return false
68
73
  end
69
74
 
75
+ # This sets the short_buffer_allowed flag in the Packet class
76
+ # which allows packets that have a buffer shorter than the defined size.
77
+ # Note that the buffer is still resized to the defined length
70
78
  def enforce_short_buffer_allowed
71
79
  return true
72
80
  end
73
81
 
74
- def enforce_derived_write_conversion(item)
82
+ # If this is true it will enfore that COSMOS DERIVED items must have a
83
+ # write_conversion to be written
84
+ def enforce_derived_write_conversion(_item)
75
85
  return true
76
86
  end
77
87
  end
@@ -121,18 +121,56 @@ module OpenC3
121
121
  return value
122
122
  end
123
123
 
124
+ def read_items(items, buffer)
125
+ result = {}
126
+ body_items = []
127
+ items.each do |item|
128
+ if item.name[0..4] == 'HTTP_'
129
+ result[item.name] = read_item(item, buffer)
130
+ else
131
+ body_items << item
132
+ end
133
+ end
134
+ body_result = @body_accessor.read_items(body_items, buffer)
135
+ result.merge!(body_result) # Merge Body accessor read items with HTTP_ items
136
+ return result
137
+ end
138
+
139
+ def write_items(items, values, buffer)
140
+ body_items = []
141
+ items.each_with_index do |item, index|
142
+ if item.name[0..4] == 'HTTP_'
143
+ write_item(item, values[index], buffer)
144
+ else
145
+ body_items << item
146
+ end
147
+ end
148
+ @body_accessor.write_items(body_items, values, buffer)
149
+ return values
150
+ end
151
+
152
+ # If this is set it will enforce that buffer data is encoded
153
+ # in a specific encoding
124
154
  def enforce_encoding
125
155
  return @body_accessor.enforce_encoding
126
156
  end
127
157
 
158
+ # This affects whether the Packet class enforces the buffer
159
+ # length at all. Set to false to remove any correlation between
160
+ # buffer length and defined sizes of items in COSMOS
128
161
  def enforce_length
129
162
  return @body_accessor.enforce_length
130
163
  end
131
164
 
165
+ # This sets the short_buffer_allowed flag in the Packet class
166
+ # which allows packets that have a buffer shorter than the defined size.
167
+ # Note that the buffer is still resized to the defined length
132
168
  def enforce_short_buffer_allowed
133
169
  return @body_accessor.enforce_short_buffer_allowed
134
170
  end
135
171
 
172
+ # If this is true it will enfore that COSMOS DERIVED items must have a
173
+ # write_conversion to be written
136
174
  def enforce_derived_write_conversion(item)
137
175
  case item.name
138
176
  when 'HTTP_STATUS', 'HTTP_PATH', 'HTTP_METHOD', 'HTTP_PACKET', 'HTTP_ERROR_PACKET', /^HTTP_QUERY_/, /^HTTP_HEADER_/
@@ -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
@@ -24,7 +24,8 @@ module OpenC3
24
24
  class JsonAccessor < Accessor
25
25
  def self.read_item(item, buffer)
26
26
  return nil if item.data_type == :DERIVED
27
- return JsonPath.on(buffer, item.key).first
27
+ value = JsonPath.on(buffer, item.key).first
28
+ return convert_to_type(value, item)
28
29
  end
29
30
 
30
31
  def self.write_item(item, value, buffer)
@@ -123,6 +124,7 @@ module OpenC3
123
124
  raise "Unsupported key/token: #{item.key} - #{token}"
124
125
  end
125
126
  end
127
+ value = convert_to_type(value, item)
126
128
  if parent_node
127
129
  parent_node[parent_key] = value
128
130
  else
@@ -131,19 +133,29 @@ module OpenC3
131
133
  return decoded
132
134
  end
133
135
 
136
+ # If this is set it will enforce that buffer data is encoded
137
+ # in a specific encoding
134
138
  def enforce_encoding
135
139
  return nil
136
140
  end
137
141
 
142
+ # This affects whether the Packet class enforces the buffer
143
+ # length at all. Set to false to remove any correlation between
144
+ # buffer length and defined sizes of items in COSMOS
138
145
  def enforce_length
139
146
  return false
140
147
  end
141
148
 
149
+ # This sets the short_buffer_allowed flag in the Packet class
150
+ # which allows packets that have a buffer shorter than the defined size.
151
+ # Note that the buffer is still resized to the defined length
142
152
  def enforce_short_buffer_allowed
143
153
  return true
144
154
  end
145
155
 
146
- def enforce_derived_write_conversion(item)
156
+ # If this is true it will enfore that COSMOS DERIVED items must have a
157
+ # write_conversion to be written
158
+ def enforce_derived_write_conversion(_item)
147
159
  return true
148
160
  end
149
161
  end
@@ -0,0 +1,150 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2024 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
+ require 'openc3/accessors/accessor'
20
+
21
+ module OpenC3
22
+ class TemplateAccessor < Accessor
23
+ def initialize(packet, left_char = '<', right_char = '>')
24
+ super(packet)
25
+ @left_char = left_char
26
+ @right_char = right_char
27
+ @configured = false
28
+ end
29
+
30
+ def configure
31
+ return if @configured
32
+
33
+ escaped_left_char = @left_char
34
+ escaped_left_char = "\\#{@left_char}" if @left_char == '('
35
+ escaped_right_char = @right_char
36
+ escaped_right_char = "\\#{@right_char}" if @right_char == ')'
37
+
38
+ # Convert the template into a Regexp for reading each item
39
+ template = @packet.template.dup
40
+ template_items = template.scan(Regexp.new("#{escaped_left_char}.*?#{escaped_right_char}"))
41
+ escaped_read_template = template
42
+ if @left_char != '('
43
+ escaped_read_template = escaped_read_template.gsub('(', '\(')
44
+ end
45
+ if @right_char != ')'
46
+ escaped_read_template = escaped_read_template.gsub(')', '\)')
47
+ end
48
+
49
+ @item_keys = []
50
+ template_items.each do |item|
51
+ @item_keys << item[1..-2]
52
+ escaped_read_template.gsub!(item, "(.*)")
53
+ end
54
+ @read_regexp = Regexp.new(escaped_read_template)
55
+
56
+ @configured = true
57
+ end
58
+
59
+ def read_item(item, buffer)
60
+ return nil if item.data_type == :DERIVED
61
+ configure()
62
+
63
+ # Scan the response for all the variables in brackets <VARIABLE>
64
+ values = buffer.scan(@read_regexp)[0]
65
+ if !values || (values.length != @item_keys.length)
66
+ raise "Unexpected number of items found in buffer: #{values ? values.length : 0}, Expected: #{@item_keys.length}"
67
+ else
68
+ values.each_with_index do |value, i|
69
+ item_key = @item_keys[i]
70
+ if item_key == item.key
71
+ return Accessor.convert_to_type(value, item)
72
+ end
73
+ end
74
+ end
75
+
76
+ raise "Response does not include key #{item.key}: #{buffer}"
77
+ end
78
+
79
+ def read_items(items, buffer)
80
+ result = {}
81
+ configure()
82
+
83
+ # Scan the response for all the variables in brackets <VARIABLE>
84
+ values = buffer.scan(@read_regexp)[0]
85
+ if !values || (values.length != @item_keys.length)
86
+ raise "Unexpected number of items found in buffer: #{values ? values.length : 0}, Expected: #{@item_keys.length}"
87
+ else
88
+ items.each do |item|
89
+ if item.data_type == :DERIVED
90
+ result[item.name] = nil
91
+ next
92
+ end
93
+ index = @item_keys.index(item.key)
94
+ if index
95
+ result[item.name] = Accessor.convert_to_type(values[index], item)
96
+ else
97
+ raise "Unknown item with key #{item.key} requested"
98
+ end
99
+ end
100
+ end
101
+
102
+ return result
103
+ end
104
+
105
+ def write_item(item, value, buffer)
106
+ return nil if item.data_type == :DERIVED
107
+ configure()
108
+
109
+ success = buffer.gsub!("#{@left_char}#{item.key}#{@right_char}", value.to_s)
110
+ raise "Key #{item.key} not found in template" unless success
111
+ return value
112
+ end
113
+
114
+ def write_items(items, values, buffer)
115
+ configure()
116
+ items.each_with_index do |item, index|
117
+ next if item.data_type == :DERIVED
118
+ success = buffer.gsub!("#{@left_char}#{item.key}#{@right_char}", values[index].to_s)
119
+ raise "Key #{item.key} not found in template" unless success
120
+ end
121
+ return values
122
+ end
123
+
124
+ # If this is set it will enforce that buffer data is encoded
125
+ # in a specific encoding
126
+ def enforce_encoding
127
+ return nil
128
+ end
129
+
130
+ # This affects whether the Packet class enforces the buffer
131
+ # length at all. Set to false to remove any correlation between
132
+ # buffer length and defined sizes of items in COSMOS
133
+ def enforce_length
134
+ return false
135
+ end
136
+
137
+ # This sets the short_buffer_allowed flag in the Packet class
138
+ # which allows packets that have a buffer shorter than the defined size.
139
+ # Note that the buffer is still resized to the defined length
140
+ def enforce_short_buffer_allowed
141
+ return true
142
+ end
143
+
144
+ # If this is true it will enfore that COSMOS DERIVED items must have a
145
+ # write_conversion to be written
146
+ def enforce_derived_write_conversion(_item)
147
+ return true
148
+ end
149
+ end
150
+ end
@@ -68,19 +68,29 @@ module OpenC3
68
68
  doc.to_xml
69
69
  end
70
70
 
71
+ # If this is set it will enforce that buffer data is encoded
72
+ # in a specific encoding
71
73
  def enforce_encoding
72
74
  return nil
73
75
  end
74
76
 
77
+ # This affects whether the Packet class enforces the buffer
78
+ # length at all. Set to false to remove any correlation between
79
+ # buffer length and defined sizes of items in COSMOS
75
80
  def enforce_length
76
81
  return false
77
82
  end
78
83
 
84
+ # This sets the short_buffer_allowed flag in the Packet class
85
+ # which allows packets that have a buffer shorter than the defined size.
86
+ # Note that the buffer is still resized to the defined length
79
87
  def enforce_short_buffer_allowed
80
88
  return true
81
89
  end
82
90
 
83
- def enforce_derived_write_conversion(item)
91
+ # If this is true it will enfore that COSMOS DERIVED items must have a
92
+ # write_conversion to be written
93
+ def enforce_derived_write_conversion(_item)
84
94
  return true
85
95
  end
86
96
  end
@@ -25,4 +25,5 @@ module OpenC3
25
25
  autoload(:HttpAccessor, 'openc3/accessors/http_accessor.rb')
26
26
  autoload(:JsonAccessor, 'openc3/accessors/json_accessor.rb')
27
27
  autoload(:XmlAccessor, 'openc3/accessors/xml_accessor.rb')
28
+ autoload(:TemplateAccessor, 'openc3/accessors/template_accessor.rb')
28
29
  end