openc3 5.15.2 → 5.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Rakefile +1 -0
  4. data/bin/openc3cli +20 -0
  5. data/bin/pipinstall +3 -0
  6. data/data/config/interface_modifiers.yaml +4 -1
  7. data/data/config/telemetry_modifiers.yaml +6 -1
  8. data/ext/openc3/ext/burst_protocol/burst_protocol.c +317 -0
  9. data/ext/openc3/ext/burst_protocol/extconf.rb +13 -0
  10. data/lib/openc3/accessors/accessor.rb +1 -1
  11. data/lib/openc3/api/tlm_api.rb +1 -1
  12. data/lib/openc3/interfaces/http_client_interface.rb +8 -4
  13. data/lib/openc3/interfaces/http_server_interface.rb +22 -6
  14. data/lib/openc3/interfaces/interface.rb +6 -0
  15. data/lib/openc3/interfaces/linc_interface.rb +5 -3
  16. data/lib/openc3/interfaces/mqtt_interface.rb +7 -3
  17. data/lib/openc3/interfaces/mqtt_stream_interface.rb +8 -1
  18. data/lib/openc3/interfaces/protocols/burst_protocol.rb +104 -100
  19. data/lib/openc3/interfaces/protocols/fixed_protocol.rb +11 -3
  20. data/lib/openc3/interfaces/serial_interface.rb +16 -1
  21. data/lib/openc3/interfaces/simulated_target_interface.rb +7 -3
  22. data/lib/openc3/interfaces/tcpip_client_interface.rb +18 -1
  23. data/lib/openc3/interfaces/tcpip_server_interface.rb +24 -15
  24. data/lib/openc3/interfaces/udp_interface.rb +11 -1
  25. data/lib/openc3/logs/packet_log_writer.rb +1 -1
  26. data/lib/openc3/microservices/decom_microservice.rb +3 -2
  27. data/lib/openc3/microservices/interface_microservice.rb +5 -5
  28. data/lib/openc3/models/activity_model.rb +104 -40
  29. data/lib/openc3/models/gem_model.rb +1 -1
  30. data/lib/openc3/models/plugin_model.rb +5 -3
  31. data/lib/openc3/models/python_package_model.rb +15 -5
  32. data/lib/openc3/models/scope_model.rb +1 -1
  33. data/lib/openc3/models/target_model.rb +1 -1
  34. data/lib/openc3/packets/packet.rb +27 -24
  35. data/lib/openc3/packets/packet_config.rb +18 -1
  36. data/lib/openc3/packets/parsers/packet_item_parser.rb +10 -6
  37. data/lib/openc3/packets/structure.rb +7 -7
  38. data/lib/openc3/packets/structure_item.rb +4 -2
  39. data/lib/openc3/script/api_shared.rb +33 -29
  40. data/lib/openc3/script/plugins.rb +13 -13
  41. data/lib/openc3/version.rb +6 -6
  42. data/templates/tool_angular/package.json +8 -8
  43. data/templates/tool_react/package.json +2 -2
  44. data/templates/tool_svelte/build/smui.css +1 -5
  45. data/templates/tool_svelte/package.json +3 -3
  46. data/templates/tool_vue/package.json +12 -12
  47. data/templates/widget/package.json +11 -11
  48. metadata +21 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a39dab08bb9810376520e75a7bf3a6c63d30ad54b93566b82a849d780693a366
4
- data.tar.gz: 65d282829dba0706cbe0e32603e51ad8ab3dfc0fdaf37d9bd400787bb7a1cb03
3
+ metadata.gz: af3e74fa7b78038906c1b2120e62aa7a9b3d835effe03dbd96e500d737a443cb
4
+ data.tar.gz: 8bba305bdd1ac061300aa8676564c0966cf01d68df8da86adfc5bf05d873165f
5
5
  SHA512:
