openc3 5.15.2 → 5.16.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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Rakefile +1 -0
- data/bin/openc3cli +20 -0
- data/bin/pipinstall +3 -0
- data/data/config/interface_modifiers.yaml +4 -1
- data/data/config/telemetry_modifiers.yaml +6 -1
- data/ext/openc3/ext/burst_protocol/burst_protocol.c +317 -0
- data/ext/openc3/ext/burst_protocol/extconf.rb +13 -0
- data/lib/openc3/accessors/accessor.rb +1 -1
- data/lib/openc3/api/tlm_api.rb +1 -1
- data/lib/openc3/interfaces/http_client_interface.rb +8 -4
- data/lib/openc3/interfaces/http_server_interface.rb +22 -6
- data/lib/openc3/interfaces/interface.rb +6 -0
- data/lib/openc3/interfaces/linc_interface.rb +5 -3
- data/lib/openc3/interfaces/mqtt_interface.rb +7 -3
- data/lib/openc3/interfaces/mqtt_stream_interface.rb +8 -1
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +104 -100
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +11 -3
- data/lib/openc3/interfaces/serial_interface.rb +16 -1
- data/lib/openc3/interfaces/simulated_target_interface.rb +7 -3
- data/lib/openc3/interfaces/tcpip_client_interface.rb +18 -1
- data/lib/openc3/interfaces/tcpip_server_interface.rb +24 -15
- data/lib/openc3/interfaces/udp_interface.rb +11 -1
- data/lib/openc3/logs/packet_log_writer.rb +1 -1
- data/lib/openc3/microservices/decom_microservice.rb +3 -2
- data/lib/openc3/microservices/interface_microservice.rb +5 -5
- data/lib/openc3/models/activity_model.rb +104 -40
- data/lib/openc3/models/gem_model.rb +1 -1
- data/lib/openc3/models/plugin_model.rb +5 -3
- data/lib/openc3/models/python_package_model.rb +15 -5
- data/lib/openc3/models/scope_model.rb +1 -1
- data/lib/openc3/models/target_model.rb +1 -1
- data/lib/openc3/packets/packet.rb +27 -24
- data/lib/openc3/packets/packet_config.rb +18 -1
- data/lib/openc3/packets/parsers/packet_item_parser.rb +10 -6
- data/lib/openc3/packets/structure.rb +7 -7
- data/lib/openc3/packets/structure_item.rb +4 -2
- data/lib/openc3/script/api_shared.rb +33 -29
- data/lib/openc3/script/plugins.rb +13 -13
- data/lib/openc3/version.rb +6 -6
- data/templates/tool_angular/package.json +8 -8
- data/templates/tool_react/package.json +2 -2
- data/templates/tool_svelte/build/smui.css +1 -5
- data/templates/tool_svelte/package.json +3 -3
- data/templates/tool_vue/package.json +12 -12
- data/templates/widget/package.json +11 -11
- metadata +21 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af3e74fa7b78038906c1b2120e62aa7a9b3d835effe03dbd96e500d737a443cb
|
4
|
+
data.tar.gz: 8bba305bdd1ac061300aa8676564c0966cf01d68df8da86adfc5bf05d873165f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
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
@@ -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
|
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'
|
data/lib/openc3/api/tlm_api.rb
CHANGED
@@ -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
|
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
|
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
|
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 =>
|
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#{
|
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(
|
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(
|
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 =>
|
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
|
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
|
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 |
|
112
|
-
target_packets.each do |
|
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
|
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)
|