openc3 5.13.0 → 5.14.0

Sign up to get free protection for your applications and to get access to all the features.
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