6
- metadata.gz: 12bffefe104e90e159c16bcc54ab53745e86a97bfb762c7e0e25141d6bd3c91ad6bb8827017d915dfb459b2fc69ea7365c97e7fa22236abb16ff0d73d8d485d7
7
- data.tar.gz: b2efa2780f97e2aa3392cc483534d949be4fb27032dbc3e52015ebfa89da08d234e5777c50dbfa09e477357d3b5ca67aba847f8f5d723676d2331da84e880f7f
6
+ metadata.gz: '09554021246cc00fca2b1f32e627274eca5ff5ea6fa5851175e2b86cba6b9ff07ef5a05e4cc13a40ee6239793d74557d956384b8fb25acf267721b21208c2fa1'
7
+ data.tar.gz: 6db1a30df9c512df371b69240649947fd40ec78409d94bf7ff466096180c4ebf39958d2247b15e8b50e5a84b4fa066e461e38bad5fa8cc0bc1f7d4b8982112ab
data/Gemfile CHANGED
@@ -8,7 +8,7 @@ gemspec :name => 'openc3'
8
8
 
9
9
  # Include the rails gems for the convenience of custom microservice plugins
10
10
  gem 'bootsnap', '>= 1.9.3', require: false
11
- gem 'mock_redis', '0.41'
11
+ gem 'mock_redis', '0.44'
12
12
  gem 'rack-cors', '~> 2.0'
13
13
  gem 'rails', '~> 7.1.0'
14
14
  gem 'rspec-rails', '~> 6.0'
data/Rakefile CHANGED
@@ -53,6 +53,7 @@ task :build => [:devkit] do
53
53
  shared_extension = 'bundle' if /darwin/.match?(platform)
54
54
 
