fprime-gds 4.0.2a1__py3-none-any.whl → 4.0.2a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fprime_gds/common/decoders/ch_decoder.py +1 -1
- fprime_gds/common/decoders/event_decoder.py +1 -1
- fprime_gds/common/decoders/pkt_decoder.py +1 -1
- fprime_gds/common/distributor/distributor.py +1 -1
- fprime_gds/common/encoders/cmd_encoder.py +1 -1
- fprime_gds/common/encoders/encoder.py +1 -1
- fprime_gds/common/encoders/seq_writer.py +1 -1
- fprime_gds/common/gds_cli/base_commands.py +1 -1
- fprime_gds/common/gds_cli/channels.py +1 -1
- fprime_gds/common/gds_cli/command_send.py +1 -1
- fprime_gds/common/gds_cli/events.py +1 -1
- fprime_gds/common/handlers.py +56 -0
- fprime_gds/common/{pipeline → models}/dictionaries.py +1 -0
- fprime_gds/common/pipeline/publishing.py +111 -0
- fprime_gds/common/pipeline/standard.py +7 -21
- fprime_gds/common/utils/config_manager.py +1 -1
- fprime_gds/executables/apps.py +59 -14
- fprime_gds/executables/cli.py +28 -5
- fprime_gds/executables/fprime_cli.py +1 -1
- fprime_gds/executables/run_deployment.py +19 -6
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/METADATA +1 -1
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/RECORD +27 -28
- fprime_gds/common/models/common/channel_telemetry.py +0 -174
- fprime_gds/common/models/common/event.py +0 -121
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/WHEEL +0 -0
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/entry_points.txt +0 -0
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/licenses/LICENSE.txt +0 -0
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/licenses/NOTICE.txt +0 -0
- {fprime_gds-4.0.2a1.dist-info → fprime_gds-4.0.2a2.dist-info}/top_level.txt +0 -0
@@ -41,7 +41,7 @@ class ChDecoder(Decoder):
|
|
41
41
|
|
42
42
|
if config is None:
|
43
43
|
# Retrieve singleton for the configs
|
44
|
-
config = config_manager.ConfigManager
|
44
|
+
config = config_manager.ConfigManager.get_instance()
|
45
45
|
|
46
46
|
self.__dict = ch_dict
|
47
47
|
self.id_obj = config.get_type("FwChanIdType")
|
@@ -43,7 +43,7 @@ class EventDecoder(decoder.Decoder):
|
|
43
43
|
|
44
44
|
if config is None:
|
45
45
|
# Retrieve defaults for the configs
|
46
|
-
config = config_manager.ConfigManager
|
46
|
+
config = config_manager.ConfigManager.get_instance()
|
47
47
|
|
48
48
|
self.__dict = event_dict
|
49
49
|
self.id_obj = config.get_type("FwEventIdType")
|
@@ -41,7 +41,7 @@ class PktDecoder(ChDecoder):
|
|
41
41
|
An initialized PktDecoder object
|
42
42
|
"""
|
43
43
|
if config is None:
|
44
|
-
config = config_manager.ConfigManager
|
44
|
+
config = config_manager.ConfigManager.get_instance()
|
45
45
|
super().__init__(ch_dict, config)
|
46
46
|
|
47
47
|
self.__dict = pkt_name_dict
|
@@ -45,7 +45,7 @@ class Distributor(DataHandler):
|
|
45
45
|
"""
|
46
46
|
if config is None:
|
47
47
|
# Retrieve singleton for the configs, or defaults if singleton unused
|
48
|
-
config = config_manager.ConfigManager
|
48
|
+
config = config_manager.ConfigManager.get_instance()
|
49
49
|
|
50
50
|
self.__decoders = {key.name: [] for key in list(data_desc_type.DataDescType)}
|
51
51
|
|
@@ -68,7 +68,7 @@ class CmdEncoder(encoder.Encoder):
|
|
68
68
|
"""
|
69
69
|
|
70
70
|
if config is None:
|
71
|
-
config = config_manager.ConfigManager
|
71
|
+
config = config_manager.ConfigManager.get_instance()
|
72
72
|
super().__init__(config)
|
73
73
|
|
74
74
|
self.len_obj = self.config.get_type("msg_len")
|
@@ -10,7 +10,7 @@ from typing import Iterable
|
|
10
10
|
|
11
11
|
import fprime_gds.common.gds_cli.filtering_utils as filtering_utils
|
12
12
|
import fprime_gds.common.gds_cli.test_api_utils as test_api_utils
|
13
|
-
from fprime_gds.common.
|
13
|
+
from fprime_gds.common.models.dictionaries import Dictionaries
|
14
14
|
from fprime_gds.common.testing_fw import predicates
|
15
15
|
from fprime_gds.common.testing_fw.api import IntegrationTestAPI
|
16
16
|
from fprime_gds.executables.cli import StandardPipelineParser
|
@@ -7,7 +7,7 @@ from typing import Iterable
|
|
7
7
|
import fprime_gds.common.gds_cli.test_api_utils as test_api_utils
|
8
8
|
from fprime_gds.common.data_types.ch_data import ChData
|
9
9
|
from fprime_gds.common.gds_cli.base_commands import QueryHistoryCommand
|
10
|
-
from fprime_gds.common.
|
10
|
+
from fprime_gds.common.models.dictionaries import Dictionaries
|
11
11
|
from fprime_gds.common.testing_fw import predicates
|
12
12
|
from fprime_gds.common.testing_fw.api import IntegrationTestAPI
|
13
13
|
|
@@ -9,7 +9,7 @@ from fprime.common.models.serialize.type_exceptions import NotInitializedExcepti
|
|
9
9
|
|
10
10
|
import fprime_gds.common.gds_cli.test_api_utils as test_api_utils
|
11
11
|
from fprime_gds.common.gds_cli.base_commands import BaseCommand
|
12
|
-
from fprime_gds.common.
|
12
|
+
from fprime_gds.common.models.dictionaries import Dictionaries
|
13
13
|
from fprime_gds.common.templates.cmd_template import CmdTemplate
|
14
14
|
from fprime_gds.common.testing_fw import predicates
|
15
15
|
from fprime_gds.common.testing_fw.api import IntegrationTestAPI
|
@@ -7,7 +7,7 @@ from typing import Iterable
|
|
7
7
|
import fprime_gds.common.gds_cli.test_api_utils as test_api_utils
|
8
8
|
from fprime_gds.common.data_types.event_data import EventData
|
9
9
|
from fprime_gds.common.gds_cli.base_commands import QueryHistoryCommand
|
10
|
-
from fprime_gds.common.
|
10
|
+
from fprime_gds.common.models.dictionaries import Dictionaries
|
11
11
|
from fprime_gds.common.testing_fw import predicates
|
12
12
|
from fprime_gds.common.testing_fw.api import IntegrationTestAPI
|
13
13
|
|
fprime_gds/common/handlers.py
CHANGED
@@ -37,6 +37,13 @@ class DataHandlerPlugin(DataHandler, abc.ABC):
|
|
37
37
|
data types it handles (whereas DataHandler leaves that up to the registration call). Users shall concretely subclass
|
38
38
|
this class with their own data handling functionality.
|
39
39
|
"""
|
40
|
+
def __init__(self, **kwargs):
|
41
|
+
""" Initialize """
|
42
|
+
self.publisher = None
|
43
|
+
|
44
|
+
def set_publisher(self, publisher):
|
45
|
+
""" Set publishing pipeline """
|
46
|
+
self.publisher = publisher
|
40
47
|
|
41
48
|
@abc.abstractmethod
|
42
49
|
def get_handled_descriptors() -> List[str]:
|
@@ -113,3 +120,52 @@ class HandlerRegistrar(abc.ABC):
|
|
113
120
|
"""
|
114
121
|
for registrant in self._registrants:
|
115
122
|
registrant.data_callback(data, sender)
|
123
|
+
|
124
|
+
|
125
|
+
class MappedRegistrar(abc.ABC):
|
126
|
+
""" Class to register a mapping """
|
127
|
+
|
128
|
+
def __init__(self):
|
129
|
+
""" Initialize an empty registrant list """
|
130
|
+
super().__init__()
|
131
|
+
self._registrants = {}
|
132
|
+
|
133
|
+
def register(self, id, registrant):
|
134
|
+
"""
|
135
|
+
Register a registrant with this registrar associated with the ID. Will be stored and called back when asked to
|
136
|
+
send data to all the handlers registered at the id
|
137
|
+
|
138
|
+
:param id: id to register to
|
139
|
+
:param registrant: handler to register
|
140
|
+
"""
|
141
|
+
self._registrants[id] = self._registrants.get(id, HandlerRegistrar())
|
142
|
+
self._registrants[id].register(registrant)
|
143
|
+
|
144
|
+
def deregister(self, id, registrant):
|
145
|
+
"""
|
146
|
+
Remove a registrant from the registrar such that it will not be called back later. Note: ignores invalid
|
147
|
+
removals by trapping the error, as the desired effect is already satisfied.
|
148
|
+
|
149
|
+
:param id: id to register to
|
150
|
+
:param registrant: registrant to remove
|
151
|
+
:return: True if found, False if not. May safely be ignored.
|
152
|
+
"""
|
153
|
+
try:
|
154
|
+
self._registrants[id].deregister(registrant)
|
155
|
+
return True
|
156
|
+
except (ValueError, KeyError):
|
157
|
+
return False
|
158
|
+
|
159
|
+
def send_to_all(self, id, data, sender=None):
|
160
|
+
"""
|
161
|
+
Sends the given data to all registrants at id.
|
162
|
+
|
163
|
+
:param id: id to send to
|
164
|
+
:param data: data to send back to registrants
|
165
|
+
:param sender: (optional) sender to pass to data_callback
|
166
|
+
"""
|
167
|
+
try:
|
168
|
+
self._registrants[id].send_to_all(data, sender)
|
169
|
+
except KeyError:
|
170
|
+
print("KeyERROR")
|
171
|
+
pass
|
@@ -57,6 +57,7 @@ class Dictionaries:
|
|
57
57
|
|
58
58
|
:param dictionary: dictionary path used for loading dictionaries
|
59
59
|
:param packet_spec: specification for packets, or None, for packetized telemetry
|
60
|
+
:param packet_set_name: name of packet set in case multiple are available
|
60
61
|
"""
|
61
62
|
if Path(dictionary).is_file() and ".json" in Path(dictionary).suffixes:
|
62
63
|
# Events
|
@@ -0,0 +1,111 @@
|
|
1
|
+
"""
|
2
|
+
publishing.py:
|
3
|
+
|
4
|
+
This file contains a basic publishing pipeline. It reads and writes data bound for the GDS.
|
5
|
+
|
6
|
+
:author: lestarch
|
7
|
+
"""
|
8
|
+
|
9
|
+
|
10
|
+
from typing import Type
|
11
|
+
|
12
|
+
from fprime_gds.common.data_types.ch_data import ChData
|
13
|
+
from fprime_gds.common.data_types.event_data import EventData
|
14
|
+
from fprime_gds.common.encoders.ch_encoder import ChEncoder
|
15
|
+
from fprime_gds.common.encoders.event_encoder import EventEncoder
|
16
|
+
from fprime_gds.common.transport import RoutingTag, ThreadedTCPSocketClient
|
17
|
+
from fprime_gds.common.utils.config_manager import ConfigManager
|
18
|
+
|
19
|
+
from fprime_gds.common.handlers import DataHandler, MappedRegistrar
|
20
|
+
from ..models import dictionaries
|
21
|
+
|
22
|
+
|
23
|
+
class PublishingPipeline(DataHandler, MappedRegistrar):
|
24
|
+
""" Pipeline for publishing
|
25
|
+
|
26
|
+
This pipeline sets up the following process:
|
27
|
+
|
28
|
+
Data -> Encoder -> Client -> <wire>
|
29
|
+
"""
|
30
|
+
DEFAULT_ENCODERS = {
|
31
|
+
"FW_PACKET_LOG": EventEncoder,
|
32
|
+
"FW_PACKET_TELEM": ChEncoder
|
33
|
+
}
|
34
|
+
|
35
|
+
def __init__(self):
|
36
|
+
"""
|
37
|
+
Set core variables to None or their composition handlers.
|
38
|
+
"""
|
39
|
+
super().__init__()
|
40
|
+
self.client_socket = None
|
41
|
+
|
42
|
+
self._dictionaries = dictionaries.Dictionaries()
|
43
|
+
self._transport_type = ThreadedTCPSocketClient
|
44
|
+
|
45
|
+
def setup(self, dictionaries):
|
46
|
+
""" Set up the publishing pipeline """
|
47
|
+
self._dictionaries = dictionaries
|
48
|
+
self.client_socket = self.__transport_type()
|
49
|
+
config = ConfigManager.get_instance()
|
50
|
+
|
51
|
+
for id, encoder_class in self.DEFAULT_ENCODERS.items():
|
52
|
+
encoder_instance = encoder_class(config=config)
|
53
|
+
encoder_instance.register(self.client_socket)
|
54
|
+
self.register(id, encoder_instance)
|
55
|
+
|
56
|
+
def data_callback(self, data, sender=None):
|
57
|
+
""" Publish data """
|
58
|
+
if isinstance(data, ChData):
|
59
|
+
self.send_to_all("FW_PACKET_TELEM", data)
|
60
|
+
elif isinstance(data, EventData):
|
61
|
+
self.send_to_all("FW_PACKET_LOG", data)
|
62
|
+
return super().data_callback(data, sender)
|
63
|
+
|
64
|
+
def publish_channel(self, name, value, time):
|
65
|
+
""" Publish channel value using name, time, and value
|
66
|
+
|
67
|
+
Looks up the channel template in the dictionary and constructs a new channel object given the time and value.
|
68
|
+
This ChData object is then sent into the outgoing "publish" pipeline.
|
69
|
+
|
70
|
+
"""
|
71
|
+
template = self._dictionaries.channel_name[name]
|
72
|
+
copied_value_object = template.get_type_obj()(value)
|
73
|
+
copied_value_object.val = value
|
74
|
+
object = ChData(copied_value_object, time, template)
|
75
|
+
return self.data_callback(object, self)
|
76
|
+
|
77
|
+
@property
|
78
|
+
def transport_implementation(self):
|
79
|
+
"""Get implementation type for transport"""
|
80
|
+
return self.__transport_type
|
81
|
+
|
82
|
+
@transport_implementation.setter
|
83
|
+
def transport_implementation(self, transport_type: Type[None]):
|
84
|
+
"""Set the implementation type for transport"""
|
85
|
+
assert (
|
86
|
+
self.client_socket is None
|
87
|
+
), "Cannot setup transport implementation type after setup"
|
88
|
+
self.__transport_type = transport_type
|
89
|
+
|
90
|
+
|
91
|
+
def connect(
|
92
|
+
self, connection_uri, incoming_tag=RoutingTag.GUI, outgoing_tag=RoutingTag.GUI
|
93
|
+
):
|
94
|
+
"""Connects to the middleware layer
|
95
|
+
|
96
|
+
Connect to the middleware layer. This connection needs to identify if the object is a a FSW or GUI client. The
|
97
|
+
default connection acts as a GUI client sending back to the GUI.
|
98
|
+
|
99
|
+
Args:
|
100
|
+
connection_uri: URI of the connection to make
|
101
|
+
incoming_tag: this pipeline will act as supplied tag (GUI, FSW). Default: GUI
|
102
|
+
outgoing_tag: this pipeline will produce data for supplied tag (FSW, GUI). Default: FSW
|
103
|
+
"""
|
104
|
+
self.client_socket.connect(connection_uri, incoming_tag, outgoing_tag)
|
105
|
+
|
106
|
+
def disconnect(self):
|
107
|
+
""" Disconnect from the client socket """
|
108
|
+
if self.client_socket is not None:
|
109
|
+
self.client_socket.disconnect()
|
110
|
+
|
111
|
+
|
@@ -23,7 +23,7 @@ from fprime_gds.common.transport import RoutingTag, ThreadedTCPSocketClient
|
|
23
23
|
from fprime_gds.common.utils.config_manager import ConfigManager
|
24
24
|
|
25
25
|
# Local imports for the sake of composition
|
26
|
-
from . import
|
26
|
+
from . import encoding, files, histories
|
27
27
|
|
28
28
|
|
29
29
|
class StandardPipeline:
|
@@ -49,7 +49,7 @@ class StandardPipeline:
|
|
49
49
|
self.up_store = None
|
50
50
|
self.down_store = None
|
51
51
|
|
52
|
-
self.__dictionaries =
|
52
|
+
self.__dictionaries = None
|
53
53
|
self.__coders = encoding.EncodingDecoding()
|
54
54
|
self.__histories = histories.Histories()
|
55
55
|
self.__filing = files.Filing()
|
@@ -58,11 +58,9 @@ class StandardPipeline:
|
|
58
58
|
def setup(
|
59
59
|
self,
|
60
60
|
config: ConfigManager,
|
61
|
-
|
61
|
+
dictionaries,
|
62
62
|
file_store,
|
63
63
|
logging_prefix=None,
|
64
|
-
packet_spec=None,
|
65
|
-
packet_set_name=None,
|
66
64
|
data_logging_enabled=True
|
67
65
|
):
|
68
66
|
"""
|
@@ -70,14 +68,13 @@ class StandardPipeline:
|
|
70
68
|
patterns. This allows just registering the consumers, and invoking 'setup' all other of the GDS support layer.
|
71
69
|
|
72
70
|
:param config: config object used when constructing the pipeline.
|
73
|
-
:param
|
71
|
+
:param dictionaries: dictionary path. Used to setup loading of dictionaries.
|
74
72
|
:param file_store: uplink/downlink storage directory
|
75
73
|
:param logging_prefix: logging prefix. Defaults to not logging at all.
|
76
74
|
:param packet_spec: location of packetized telemetry XML specification.
|
77
75
|
"""
|
78
|
-
|
79
|
-
|
80
|
-
), f"Dictionary {dictionary} does not exist"
|
76
|
+
self.distributor = fprime_gds.common.distributor.distributor.Distributor(config)
|
77
|
+
self.client_socket = self.__transport_type()
|
81
78
|
# File storage configuration for uplink and downlink
|
82
79
|
self.up_store = Path(file_store) / "fprime-uplink"
|
83
80
|
self.down_store = Path(file_store) / "fprime-downlink"
|
@@ -88,18 +85,7 @@ class StandardPipeline:
|
|
88
85
|
raise PermissionError(
|
89
86
|
f"{file_store} is not writable. Fix permissions or change storage directory with --file-storage-directory."
|
90
87
|
)
|
91
|
-
self.
|
92
|
-
# Loads the distributor and client socket
|
93
|
-
self.distributor = fprime_gds.common.distributor.distributor.Distributor(config)
|
94
|
-
self.client_socket = self.__transport_type()
|
95
|
-
# Setup dictionaries encoders and decoders
|
96
|
-
self.dictionaries.load_dictionaries(
|
97
|
-
self.dictionary_path, packet_spec, packet_set_name
|
98
|
-
)
|
99
|
-
# Update config to use Fw types defined in the JSON dictionary
|
100
|
-
if self.dictionaries.fw_type_name:
|
101
|
-
for fw_type_name, fw_type in self.dictionaries.fw_type_name.items():
|
102
|
-
config.set("types", fw_type_name, fw_type)
|
88
|
+
self.__dictionaries = dictionaries
|
103
89
|
self.coders.setup_coders(
|
104
90
|
self.dictionaries, self.distributor, self.client_socket, config
|
105
91
|
)
|
@@ -40,7 +40,7 @@ class ConfigBadTypeException(Exception):
|
|
40
40
|
config_name (string): Name of the config containing the bad type
|
41
41
|
type_str (string): Bad type string that caused the error
|
42
42
|
"""
|
43
|
-
|
43
|
+
super().__init__(f"Invalid type string {type_str} read in configuration {config_name}")
|
44
44
|
|
45
45
|
|
46
46
|
class ConfigManager(configparser.ConfigParser):
|
fprime_gds/executables/apps.py
CHANGED
@@ -14,8 +14,8 @@ command line that will be spun into its own process.
|
|
14
14
|
import subprocess
|
15
15
|
import sys
|
16
16
|
from abc import ABC, abstractmethod
|
17
|
-
|
18
|
-
from typing import final, List, Dict, Tuple, Type
|
17
|
+
import argparse
|
18
|
+
from typing import final, List, Dict, Tuple, Type, Optional
|
19
19
|
|
20
20
|
from fprime_gds.plugin.definitions import gds_plugin_specification, gds_plugin
|
21
21
|
from fprime_gds.plugin.system import Plugins
|
@@ -23,10 +23,13 @@ from fprime_gds.executables.cli import (
|
|
23
23
|
CompositeParser,
|
24
24
|
ParserBase,
|
25
25
|
BareArgumentParser,
|
26
|
+
MiddleWareParser,
|
27
|
+
DictionaryParser,
|
26
28
|
StandardPipelineParser,
|
27
29
|
PluginArgumentParser,
|
28
30
|
)
|
29
31
|
from fprime_gds.common.pipeline.standard import StandardPipeline
|
32
|
+
from fprime_gds.common.pipeline.publishing import PublishingPipeline
|
30
33
|
|
31
34
|
|
32
35
|
class GdsBaseFunction(ABC):
|
@@ -40,7 +43,7 @@ class GdsBaseFunction(ABC):
|
|
40
43
|
"""
|
41
44
|
|
42
45
|
@abstractmethod
|
43
|
-
def run(self):
|
46
|
+
def run(self, parsed_args):
|
44
47
|
"""Run the start-up function
|
45
48
|
|
46
49
|
Run the start-up function unconstrained by the limitations of running in a dedicated subprocess.
|
@@ -110,13 +113,13 @@ class GdsApp(GdsBaseFunction):
|
|
110
113
|
self.process = None
|
111
114
|
self.arguments = arguments
|
112
115
|
|
113
|
-
def run(self):
|
116
|
+
def run(self, parsed_args):
|
114
117
|
"""Run the application as an isolated process
|
115
118
|
|
116
119
|
GdsFunction objects require an implementation of the `run` command. This implementation will take the arguments
|
117
120
|
provided from `get_process_invocation` function and supplies them as an invocation of the isolated subprocess.
|
118
121
|
"""
|
119
|
-
invocation_arguments = self.get_process_invocation()
|
122
|
+
invocation_arguments = self.get_process_invocation(parsed_args)
|
120
123
|
self.process = subprocess.Popen(invocation_arguments)
|
121
124
|
|
122
125
|
def wait(self, timeout=None):
|
@@ -137,7 +140,9 @@ class GdsApp(GdsBaseFunction):
|
|
137
140
|
return self.process.returncode
|
138
141
|
|
139
142
|
@abstractmethod
|
140
|
-
def get_process_invocation(
|
143
|
+
def get_process_invocation(
|
144
|
+
self, namespace: Optional[argparse.Namespace] = None
|
145
|
+
) -> List[str]:
|
141
146
|
"""Run the start-up function
|
142
147
|
|
143
148
|
Run the start-up function unconstrained by the limitations of running in a dedicated subprocess.
|
@@ -199,6 +204,18 @@ class GdsStandardApp(GdsApp):
|
|
199
204
|
dictionary of flag tuple to argparse kwargs
|
200
205
|
"""
|
201
206
|
return {}
|
207
|
+
|
208
|
+
@classmethod
|
209
|
+
def get_additional_cli_parsers(cls) -> List[ParserBase]:
|
210
|
+
""" Supply a list of CLI parser objects
|
211
|
+
|
212
|
+
Supply a list of CLI parser objects to the CLI system. This allows use of full ParserBase objects instead of
|
213
|
+
the more restrictive dictionary approach seen in get_additional_arguments.
|
214
|
+
|
215
|
+
Returns:
|
216
|
+
list of parser objects as passed to ParserBase
|
217
|
+
"""
|
218
|
+
return []
|
202
219
|
|
203
220
|
@classmethod
|
204
221
|
def init(cls):
|
@@ -230,7 +247,7 @@ class GdsStandardApp(GdsApp):
|
|
230
247
|
"""Start function to contain behavior based in standard pipeline"""
|
231
248
|
raise NotImplementedError()
|
232
249
|
|
233
|
-
def get_process_invocation(self):
|
250
|
+
def get_process_invocation(self, namespace=None):
|
234
251
|
"""Return the process invocation for this class' main
|
235
252
|
|
236
253
|
The process invocation of this application is to run cls.main and supply it a reproduced version of the
|
@@ -247,7 +264,8 @@ class GdsStandardApp(GdsApp):
|
|
247
264
|
composite_parser = CompositeParser(
|
248
265
|
[self.get_cli_parser(), StandardPipelineParser]
|
249
266
|
)
|
250
|
-
namespace
|
267
|
+
if namespace is None:
|
268
|
+
namespace, _, _ = ParserBase.parse_known_args([composite_parser], client=True)
|
251
269
|
args = composite_parser.reproduce_cli_args(namespace)
|
252
270
|
return [sys.executable, "-c", f"import {module}\n{module}.{cls}.main()"] + args
|
253
271
|
|
@@ -261,32 +279,39 @@ class GdsStandardApp(GdsApp):
|
|
261
279
|
[]
|
262
280
|
) # Disable plugin system unless specified through init
|
263
281
|
# In the case where `init` sets up the plugin system, we want to pass the assertion
|
264
|
-
# triggered by the code above that turns it off in the not-setup case.
|
282
|
+
# triggered by the code above that turns it off in the not-setup case.
|
265
283
|
except AssertionError:
|
266
284
|
pass
|
267
285
|
plugin_name = getattr(cls, "get_name", lambda: cls.__name__)()
|
286
|
+
plugin_composite = CompositeParser([cls.get_cli_parser()] + cls.get_additional_cli_parsers())
|
287
|
+
|
268
288
|
parsed_arguments, _ = ParserBase.parse_args(
|
269
|
-
[
|
289
|
+
[ StandardPipelineParser, PluginArgumentParser, plugin_composite],
|
270
290
|
f"{plugin_name}: a standard app plugin",
|
291
|
+
client=True,
|
271
292
|
)
|
272
293
|
pipeline = StandardPipeline()
|
273
|
-
# Turn off history and
|
294
|
+
# Turn off history, file handling, and logging
|
274
295
|
pipeline.histories.implementation = None
|
275
296
|
pipeline.filing = None
|
297
|
+
parsed_arguments.disable_data_logging = True
|
276
298
|
pipeline = StandardPipelineParser.pipeline_factory(
|
277
299
|
parsed_arguments, pipeline
|
278
300
|
)
|
279
301
|
application = cls(
|
280
|
-
**cls.get_cli_parser().extract_arguments(parsed_arguments)
|
302
|
+
**cls.get_cli_parser().extract_arguments(parsed_arguments),
|
303
|
+
namespace=parsed_arguments,
|
304
|
+
|
281
305
|
)
|
282
306
|
application.start(pipeline)
|
283
307
|
sys.exit(0)
|
284
308
|
except Exception as e:
|
285
309
|
print(f"[ERROR] Error launching {cls.__name__}: {e}", file=sys.stderr)
|
286
|
-
raise
|
287
310
|
sys.exit(148)
|
288
311
|
|
289
312
|
|
313
|
+
|
314
|
+
|
290
315
|
@gds_plugin(GdsApp)
|
291
316
|
class CustomDataHandlers(GdsStandardApp):
|
292
317
|
"""Run an app that registers all custom data handlers
|
@@ -294,10 +319,25 @@ class CustomDataHandlers(GdsStandardApp):
|
|
294
319
|
A GdsApp plugin, built using the GdsStandardApp helper, that uses the provided standard pipeline to register each
|
295
320
|
custom DataHandler plugin as a consumer of the appropriate type.
|
296
321
|
"""
|
322
|
+
PLUGIN_PARSER = CompositeParser([MiddleWareParser, DictionaryParser])
|
297
323
|
|
298
|
-
def __init__(self, **kwargs):
|
324
|
+
def __init__(self, namespace, **kwargs):
|
299
325
|
"""Required __init__ implementation"""
|
300
326
|
super().__init__(**kwargs)
|
327
|
+
self.connection_transport = namespace.connection_transport
|
328
|
+
self.connection_uri = namespace.connection_uri
|
329
|
+
self.dictionaries = namespace.dictionaries
|
330
|
+
|
331
|
+
@classmethod
|
332
|
+
def get_additional_arguments(cls):
|
333
|
+
""" Supplies additional arguments needed """
|
334
|
+
return {}
|
335
|
+
|
336
|
+
@classmethod
|
337
|
+
def get_additional_cli_parsers(cls):
|
338
|
+
""" Requires MiddleWareParser and Dictionary Parser"""
|
339
|
+
return [cls.PLUGIN_PARSER]
|
340
|
+
|
301
341
|
|
302
342
|
@classmethod
|
303
343
|
def init(cls):
|
@@ -312,10 +352,15 @@ class CustomDataHandlers(GdsStandardApp):
|
|
312
352
|
"FW_PACKET_FILE": pipeline.coders.register_file_consumer,
|
313
353
|
"FW_PACKET_PACKETIZED_TLM": pipeline.coders.register_packet_consumer,
|
314
354
|
}
|
355
|
+
self.publisher = PublishingPipeline()
|
356
|
+
self.publisher.transport_implementation = self.connection_transport
|
357
|
+
self.publisher.setup(self.dictionaries)
|
358
|
+
self.publisher.connect(self.connection_uri)
|
315
359
|
|
316
360
|
data_handlers = Plugins.system().get_feature_classes("data_handler")
|
317
361
|
for data_handler_class in data_handlers:
|
318
362
|
data_handler = data_handler_class()
|
363
|
+
data_handler.set_publisher(self.publisher)
|
319
364
|
descriptors = data_handler.get_handled_descriptors()
|
320
365
|
for descriptor in descriptors:
|
321
366
|
DESCRIPTOR_TO_FUNCTION.get(descriptor, lambda discard: discard)(
|
fprime_gds/executables/cli.py
CHANGED
@@ -27,9 +27,9 @@ from pathlib import Path
|
|
27
27
|
from typing import Any, Dict, List, Tuple
|
28
28
|
|
29
29
|
# Required to set the checksum as a module variable
|
30
|
-
import fprime_gds.common.communication.checksum
|
31
30
|
import fprime_gds.common.logger
|
32
31
|
from fprime_gds.common.communication.adapters.ip import check_port
|
32
|
+
from fprime_gds.common.models.dictionaries import Dictionaries
|
33
33
|
from fprime_gds.common.pipeline.standard import StandardPipeline
|
34
34
|
from fprime_gds.common.transport import ThreadedTCPSocketClient
|
35
35
|
from fprime_gds.common.utils.config_manager import ConfigManager
|
@@ -176,6 +176,18 @@ class ParserBase(ABC):
|
|
176
176
|
]
|
177
177
|
return list(itertools.chain.from_iterable(cli_pairs))
|
178
178
|
|
179
|
+
def handle_values(self, values: Dict[str, Any]):
|
180
|
+
"""Post-process the parser's arguments in dictionary form
|
181
|
+
|
182
|
+
Handle arguments from the given parser in dictionary form. This will convert to/from the namespace and then
|
183
|
+
delegate to handle_arguments.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
args: arguments namespace of processed arguments
|
187
|
+
Returns: dictionary with processed results of arguments.
|
188
|
+
"""
|
189
|
+
return vars(self.handle_arguments(args=argparse.Namespace(**values), kwargs={}))
|
190
|
+
|
179
191
|
@abstractmethod
|
180
192
|
def handle_arguments(self, args, **kwargs):
|
181
193
|
"""Post-process the parser's arguments
|
@@ -1007,6 +1019,19 @@ class DictionaryParser(DetectionParser):
|
|
1007
1019
|
elif args.dictionary is None:
|
1008
1020
|
args = super().handle_arguments(args, **kwargs)
|
1009
1021
|
args.dictionary = find_dict(args.deployment)
|
1022
|
+
|
1023
|
+
# Setup dictionaries encoders and decoders
|
1024
|
+
dictionaries = Dictionaries()
|
1025
|
+
|
1026
|
+
dictionaries.load_dictionaries(
|
1027
|
+
args.dictionary, args.packet_spec, args.packet_set_name
|
1028
|
+
)
|
1029
|
+
config = ConfigManager.get_instance()
|
1030
|
+
# Update config to use Fw types defined in the JSON dictionary
|
1031
|
+
if dictionaries.fw_type_name:
|
1032
|
+
for fw_type_name, fw_type in dictionaries.fw_type_name.items():
|
1033
|
+
config.set("types", fw_type_name, fw_type)
|
1034
|
+
args.dictionaries = dictionaries
|
1010
1035
|
return args
|
1011
1036
|
|
1012
1037
|
|
@@ -1070,11 +1095,9 @@ class StandardPipelineParser(CompositeParser):
|
|
1070
1095
|
def pipeline_factory(args_ns, pipeline=None) -> StandardPipeline:
|
1071
1096
|
"""A factory of the standard pipeline given the handled arguments"""
|
1072
1097
|
pipeline_arguments = {
|
1073
|
-
"config": ConfigManager(),
|
1074
|
-
"
|
1098
|
+
"config": ConfigManager.get_instance(),
|
1099
|
+
"dictionaries": args_ns.dictionaries,
|
1075
1100
|
"file_store": args_ns.files_storage_directory,
|
1076
|
-
"packet_spec": args_ns.packet_spec,
|
1077
|
-
"packet_set_name": args_ns.packet_set_name,
|
1078
1101
|
"logging_prefix": args_ns.logs,
|
1079
1102
|
"data_logging_enabled": not args_ns.disable_data_logging
|
1080
1103
|
}
|
@@ -227,7 +227,7 @@ class CommandSubparserInjector(CliSubparserInjectorBase):
|
|
227
227
|
argcomplete.warn("No dictionary found to get command names from")
|
228
228
|
return []
|
229
229
|
|
230
|
-
from fprime_gds.common.
|
230
|
+
from fprime_gds.common.models.dictionaries import Dictionaries
|
231
231
|
|
232
232
|
dictionary = Dictionaries()
|
233
233
|
dictionary.load_dictionaries(dict_path, None, None)
|
@@ -5,6 +5,7 @@
|
|
5
5
|
####
|
6
6
|
import os
|
7
7
|
import sys
|
8
|
+
import copy
|
8
9
|
import webbrowser
|
9
10
|
|
10
11
|
from fprime_gds.executables.cli import (
|
@@ -38,7 +39,9 @@ def parse_args():
|
|
38
39
|
PluginArgumentParser,
|
39
40
|
]
|
40
41
|
# Parse the arguments, and refine through all handlers
|
41
|
-
args, parser = ConfigDrivenParser.parse_args(
|
42
|
+
args, parser = ConfigDrivenParser.parse_args(
|
43
|
+
arg_handlers, "Run F prime deployment and GDS"
|
44
|
+
)
|
42
45
|
return args
|
43
46
|
|
44
47
|
|
@@ -175,11 +178,21 @@ def launch_comm(parsed_args):
|
|
175
178
|
)
|
176
179
|
|
177
180
|
|
178
|
-
def launch_plugin(plugin_class_instance):
|
181
|
+
def launch_plugin(parsed_args, plugin_class_instance):
|
179
182
|
"""Launch a plugin instance"""
|
180
|
-
plugin_name = getattr(
|
183
|
+
plugin_name = getattr(
|
184
|
+
plugin_class_instance,
|
185
|
+
"get_name",
|
186
|
+
lambda: plugin_class_instance.__class__.__name__,
|
187
|
+
)()
|
188
|
+
plugin_args = copy.deepcopy(parsed_args)
|
189
|
+
# Set logging to use a subdirectory within the root logs directory
|
190
|
+
plugin_logs = os.path.join(plugin_args.logs, plugin_name)
|
191
|
+
os.mkdir(plugin_logs)
|
192
|
+
plugin_args.logs = plugin_logs
|
193
|
+
plugin_args.log_directly = True
|
181
194
|
return launch_process(
|
182
|
-
plugin_class_instance.get_process_invocation(),
|
195
|
+
plugin_class_instance.get_process_invocation(plugin_args),
|
183
196
|
name=f"{ plugin_name } Plugin App",
|
184
197
|
launch_time=1,
|
185
198
|
)
|
@@ -218,11 +231,11 @@ def main():
|
|
218
231
|
try:
|
219
232
|
procs = [launcher(parsed_args) for launcher in launchers]
|
220
233
|
_ = [
|
221
|
-
launch_plugin(cls())
|
234
|
+
launch_plugin(parsed_args, cls(namespace=parsed_args))
|
222
235
|
for cls in Plugins.system().get_feature_classes("gds_app")
|
223
236
|
]
|
224
237
|
_ = [
|
225
|
-
instance().run()
|
238
|
+
instance().run(parsed_args)
|
226
239
|
for instance in Plugins.system().get_feature_classes("gds_function")
|
227
240
|
]
|
228
241
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fprime-gds
|
3
|
-
Version: 4.0.
|
3
|
+
Version: 4.0.2a2
|
4
4
|
Summary: F Prime Flight Software Ground Data System layer
|
5
5
|
Author-email: Michael Starch <Michael.D.Starch@jpl.nasa.gov>, Thomas Boyer-Chammard <Thomas.Boyer.Chammard@jpl.nasa.gov>
|
6
6
|
License:
|
@@ -2,7 +2,7 @@ fastentrypoints.py,sha256=2HO-tsTTZxpzYNd-BaLK3WDLknzCZKzb_yX2p3Ftqa8,4020
|
|
2
2
|
fprime_gds/__init__.py,sha256=y2ljhCEHnvyfSDvXIEgBGIk8oHjjjjCWFxfddOGeYFk,115
|
3
3
|
fprime_gds/version.py,sha256=dlUlfOKTsGaqz_L7TjhCVC-Vanx5cK67kdZlqcHCM8M,395
|
4
4
|
fprime_gds/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
fprime_gds/common/handlers.py,sha256=
|
5
|
+
fprime_gds/common/handlers.py,sha256=vPfW1jJpq-oI7c9OTFqZ1LovlhFjx1DEUrfZTk_iuNY,6344
|
6
6
|
fprime_gds/common/transport.py,sha256=uYXWkM8TYEYz1vfY4AEn0PF8Gu4tkYmJ5t4w1YY1yW8,10565
|
7
7
|
fprime_gds/common/zmq_transport.py,sha256=E_iBZ5sA4JKB99MWSOM6XnPrO-mbFyRvD9eQp9te6-Y,12397
|
8
8
|
fprime_gds/common/communication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -29,21 +29,21 @@ fprime_gds/common/data_types/file_data.py,sha256=4_G9kf4ThC5NzkxnKa0xNYBdi8UDvZg
|
|
29
29
|
fprime_gds/common/data_types/pkt_data.py,sha256=cxqUnsPte0ijF1E8F1_uglVKIJFAIQbpoBlmwRjMrJY,3405
|
30
30
|
fprime_gds/common/data_types/sys_data.py,sha256=Xfk5xryFg7zWS3VcGUDx9lQYBTajjWXvwkgFK5EUCG4,2095
|
31
31
|
fprime_gds/common/decoders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
|
-
fprime_gds/common/decoders/ch_decoder.py,sha256
|
32
|
+
fprime_gds/common/decoders/ch_decoder.py,sha256=-Vo_GJys-4ohs94XV0ZYB88SNqN0gxxY29Ijt1gwyXY,3847
|
33
33
|
fprime_gds/common/decoders/decoder.py,sha256=9j7u05_nwXaEjR0etsoB--ATsHuILYCXlhk9m9yajKg,2655
|
34
|
-
fprime_gds/common/decoders/event_decoder.py,sha256=
|
34
|
+
fprime_gds/common/decoders/event_decoder.py,sha256=tF_mg98RDjR0PppymGhmXybYXA0mFqklZXwora-cVtw,4503
|
35
35
|
fprime_gds/common/decoders/file_decoder.py,sha256=Ky2U8bli3YL6GbT9jSSvI73ySOtf0cdZLK4FXTuWjfA,2542
|
36
|
-
fprime_gds/common/decoders/pkt_decoder.py,sha256=
|
36
|
+
fprime_gds/common/decoders/pkt_decoder.py,sha256=c1CebqBaD7rAZd9t0AXkGVRTCtvXj0YH9OBN2bJKaTk,3327
|
37
37
|
fprime_gds/common/distributor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
|
-
fprime_gds/common/distributor/distributor.py,sha256=
|
38
|
+
fprime_gds/common/distributor/distributor.py,sha256=hP0mUknxxpKrQfYkf57dHbMItwgUTzpzmkrc1AOHVCw,8034
|
39
39
|
fprime_gds/common/encoders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
40
40
|
fprime_gds/common/encoders/ch_encoder.py,sha256=TBrTJ7TK4WwCh6KAspozh63WcPxrMImloB8tz7qeulw,2878
|
41
|
-
fprime_gds/common/encoders/cmd_encoder.py,sha256=
|
42
|
-
fprime_gds/common/encoders/encoder.py,sha256=
|
41
|
+
fprime_gds/common/encoders/cmd_encoder.py,sha256=iFPi6uMlMPlApC47p9YKRjKJxMvz46p15Yy3NnGTyaE,3497
|
42
|
+
fprime_gds/common/encoders/encoder.py,sha256=jaN-uLHRGAzAs33ZdPm2FTdh3mAvsOCtqO6Ov9hspyI,2997
|
43
43
|
fprime_gds/common/encoders/event_encoder.py,sha256=aM_3hWWx4OrLKF3-MlhmGSBYnzt-4iktSzMVrcUbfB8,3140
|
44
44
|
fprime_gds/common/encoders/file_encoder.py,sha256=G9uUXQP-oD2eW_GJuGNBrN7xPafKFhmgKiNi-zvZz-g,3830
|
45
45
|
fprime_gds/common/encoders/pkt_encoder.py,sha256=6hzwrAEg1tjGw9yGycWMuNgbGCoe87Cd-7eP1rvy2d4,3126
|
46
|
-
fprime_gds/common/encoders/seq_writer.py,sha256=
|
46
|
+
fprime_gds/common/encoders/seq_writer.py,sha256=g0Rmnlw4qLgJn290ORzJ21jZo0gB2dTvHFWs4pzbmio,6880
|
47
47
|
fprime_gds/common/files/File Decoder Documentation.txt,sha256=a-VYHcUMqh7mBGY2fqvMf1nd3gdg3cLdPKwrulNKXjc,5314
|
48
48
|
fprime_gds/common/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
49
|
fprime_gds/common/files/downlinker.py,sha256=CZPfhH0J9-LNqW5Cv_ryicLTuoedLSWK8OPQmmQDZZY,7498
|
@@ -59,10 +59,10 @@ fprime_gds/common/fpy/parser.py,sha256=g-l67oZN_vB1JAdZ5S3u9m8APf6PdJ88GZyz0iX66
|
|
59
59
|
fprime_gds/common/fpy/bytecode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
60
60
|
fprime_gds/common/fpy/bytecode/directives.py,sha256=tBpPQ2ZnQXA7juB85HhacDdil1vEHUKW8m_AsMf1KdQ,13360
|
61
61
|
fprime_gds/common/gds_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
62
|
-
fprime_gds/common/gds_cli/base_commands.py,sha256=
|
63
|
-
fprime_gds/common/gds_cli/channels.py,sha256=
|
64
|
-
fprime_gds/common/gds_cli/command_send.py,sha256=
|
65
|
-
fprime_gds/common/gds_cli/events.py,sha256=
|
62
|
+
fprime_gds/common/gds_cli/base_commands.py,sha256=js4SAXPfDYy_ewIL27066XylExxh9S1A-e4NNChWf9s,9430
|
63
|
+
fprime_gds/common/gds_cli/channels.py,sha256=BvADGBrsJ2G9zcGpSwJlxLRFiY1bUxtQSTfEOlA3UME,2134
|
64
|
+
fprime_gds/common/gds_cli/command_send.py,sha256=SnDBbwKzNluG-yJSsmsQJpNBPmv4O7nMvG6qYbdpI64,6606
|
65
|
+
fprime_gds/common/gds_cli/events.py,sha256=9Jpk0C7VI-KldFxo7neaG2MpcKhqH2VE2xaV8G-5pSw,2121
|
66
66
|
fprime_gds/common/gds_cli/filtering_utils.py,sha256=2LxT9tzuNvnwm7HVItv87XkO6K29nOBift2bYcYn3zg,7554
|
67
67
|
fprime_gds/common/gds_cli/test_api_utils.py,sha256=VphGie_VxTMZQGz6p_5AjdEZWXqKJTohrqslRS8VnNU,5109
|
68
68
|
fprime_gds/common/history/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -88,19 +88,18 @@ fprime_gds/common/logger/__init__.py,sha256=TLUbrAnkCtckKGsLzh4hXgEshwQfZsWMDaOO
|
|
88
88
|
fprime_gds/common/logger/data_logger.py,sha256=VjfhTGO1gGw954xNhSc0_zpw8JexCho5f8BlXDEYkL4,2505
|
89
89
|
fprime_gds/common/logger/test_logger.py,sha256=wL8Lq49sVmxGRALgv-ei6AnXFh79qlHFehmKJ1A8X28,6475
|
90
90
|
fprime_gds/common/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
91
|
+
fprime_gds/common/models/dictionaries.py,sha256=8HRnSrg6yVOlep17qFWdJzKJ7gZIoNGA-bCabuITyM8,8091
|
91
92
|
fprime_gds/common/models/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
|
-
fprime_gds/common/models/common/channel_telemetry.py,sha256=UkLIgWLgVNi2AmPnuT3k9pAmUqNuw2zYHj_r6dB3q5o,4305
|
93
93
|
fprime_gds/common/models/common/command.py,sha256=ASih9dwR_7F94nR1CV7cIuZEJSuaUAzX7JU2_lCAg4g,5476
|
94
|
-
fprime_gds/common/models/common/event.py,sha256=gSFrCJT9ZddGJfkf3fGCCqk0aMIQV-SNeAhCX6hnbrc,3386
|
95
94
|
fprime_gds/common/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
95
|
fprime_gds/common/parsers/seq_file_parser.py,sha256=6DZrA0jmt8IqsutfK7pdLtYn4oVHO593rWgAOH63yRg,9587
|
97
96
|
fprime_gds/common/pipeline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
98
|
-
fprime_gds/common/pipeline/dictionaries.py,sha256=x3QCZAg6YB9bEumZ330PGo0ilJqODGyo_K70RgbQ53M,8009
|
99
97
|
fprime_gds/common/pipeline/encoding.py,sha256=PttJ8NmXm75mLXyhlmxOJqE8RFt46q1dThaV19PyAr4,7216
|
100
98
|
fprime_gds/common/pipeline/files.py,sha256=J2zm0sucvImtmSnv0iUp5uTpvUO8nlmz2lUdMuMC5aM,2244
|
101
99
|
fprime_gds/common/pipeline/histories.py,sha256=7KyboNnm9OARQk4meVPSSeYpeqH0G8RWRiy0BLBL1rw,3671
|
100
|
+
fprime_gds/common/pipeline/publishing.py,sha256=A0Hb4RpK7RCBDN9BEiJZr9WQMSrmohYXCFOuzl23mPo,3953
|
102
101
|
fprime_gds/common/pipeline/router.py,sha256=-P1wI0KXEh_snOzDaq8CjEoWuM_zRm8vUMR1T0oY9qQ,2327
|
103
|
-
fprime_gds/common/pipeline/standard.py,sha256=
|
102
|
+
fprime_gds/common/pipeline/standard.py,sha256=Gj-TPWoCWN-zp6uI2o_TI9jANJ7I7hmXOujgwJ8PlMo,9126
|
104
103
|
fprime_gds/common/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
105
104
|
fprime_gds/common/templates/ch_template.py,sha256=1MoDZsia0dI_CvnIttwyKLhbQhum35OcJnFc50Xohuo,3893
|
106
105
|
fprime_gds/common/templates/cmd_template.py,sha256=n91z4WhFgHwTu6_fQqy7JqpkEObAkllIeEy0AR0DvrQ,5455
|
@@ -117,18 +116,18 @@ fprime_gds/common/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
117
116
|
fprime_gds/common/tools/params.py,sha256=htnMLlUW9HmBo4Qc7kYhnWr1sO6bK2mckdskLt5rDUk,9323
|
118
117
|
fprime_gds/common/tools/seqgen.py,sha256=O57igktjWku5OJhBqezhCjPYUmh4GZM-9qKCChqEW7g,6034
|
119
118
|
fprime_gds/common/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
120
|
-
fprime_gds/common/utils/config_manager.py,sha256=
|
119
|
+
fprime_gds/common/utils/config_manager.py,sha256=dMqN204UKLiZzIs7-d--fdYMQ8kBzTX56xexkgFq18s,5550
|
121
120
|
fprime_gds/common/utils/data_desc_type.py,sha256=0AkEMfEa5refd_moovf1hkgKiNakADRzv4soghvf9a4,883
|
122
121
|
fprime_gds/common/utils/event_severity.py,sha256=7qPXHrDaM_REJ7sKBUEJTZIE0D4qVnVajsPDUuHg7sI,300
|
123
122
|
fprime_gds/common/utils/string_util.py,sha256=u_2iahRG3ROu3lAAt_KVcK226gEByElXqrA8mH8eDpI,3584
|
124
123
|
fprime_gds/executables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
125
|
-
fprime_gds/executables/apps.py,sha256=
|
126
|
-
fprime_gds/executables/cli.py,sha256=
|
124
|
+
fprime_gds/executables/apps.py,sha256=_OLWxby1XvYmmDcecsOAKu34XGf952_ya5uRWf_8Y3I,15127
|
125
|
+
fprime_gds/executables/cli.py,sha256=OqcBOpvnj8f8wZjntfbr-pNzCEF3P_-eA58kBqK7iDg,52216
|
127
126
|
fprime_gds/executables/comm.py,sha256=08rO0o0MJgTRngB7Ygu2IL_gEAWKF7WFvFyro1CqReE,5214
|
128
127
|
fprime_gds/executables/data_product_writer.py,sha256=e1Rp2LT_Cpg08f0Ki8GhirC7Wn6LtYiAef7KLAkZHUY,37773
|
129
128
|
fprime_gds/executables/dictionary_merge.py,sha256=3Zy8LcbEdBwmNX2GLN_Nr1DfbLyWYHg-y4jdjTVCXgY,7966
|
130
|
-
fprime_gds/executables/fprime_cli.py,sha256=
|
131
|
-
fprime_gds/executables/run_deployment.py,sha256=
|
129
|
+
fprime_gds/executables/fprime_cli.py,sha256=9_eNU7AzUOMhz4FLPkD_byA9C13c509wGPZN-kdw9Ok,12429
|
130
|
+
fprime_gds/executables/run_deployment.py,sha256=4K3isTF7C8FojFvzxLC8vaj1GZpKOuPZQ3CtIYdyhRE,7638
|
132
131
|
fprime_gds/executables/tcpserver.py,sha256=KspVpu5YIuiWKOk5E6UDMKvqXYrRB1j9aX8CkMxysfw,17555
|
133
132
|
fprime_gds/executables/utils.py,sha256=SbzXRe1p41qMPdifvPap5_4v0T42gZZ_Rs_OYfITd80,7626
|
134
133
|
fprime_gds/flask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -245,10 +244,10 @@ fprime_gds/flask/static/third-party/webfonts/fa-solid-900.woff2,sha256=mDS4KtJuK
|
|
245
244
|
fprime_gds/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
246
245
|
fprime_gds/plugin/definitions.py,sha256=QlxW1gNvoiqGMslSJjh3dTFZuv0igFHawN__3XJ0Wns,5355
|
247
246
|
fprime_gds/plugin/system.py,sha256=M9xb-8jBhCUUx3X1z2uAP8Wx_v6NkL8JeaFgGcMnQqY,13432
|
248
|
-
fprime_gds-4.0.
|
249
|
-
fprime_gds-4.0.
|
250
|
-
fprime_gds-4.0.
|
251
|
-
fprime_gds-4.0.
|
252
|
-
fprime_gds-4.0.
|
253
|
-
fprime_gds-4.0.
|
254
|
-
fprime_gds-4.0.
|
247
|
+
fprime_gds-4.0.2a2.dist-info/licenses/LICENSE.txt,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
248
|
+
fprime_gds-4.0.2a2.dist-info/licenses/NOTICE.txt,sha256=vXjA_xRcQhd83Vfk5D_vXg5kOjnnXvLuMi5vFKDEVmg,1612
|
249
|
+
fprime_gds-4.0.2a2.dist-info/METADATA,sha256=t7Idkx-zA1DrvKJaxm_zVGZoTDFxw_UJtLY35Xje4R4,24576
|
250
|
+
fprime_gds-4.0.2a2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
251
|
+
fprime_gds-4.0.2a2.dist-info/entry_points.txt,sha256=16r0xeF-Qn-ducW_QvHiyrFnNjnLK-OOaTbqQIQpd0o,494
|
252
|
+
fprime_gds-4.0.2a2.dist-info/top_level.txt,sha256=6vzFLIX6ANfavKaXFHDMSLFtS94a6FaAsIWhjgYuSNE,27
|
253
|
+
fprime_gds-4.0.2a2.dist-info/RECORD,,
|
@@ -1,174 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Created on Apr. 27, 2015
|
3
|
-
|
4
|
-
@author: reder
|
5
|
-
"""
|
6
|
-
|
7
|
-
from fprime.common.models.serialize.type_base import BaseType
|
8
|
-
|
9
|
-
# Import the types this way so they do not need prefixing for execution.
|
10
|
-
from fprime.common.models.serialize.type_exceptions import (
|
11
|
-
TypeException,
|
12
|
-
TypeMismatchException,
|
13
|
-
)
|
14
|
-
|
15
|
-
|
16
|
-
class Channel:
|
17
|
-
"""
|
18
|
-
Channel class is for deserialize channel telemetry value.
|
19
|
-
Really this is a container since the type will have it's own deserialize
|
20
|
-
implementation.
|
21
|
-
"""
|
22
|
-
|
23
|
-
def __init__(
|
24
|
-
self,
|
25
|
-
name,
|
26
|
-
channel_id,
|
27
|
-
comp_name,
|
28
|
-
ch_description,
|
29
|
-
ch_type,
|
30
|
-
ch_format_string,
|
31
|
-
low_red,
|
32
|
-
low_orange,
|
33
|
-
low_yellow,
|
34
|
-
high_yellow,
|
35
|
-
high_orange,
|
36
|
-
high_red,
|
37
|
-
):
|
38
|
-
"""
|
39
|
-
Constructor
|
40
|
-
"""
|
41
|
-
#
|
42
|
-
# Make sure correct types are passed
|
43
|
-
#
|
44
|
-
if not isinstance(name, str):
|
45
|
-
raise TypeMismatchException(str, type(name))
|
46
|
-
|
47
|
-
if not isinstance(channel_id, int):
|
48
|
-
raise TypeMismatchException(int, type(channel_id))
|
49
|
-
|
50
|
-
if not isinstance(ch_description, str):
|
51
|
-
raise TypeMismatchException(str, type(ch_description))
|
52
|
-
|
53
|
-
if not isinstance(ch_type, BaseType):
|
54
|
-
raise TypeMismatchException(BaseType, type(ch_type))
|
55
|
-
|
56
|
-
# Initialize event internal variables
|
57
|
-
self.__name = name
|
58
|
-
self.__comp_name = comp_name
|
59
|
-
self.__id = channel_id
|
60
|
-
self.__ch_desc = ch_description
|
61
|
-
self.__ch_type = ch_type
|
62
|
-
self.__format_string = ch_format_string
|
63
|
-
self.__low_red = low_red
|
64
|
-
self.__low_orange = low_orange
|
65
|
-
self.__low_yellow = low_yellow
|
66
|
-
self.__high_yellow = high_yellow
|
67
|
-
self.__high_orange = high_orange
|
68
|
-
self.__high_red = high_red
|
69
|
-
#
|
70
|
-
self.__time_base = None
|
71
|
-
self.__time_context = None
|
72
|
-
self.__time_sec = None
|
73
|
-
self.__time_usec = None
|
74
|
-
#
|
75
|
-
self.__changed = False
|
76
|
-
|
77
|
-
def deserialize(self, ser_data, offset):
|
78
|
-
"""
|
79
|
-
Deserialize event arguments
|
80
|
-
:param ser_data: Binary input of the channel value.
|
81
|
-
:param offset: offset in data to deserialize from
|
82
|
-
:return: value from deserialized channel
|
83
|
-
"""
|
84
|
-
try:
|
85
|
-
self.__ch_type.deserialize(ser_data, offset)
|
86
|
-
val = self.__ch_type.val
|
87
|
-
except TypeException as e:
|
88
|
-
print(f"Channel deserialize exception {e.getMsg()}")
|
89
|
-
val = "ERR"
|
90
|
-
|
91
|
-
#
|
92
|
-
return val
|
93
|
-
|
94
|
-
def setTime(self, time_base, time_context, time_sec, time_usec):
|
95
|
-
"""
|
96
|
-
Channel telemetry time updater.
|
97
|
-
"""
|
98
|
-
self.__time_base = time_base
|
99
|
-
self.__time_context = time_context
|
100
|
-
self.__time_sec = time_sec
|
101
|
-
self.__time_usec = time_usec
|
102
|
-
|
103
|
-
def getTime(self):
|
104
|
-
"""
|
105
|
-
Return time tuple for UI updater use.
|
106
|
-
"""
|
107
|
-
return (
|
108
|
-
self.__time_base,
|
109
|
-
self.__time_context,
|
110
|
-
self.__time_sec,
|
111
|
-
self.__time_usec,
|
112
|
-
)
|
113
|
-
|
114
|
-
def getName(self):
|
115
|
-
return self.__name
|
116
|
-
|
117
|
-
def getCompName(self):
|
118
|
-
return self.__comp_name
|
119
|
-
|
120
|
-
def getId(self):
|
121
|
-
return self.__id
|
122
|
-
|
123
|
-
def getChDesc(self):
|
124
|
-
return self.__ch_desc
|
125
|
-
|
126
|
-
def getType(self):
|
127
|
-
return self.__ch_type
|
128
|
-
|
129
|
-
def getTimeBase(self):
|
130
|
-
return self.__time_base
|
131
|
-
|
132
|
-
def getTimeContext(self):
|
133
|
-
return self.__time_context
|
134
|
-
|
135
|
-
def getTimeSec(self):
|
136
|
-
return self.__time_sec
|
137
|
-
|
138
|
-
def getTimeUsec(self):
|
139
|
-
return self.__time_usec
|
140
|
-
|
141
|
-
def getFormatString(self):
|
142
|
-
return self.__format_string
|
143
|
-
|
144
|
-
def getLowRed(self):
|
145
|
-
return self.__low_red
|
146
|
-
|
147
|
-
def getLowOrange(self):
|
148
|
-
return self.__low_orange
|
149
|
-
|
150
|
-
def getLowYellow(self):
|
151
|
-
return self.__low_yellow
|
152
|
-
|
153
|
-
def getHighYellow(self):
|
154
|
-
return self.__high_yellow
|
155
|
-
|
156
|
-
def getHighOrange(self):
|
157
|
-
return self.__high_orange
|
158
|
-
|
159
|
-
def getHighRed(self):
|
160
|
-
return self.__high_red
|
161
|
-
|
162
|
-
@property
|
163
|
-
def changed(self):
|
164
|
-
"""
|
165
|
-
change is True if recently updated.
|
166
|
-
change is False if not changed.
|
167
|
-
"""
|
168
|
-
return self.__changed
|
169
|
-
|
170
|
-
@changed.setter
|
171
|
-
def changed(self, ch):
|
172
|
-
if ch is not False or ch is not True:
|
173
|
-
ch = True
|
174
|
-
self.__changed = ch
|
@@ -1,121 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Created on Feb. 9, 2015
|
3
|
-
|
4
|
-
@author: reder
|
5
|
-
"""
|
6
|
-
|
7
|
-
import traceback
|
8
|
-
from enum import Enum
|
9
|
-
|
10
|
-
from fprime.common.models.serialize.type_base import BaseType
|
11
|
-
|
12
|
-
# Import the types this way so they do not need prefixing for execution.
|
13
|
-
from fprime.common.models.serialize.type_exceptions import (
|
14
|
-
TypeException,
|
15
|
-
TypeMismatchException,
|
16
|
-
)
|
17
|
-
|
18
|
-
Severity = Enum(
|
19
|
-
"Severity", "COMMAND ACTIVITY_LO ACTIVITY_HI WARNING_LO WARNING_HI DIAGNOSTIC FATAL"
|
20
|
-
)
|
21
|
-
|
22
|
-
|
23
|
-
class Event:
|
24
|
-
"""
|
25
|
-
Event class is for deserializing log event messages.
|
26
|
-
THis is essentially the equivalent of EVR's in MSL, SMAP, etc.
|
27
|
-
"""
|
28
|
-
|
29
|
-
def __init__(
|
30
|
-
self, name, event_id, severity, format_string, event_description, arguments
|
31
|
-
):
|
32
|
-
"""
|
33
|
-
Constructor
|
34
|
-
"""
|
35
|
-
|
36
|
-
# Make sure correct types are passed
|
37
|
-
|
38
|
-
if not isinstance(name, str):
|
39
|
-
raise TypeMismatchException(str, type(name))
|
40
|
-
|
41
|
-
if not isinstance(event_id, int):
|
42
|
-
raise TypeMismatchException(int, type(event_id))
|
43
|
-
|
44
|
-
if not isinstance(format_string, str):
|
45
|
-
raise TypeMismatchException(str, type(format_string))
|
46
|
-
|
47
|
-
if not isinstance(event_description, str):
|
48
|
-
raise TypeMismatchException(str, type(event_description))
|
49
|
-
|
50
|
-
if not isinstance(arguments, list):
|
51
|
-
raise TypeMismatchException(list, type(arguments))
|
52
|
-
|
53
|
-
for (argname, argdesc, argtype) in arguments:
|
54
|
-
#
|
55
|
-
if not isinstance(argname, str):
|
56
|
-
raise TypeMismatchException(str, type(argname))
|
57
|
-
#
|
58
|
-
if not isinstance(argdesc, str):
|
59
|
-
raise TypeMismatchException(str, type(argdesc))
|
60
|
-
#
|
61
|
-
if not isinstance(argtype, BaseType):
|
62
|
-
raise TypeMismatchException(BaseType, type(argtype))
|
63
|
-
|
64
|
-
# Initialize event internal variables
|
65
|
-
self.__name = name
|
66
|
-
self.__id = event_id
|
67
|
-
self.__severity = severity
|
68
|
-
self.__format_string = format_string
|
69
|
-
self.__event_description = event_description
|
70
|
-
self.__arguments = arguments
|
71
|
-
|
72
|
-
def deserialize(self, ser_data):
|
73
|
-
"""
|
74
|
-
Deserialize event arguments
|
75
|
-
@param ser_data: Binary input data of id followed by args
|
76
|
-
"""
|
77
|
-
vals = []
|
78
|
-
#
|
79
|
-
# Next parse the arguments.
|
80
|
-
#
|
81
|
-
args = list(self.__arguments)
|
82
|
-
offset = 0
|
83
|
-
for arg in args:
|
84
|
-
arg_obj = arg[2]
|
85
|
-
try:
|
86
|
-
# print arg_obj
|
87
|
-
arg_obj.deserialize(ser_data, offset)
|
88
|
-
vals.append(arg_obj.val)
|
89
|
-
except TypeException as e:
|
90
|
-
print(f"Event deserialize exception {e.getMsg()}")
|
91
|
-
traceback.print_exc()
|
92
|
-
vals.append("ERR")
|
93
|
-
offset = offset + arg_obj.getSize()
|
94
|
-
|
95
|
-
vals = [0] + vals
|
96
|
-
return vals
|
97
|
-
|
98
|
-
def stringify(self, event_args_list):
|
99
|
-
"""
|
100
|
-
Return a formatted string of event args.
|
101
|
-
"""
|
102
|
-
# print event_args_list
|
103
|
-
return self.__format_string % tuple(event_args_list[1:])
|
104
|
-
|
105
|
-
def getName(self):
|
106
|
-
return self.__name
|
107
|
-
|
108
|
-
def getId(self):
|
109
|
-
return self.__id
|
110
|
-
|
111
|
-
def getSeverity(self):
|
112
|
-
return self.__severity
|
113
|
-
|
114
|
-
def getFormatString(self):
|
115
|
-
return self.__format_string
|
116
|
-
|
117
|
-
def getEventDescription(self):
|
118
|
-
return self.__event_description
|
119
|
-
|
120
|
-
def getArgs(self):
|
121
|
-
return self.__arguments
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|