55
55
  extensions = [
56
+ 'burst_protocol',
56
57
  'crc',
57
58
  'polynomial_conversion',
58
59
  'config_parser',
data/bin/openc3cli CHANGED
@@ -66,6 +66,7 @@ def print_usage
66
66
  puts " cli irb # Runs irb in the local directory"
67
67
  puts " cli validate /PATH/FILENAME.gem SCOPE variables.txt # Validate a COSMOS plugin gem file"
68
68
  puts " cli load /PATH/FILENAME.gem SCOPE variables.txt # Loads a COSMOS plugin gem file"
69
+ puts " cli list <SCOPE> # Lists installed plugins, SCOPE is DEFAULT if not given"
69
70
  puts " cli generate TYPE OPTIONS # Generate various COSMOS entities"
70
71
  puts " OPTIONS: --ruby or --python to specify the language in the generated code"
71
72
  puts " #{MIGRATE_PARSER}"
@@ -381,6 +382,22 @@ def wait_process_complete(process_name)
381
382
  end
382
383
  end
383
384
 
385
+ # Outputs list of installed plugins
386
+ def list_plugins(scope:)
387
+ scope ||= 'DEFAULT'
388
+ check_environment()
389
+ names = []
390
+ if $openc3_in_cluster
391
+ names = OpenC3::PluginModel.names(scope: scope)
392
+ else
393
+ require 'openc3/script'
394
+ names = plugin_list(scope: scope)
395
+ end
396
+ names.each do |name|
397
+ puts name
398
+ end
399
+ end
400
+
384
401
  # Loads a plugin into the OpenC3 system
385
402
  # This code is used from the command line and is the same code that gets called if you
386
403
  # edit/upgrade or install a new plugin from the Admin interface
@@ -655,6 +672,9 @@ if not ARGV[0].nil? # argument(s) given
655
672
  # See plugins_controller.rb install for usage
656
673
  load_plugin(ARGV[1], scope: ARGV[2], plugin_hash_file: ARGV[3], force: ARGV[4] == 'force')
657
674
 
675
+ when 'list'
676
+ list_plugins(scope: ARGV[1])
677
+
658
678
  when 'unload'
659
679
  unload_plugin(ARGV[1], scope: ARGV[2])
660
680
 
data/bin/pipinstall CHANGED
@@ -6,4 +6,7 @@ if [ $? -eq 0 ]; then
6
6
  else
7
7
  echo "Command failed - retrying with --no-index"
8
8
  pip install --no-index "$@"
9
+ if [ $? -eq 0 ]; then
10
+ echo "ERROR: pip install failed"
11
+ fi
9
12
  fi
@@ -127,7 +127,7 @@ OPTION:
127
127
  The option to set. OpenC3 defines several options on the core provided
128
128
  interfaces. The SerialInterface defines FLOW_CONTROL which can be NONE (default) or RTSCTS
129
129
  and DATA_BITS which changes the data bits of the serial interface.
130
- The TcpipServerInterface defines LISTEN_ADDRESS which is the IP address to accept
130
+ The TcpipServerInterface and HttpServerInterface define LISTEN_ADDRESS which is the IP address to accept
131
131
  connections on (default 0.0.0.0).
132
132
  values: .*
133
133
  - name: Parameters
@@ -138,6 +138,9 @@ OPTION:
138
138
  INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 115200 NONE 1 10.0 nil
139
139
  OPTION FLOW_CONTROL RTSCTS
140
140
  OPTION DATA_BITS 8
141
+ ROUTER SERIAL_ROUTER tcpip_server_interface.rb 2950 2950 10.0 nil BURST
142
+ ROUTE SERIAL_INT
143
+ OPTION LISTEN_ADDRESS 127.0.0.1
141
144
  SECRET:
142
145
  summary: Define a secret needed by this interface
143
146
  description: Defines a secret for this interface and optionally assigns its value to an option
@@ -170,4 +170,9 @@ ACCESSOR:
170
170
  required: true
171
171
  description: The name of the accessor class
172
172
  values: .+
173
- since: 5.0.10
173
+ since: 5.0.10
174
+ IGNORE_OVERLAP:
175
+ summary: Ignores any packet items which overlap
176
+ description: Packet items which overlap normally generate a warning unless each individual item has the OVERLAP keyword.
177
+ This ignores overlaps across the entire packet.
178
+ since: 5.15.3
@@ -0,0 +1,317 @@
1
+ /*
2
+ # Copyright 2024 OpenC3, Inc.
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
+ # This file may also be used under the terms of a commercial license
16
+ # if purchased from OpenC3, Inc.
17
+ */
18
+
19
+ #include "ruby.h"
20
+ #include "stdio.h"
21
+
22
+ static VALUE mOpenC3 = Qnil;
23
+ static VALUE cProtocol = Qnil;
24
+ static VALUE cBurstProtocol = Qnil;
25
+
26
+ static ID id_method_handle_sync_pattern = 0;
27
+ static ID id_method_reduce_to_single_packet = 0;
28
+ static ID id_method_replace = 0;
29
+ static ID id_method_clone = 0;
30
+ static ID id_method_log_discard = 0;
31
+
32
+ static ID id_ivar_data = 0;
33
+ static ID id_ivar_extra = 0;
34
+ static ID id_ivar_sync_pattern = 0;
35
+ static ID id_ivar_sync_state = 0;
36
+ static ID id_ivar_discard_leading_bytes = 0;
37
+
38
+ static VALUE symbol_RESYNC = Qnil;
39
+ static VALUE symbol_SEARCHING = Qnil;
40
+ static VALUE symbol_DISCONNECT = Qnil;
41
+ static VALUE symbol_STOP = Qnil;
42
+ static VALUE symbol_FOUND = Qnil;
43
+
44
+ /* Reads from the interface. It can look for a sync pattern before
45
+ * creating a Packet. It can discard a set number of bytes at the beginning
46
+ * before creating the Packet.
47
+ *
48
+ * Note: On the first call to this from any interface read(), data will contain a blank
49
+ * string. Blank string is an opportunity for protocols to return any queued up packets.
50
+ * If they have no queued up packets, they should pass the blank string down to chained
51
+ * protocols giving them the same opportunity.
52
+ *
53
+ * @return [String|nil] Data for a packet consisting of the bytes read */
54
+ static VALUE burst_protocol_read_data(int argc, VALUE *argv, VALUE self)
55
+ {
56
+ /* Arguments */
57
+ volatile VALUE data = Qnil;
58
+ volatile VALUE extra = Qnil;
59
+
60
+ /* Internal variables */
61
+ volatile VALUE result = Qnil;
62
+ volatile VALUE control = Qnil;
63
+ volatile VALUE packet_data = Qnil;
64
+ volatile VALUE super_args[3] = {Qnil, Qnil, Qnil};
65
+
66
+ long discard_leading_bytes = 0;
67
+
68
+ switch (argc)
69
+ {
70
+ case 1:
71
+ data = argv[0];
72
+ break;
73
+ case 2:
74
+ data = argv[0];
75
+ extra = argv[1];
76
+ break;
77
+ default:
78
+ /* Invalid number of arguments given */
79
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
80
+ break;
81
+ };
82
+
83
+ rb_str_concat(rb_ivar_get(self, id_ivar_data), data);
84
+ rb_ivar_set(self, id_ivar_extra, extra);
85
+
86
+ while (1)
87
+ {
88
+ control = rb_funcall(self, id_method_handle_sync_pattern, 0);
89
+ /* Only return here if not blank string test */
90
+ if (RTEST(control) && (RSTRING_LEN(data) > 0))
91
+ {
92
+ return control;
93
+ }
94
+
95
+ /* Reduce the data to a single packet */
96
+ result = rb_funcall(self, id_method_reduce_to_single_packet, 0);
97
+ if (RB_TYPE_P(result, T_ARRAY))
98
+ {
99
+ if (RARRAY_LEN(result) > 0)
100
+ {
101
+ packet_data = rb_ary_entry(result, 0);
102
+ if (RARRAY_LEN(result) > 1)
103
+ {
104
+ extra = rb_ary_entry(result, 1);
105
+ }
106
+ else
107
+ {
108
+ extra = Qnil;
109
+ }
110
+ }
111
+ else
112
+ {
113
+ packet_data = Qnil;
114
+ extra = Qnil;
115
+ }
116
+ }
117
+ else
118
+ {
119
+ packet_data = result;
120
+ extra = Qnil;
121
+ }
122
+ if (packet_data == symbol_RESYNC)
123
+ {
124
+ rb_ivar_set(self, id_ivar_sync_state, symbol_SEARCHING);
125
+
126
+ /* Only immediately resync if not blank string test */
127
+ if (RSTRING_LEN(data) > 0)
128
+ {
129
+ continue;
130
+ }
131
+ }
132
+
133
+ /* Potentially allow blank string to be sent to other protocols if no packet is ready in this one */
134
+ if (SYMBOL_P(packet_data))
135
+ {
136
+ if ((RSTRING_LEN(data) <= 0) && (packet_data != symbol_DISCONNECT))
137
+ {
138
+ /* On blank string test, return blank string (unless we had a packet or need disconnect)
139
+ * The base class handles the special case of returning STOP if on the last protocol in the
140
+ * chain */
141
+ super_args[0] = data;
142
+ super_args[1] = extra;
143
+ return rb_call_super(2, (VALUE *)super_args);
144
+ }
145
+ else
146
+ {
147
+ /* Return any control code if not on blank string test */
148
+ result = rb_ary_new();
149
+ rb_ary_push(result, packet_data);
150
+ rb_ary_push(result, extra);
151
+ return result;
152
+ }
153
+ }
154
+
155
+ rb_ivar_set(self, id_ivar_sync_state, symbol_SEARCHING);
156
+
157
+ /* Discard leading bytes if necessary */
158
+ if (FIX2INT(rb_ivar_get(self, id_ivar_discard_leading_bytes)) > 0)
159
+ {
160
+ discard_leading_bytes = FIX2INT(rb_ivar_get(self, id_ivar_discard_leading_bytes));
161
+ rb_str_replace(packet_data, rb_str_substr(packet_data, discard_leading_bytes, RSTRING_LEN(packet_data) - discard_leading_bytes));
162
+ }
163
+
164
+ result = rb_ary_new();
165
+ rb_ary_push(result, packet_data);
166
+ rb_ary_push(result, extra);
167
+ return result;
168
+ }
169
+ }
170
+
171
+ /* @return [Boolean] control code (nil, :STOP) */
172
+ static VALUE burst_protocol_handle_sync_pattern(VALUE self)
173
+ {
174
+ volatile VALUE sync_pattern = rb_ivar_get(self, id_ivar_sync_pattern);
175
+ volatile VALUE data = Qnil;
176
+ long sync_index = -1;
177
+ char *char_data = NULL;
178
+ char *char_sync_pattern = NULL;
179
+ long data_length = 0;
180
+ long sync_pattern_length = 0;
181
+ long i = 0;
182
+ long index = 0;
183
+ int found = 0;
184
+
185
+ if (RTEST(sync_pattern) && (rb_ivar_get(self, id_ivar_sync_state) == symbol_SEARCHING))
186
+ {
187
+ data = rb_ivar_get(self, id_ivar_data);
188
+ char_sync_pattern = RSTRING_PTR(sync_pattern);
189
+
190
+ while (1)
191
+ {
192
+ data_length = RSTRING_LEN(data);
193
+ sync_pattern_length = RSTRING_LEN(sync_pattern);
194
+
195
+ /* Make sure we have some data to look for a sync word in */
196
+ if (data_length < sync_pattern_length)
197
+ {
198
+ return symbol_STOP;
199
+ }
200
+
201
+ /* Find the beginning of the sync pattern */
202
+ sync_index = -1;
203
+ char_data = RSTRING_PTR(data);
204
+ for (i = 0; i < data_length; i++)
205
+ {
206
+ if (char_data[i] == char_sync_pattern[0])
207
+ {
208
+ sync_index = i;
209
+ break;
210
+ }
211
+ }
212
+
213
+ if (sync_index != -1)
214
+ {
215
+ /* Make sure we have enough data for the whole sync pattern past this index */
216
+ if (data_length < (sync_index + sync_pattern_length))
217
+ {
218
+ return symbol_STOP;
219
+ }
220
+
221
+ /* Check for the rest of the sync pattern */
222
+ found = 1;
223
+ index = sync_index;
224
+ for (i = 0; i < sync_pattern_length; i++)
225
+ {
226
+ if (char_data[index] != char_sync_pattern[i])
227
+ {
228
+ found = 0;
229
+ break;
230
+ }
231
+ index += 1;
232
+ }
233
+
234
+ if (found)
235
+ {
236
+ if (sync_index != 0)
237
+ {
238
+ rb_funcall(self, id_method_log_discard, 2, INT2FIX(sync_index), Qtrue);
239
+ /* Delete Data Before Sync Pattern */
240
+ rb_str_replace(data, rb_str_substr(data, sync_index, RSTRING_LEN(data) - sync_index));
241
+ }
242
+ rb_ivar_set(self, id_ivar_sync_state, symbol_FOUND);
243
+ return Qnil;
244
+ }
245
+ else
246
+ {
247
+ rb_funcall(self, id_method_log_discard, 2, INT2FIX(sync_index + 1), Qfalse);
248
+ /* Delete Data Before and including first character of suspected sync Pattern */
249
+ rb_str_replace(data, rb_str_substr(data, sync_index + 1, RSTRING_LEN(data) - sync_index - 1));
250
+ continue;
251
+ } /* if found */
252
+ }
253
+ else
254
+ {
255
+ rb_funcall(self, id_method_log_discard, 2, INT2FIX(data_length), Qfalse);
256
+ rb_str_replace(data, rb_str_new2(""));
257
+ return symbol_STOP;
258
+ }
259
+ } /* end loop */
260
+ } /* if @sync_pattern */
261
+
262
+ return Qnil;
263
+ }
264
+
265
+ static VALUE burst_protocol_reduce_to_single_packet(VALUE self)
266
+ {
267
+ volatile VALUE result = Qnil;
268
+ volatile VALUE packet_data = Qnil;
269
+ volatile VALUE data = rb_ivar_get(self, id_ivar_data);
270
+
271
+ if (RSTRING_LEN(data) <= 0)
272
+ {
273
+ /* Need some data */
274
+ return symbol_STOP;
275
+ }
276
+
277
+ /* Reduce to packet data and clear data for next packet */
278
+ packet_data = rb_funcall(data, id_method_clone, 0);
279
+ rb_str_replace(data, rb_str_new2(""));
280
+
281
+ result = rb_ary_new();
282
+ rb_ary_push(result, packet_data);
283
+ rb_ary_push(result, rb_ivar_get(self, id_ivar_extra));
284
+ return result;
285
+ }
286
+
287
+ /*
288
+ * Initialize all BurstProtocol methods
289
+ */
290
+ void Init_burst_protocol(void)
291
+ {
292
+ mOpenC3 = rb_define_module("OpenC3");
293
+
294
+ symbol_RESYNC = ID2SYM(rb_intern("RESYNC"));
295
+ symbol_SEARCHING = ID2SYM(rb_intern("SEARCHING"));
296
+ symbol_DISCONNECT = ID2SYM(rb_intern("DISCONNECT"));
297
+ symbol_STOP = ID2SYM(rb_intern("STOP"));
298
+ symbol_FOUND = ID2SYM(rb_intern("FOUND"));
299
+
300
+ id_method_handle_sync_pattern = rb_intern("handle_sync_pattern");
301
+ id_method_reduce_to_single_packet = rb_intern("reduce_to_single_packet");
302
+ id_method_replace = rb_intern("replace");
303
+ id_method_clone = rb_intern("clone");
304
+ id_method_log_discard = rb_intern("log_discard");
305
+
306
+ id_ivar_data = rb_intern("@data");
307
+ id_ivar_extra = rb_intern("@extra");
308
+ id_ivar_sync_pattern = rb_intern("@sync_pattern");
309
+ id_ivar_sync_state = rb_intern("@sync_state");
310
+ id_ivar_discard_leading_bytes = rb_intern("@discard_leading_bytes");
311
+
312
+ cProtocol = rb_define_class_under(mOpenC3, "Protocol", rb_cObject);
313
+ cBurstProtocol = rb_define_class_under(mOpenC3, "BurstProtocol", cProtocol);
314
+ rb_define_method(cBurstProtocol, "read_data", burst_protocol_read_data, -1);
315
+ rb_define_method(cBurstProtocol, "reduce_to_single_packet", burst_protocol_reduce_to_single_packet, 0);
316
+ rb_define_method(cBurstProtocol, "handle_sync_pattern", burst_protocol_handle_sync_pattern, 0);
317
+ }
@@ -0,0 +1,13 @@
1
+ require 'mkmf'
2
+
3
+ unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O3')
4
+ $CFLAGS << ' -O3'
5
+ end
6
+ if /gcc/.match?(CONFIG['CC'])
7
+ $CFLAGS << ' -Wall'
8
+ if $DEBUG && !$CFLAGS.gsub!(/ -O[\dsz]?/, ' -O0 -ggdb')
9
+ $CFLAGS << ' -O0 -ggdb'
10
+ end
11
+ end
12
+
13
+ create_makefile 'openc3/ext/burst_protocol'
@@ -105,7 +105,7 @@ module OpenC3
105
105
 
106
106
  def self.convert_to_type(value, item)
107
107
  case item.data_type
108
- when :OBJECT
108
+ when :OBJECT, :ARRAY
109
109
  # Do nothing for complex object types
110
110
  when :STRING, :BLOCK
111
111
  if item.array_size
@@ -458,7 +458,7 @@ module OpenC3
458
458
  raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
459
459
  end
460
460
  if target_name.nil? or packet_name.nil? or item_name.nil?
461
- raise "ERROR: Target name, packet name, and item name are required. Usage: #{method_name}(\"TGT PKT ITEM\") or #{method_name}(\"TGT\", \"PKT\", \"ITEM\")"
461
+ raise "ERROR: Target name, packet name and item name are required. Usage: #{method_name}(\"TGT PKT ITEM\") or #{method_name}(\"TGT\", \"PKT\", \"ITEM\")"
462
462
  end
463
463
  return [target_name, packet_name, item_name]
464
464
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2023 OpenC3, Inc.
3
+ # Copyright 2024 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is free software; you can modify and/or redistribute it
@@ -34,10 +34,10 @@ module OpenC3
34
34
  @hostname = hostname
35
35
  @port = Integer(port)
36
36
  @protocol = protocol
37
- if (port == 80 and protocol == 'http') or (port == 443 and protocol == 'https')
38
- @url = "#{protocol}://#{hostname}"
37
+ if (@port == 80 and @protocol == 'http') or (@port == 443 and @protocol == 'https')
38
+ @url = "#{@protocol}://#{@hostname}"
39
39
  else
40
- @url = "#{protocol}://#{hostname}:#{port}"
40
+ @url = "#{@protocol}://#{@hostname}:#{@port}"
41
41
  end
42
42
  @write_timeout = ConfigParser.handle_nil(write_timeout)
43
43
  @write_timeout = Float(@write_timeout) if @write_timeout
@@ -50,6 +50,10 @@ module OpenC3
50
50
  @response_queue = Queue.new
51
51
  end
52
52
 
53
+ def connection_string
54
+ return @url
55
+ end
56
+
53
57
  # Connects the interface to its target(s)
54
58
  def connect
55
59
  # Per https://github.com/lostisland/faraday/blob/main/lib/faraday/options/env.rb
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2023 OpenC3, Inc.
3
+ # Copyright 2024 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is free software; you can modify and/or redistribute it
@@ -26,14 +26,30 @@ module OpenC3
26
26
  # @param port [Integer] HTTP port
27
27
  def initialize(port = 80)
28
28
  super()
29
+ @listen_address = '0.0.0.0' # Default to ANY
29
30
  @port = Integer(port)
30
31
  @server = nil
31
32
  @request_queue = Queue.new
32
33
  end
33
34
 
35
+ # Supported Options
36
+ # LISTEN_ADDRESS - Ip address of the interface to accept connections on
37
+ # (see Interface#set_option)
38
+ def set_option(option_name, option_values)
39
+ super(option_name, option_values)
40
+ case option_name.upcase
41
+ when 'LISTEN_ADDRESS'
42
+ @listen_address = option_values[0]
43
+ end
44
+ end
45
+
46
+ def connection_string
47
+ return "listening on #{@listen_address}:#{@port}"
48
+ end
49
+
34
50
  # Connects the interface to its target(s)
35
51
  def connect
36
- @server = WEBrick::HTTPServer.new :Port => @port
52
+ @server = WEBrick::HTTPServer.new(:BindAddress => @listen_address, :Port => @port)
37
53
  @request_queue = Queue.new
38
54
 
39
55
  # Create a response hook for every command packet
@@ -43,9 +59,9 @@ module OpenC3
43
59
  path = nil
44
60
  begin
45
61
  path = packet.read('HTTP_PATH')
46
- rescue => err
62
+ rescue => e
47
63
  # No HTTP_PATH is an error
48
- Logger.error("HttpServerInterface Packet #{target_name} #{packet_name} unable to read HTTP_PATH\n#{err.formatted}")
64
+ Logger.error("HttpServerInterface Packet #{target_name} #{packet_name} unable to read HTTP_PATH\n#{e.formatted}")
49
65
  end
50
66
  if path
51
67
  @server.mount_proc path do |req, res|
@@ -145,7 +161,7 @@ module OpenC3
145
161
 
146
162
  # Writes to the socket
147
163
  # @param data [Hash] For the HTTP Interface, data is a hash with the needed request info
148
- def write_interface(data, extra = nil)
164
+ def write_interface(_data, _extra = nil)
149
165
  raise "Commands cannot be sent to HttpServerInterface"
150
166
  end
151
167
 
@@ -176,7 +192,7 @@ module OpenC3
176
192
  #
177
193
  # @param packet [Packet] Packet to extract data from
178
194
  # @return data
179
- def convert_packet_to_data(packet)
195
+ def convert_packet_to_data(_packet)
180
196
  raise "Commands cannot be sent to HttpServerInterface"
181
197
  end
182
198
  end
@@ -184,6 +184,12 @@ module OpenC3
184
184
  @scheduler = nil
185
185
  end
186
186
 
187
+ # Should be implemented by subclass to return human readable connection string
188
+ # which will be placed in log messages when connecting and during connection failures
189
+ def connection_string
190
+ return @name
191
+ end
192
+
187
193
  # Connects the interface to its target(s). Must be implemented by a
188
194
  # subclass.
189
195
  def connect
@@ -17,13 +17,15 @@
17
17
  # All changes Copyright 2022, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
- # This file may also be used under the terms of a commercial license
20
+ # This file may also be used under the terms of a commercial license
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'openc3/interfaces/tcpip_client_interface'
24
24
  require 'uuidtools'
25
25
 
26
26
  module OpenC3
27
+ # TODO: Deprecated ... Will remove in next major version of COSMOS (COSMOS 6)
28
+
27
29
  # Interface for connecting to Ball Aerospace LINC Labview targets
28
30
  class LincInterface < TcpipClientInterface
29
31
  # The maximum number of asynchronous commands we can wait for at a time.
@@ -241,7 +243,7 @@ module OpenC3
241
243
  end
242
244
 
243
245
  process_handshake_results(handshake_cmd)
244
- rescue Exception => err
246
+ rescue Exception => e
245
247
  # If anything goes wrong after successfully writing the packet to the LINC target
246
248
  # ensure that the packet gets updated in the CVT and logged to the packet log writer.
247
249
  # OpenC3 normally only does this if write returns successfully
@@ -256,7 +258,7 @@ module OpenC3
256
258
  packet_log_writer_pair.cmd_log_writer.write(packet)
257
259
  end
258
260
 
259
- raise err
261
+ raise e
260
262
  end
261
263
 
262
264
  def process_handshake_results(handshake_cmd)
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2022 OpenC3, Inc.
3
+ # Copyright 2024 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is free software; you can modify and/or redistribute it
@@ -108,8 +108,8 @@ module OpenC3
108
108
 
109
109
  # Build list of packets by topic
110
110
  @read_packets_by_topic = {}
111
- System.telemetry.all.each do |target_name, target_packets|
112
- target_packets.each do |packet_name, packet|
111
+ System.telemetry.all.each do |_target_name, target_packets|
112
+ target_packets.each do |_packet_name, packet|
113
113
  topics = packet.meta['TOPIC']
114
114
  topics = packet.meta['TOPICS'] unless topics
115
115
  if topics
@@ -121,6 +121,10 @@ module OpenC3
121
121
  end
122
122
  end
123
123
 
124
+ def connection_string
125
+ return "#{@hostname}:#{@port} (ssl: #{@ssl})"
126
+ end
127
+
124
128
  # Connects the interface to its target(s)
125
129
  def connect
126
130
  @write_topics = []
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2023 OpenC3, Inc.
3
+ # Copyright 2024 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,13 @@ module OpenC3
38
38
  @ca_file = nil
39
39
  end
40
40
 
41
+ def connection_string
42
+ result = "#{@hostname}:#{@port} (ssl: #{@ssl})"
43
+ result += " write topic: #{@write_topic}" if @write_topic
44
+ result += " read topic: #{@read_topic}" if @read_topic
45
+ return result
46
+ end
47
+
41
48
  # Creates a new {SerialStream} using the parameters passed in the constructor
42
49
  def connect
43
50
  @stream = MqttStream.new(@hostname, @port, @ssl, @write_topic, @read_topic)