nost-tools 2.0.0__py3-none-any.whl → 2.0.1__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.
Potentially problematic release.
This version of nost-tools might be problematic. Click here for more details.
- nost_tools/__init__.py +29 -29
- nost_tools/application.py +800 -793
- nost_tools/application_utils.py +262 -262
- nost_tools/configuration.py +304 -304
- nost_tools/entity.py +73 -73
- nost_tools/errors.py +14 -14
- nost_tools/logger_application.py +192 -192
- nost_tools/managed_application.py +261 -261
- nost_tools/manager.py +472 -472
- nost_tools/observer.py +181 -181
- nost_tools/publisher.py +141 -141
- nost_tools/schemas.py +432 -426
- nost_tools/simulator.py +531 -531
- {nost_tools-2.0.0.dist-info → nost_tools-2.0.1.dist-info}/METADATA +118 -119
- nost_tools-2.0.1.dist-info/RECORD +18 -0
- {nost_tools-2.0.0.dist-info → nost_tools-2.0.1.dist-info}/licenses/LICENSE +29 -29
- nost_tools-2.0.0.dist-info/RECORD +0 -18
- {nost_tools-2.0.0.dist-info → nost_tools-2.0.1.dist-info}/WHEEL +0 -0
- {nost_tools-2.0.0.dist-info → nost_tools-2.0.1.dist-info}/top_level.txt +0 -0
|
@@ -1,261 +1,261 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Provides a base application that manages communication between a simulator and broker.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import logging
|
|
6
|
-
import threading
|
|
7
|
-
import traceback
|
|
8
|
-
from datetime import datetime, timedelta
|
|
9
|
-
|
|
10
|
-
from .application import Application
|
|
11
|
-
from .application_utils import ConnectionConfig
|
|
12
|
-
from .schemas import InitCommand, StartCommand, StopCommand, UpdateCommand
|
|
13
|
-
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class ManagedApplication(Application):
|
|
18
|
-
"""
|
|
19
|
-
Managed NOS-T Application.
|
|
20
|
-
|
|
21
|
-
This object class defines the basic functionality for a NOS-T application
|
|
22
|
-
that utilizes an external Manager to command simulator execution.
|
|
23
|
-
|
|
24
|
-
Attributes:
|
|
25
|
-
prefix (str): execution namespace (prefix)
|
|
26
|
-
simulator (:obj:`Simulator`): simulator
|
|
27
|
-
client (:obj:`Client`): MQTT client
|
|
28
|
-
app_name (str): application name
|
|
29
|
-
app_description (str): application description
|
|
30
|
-
time_status_step (:obj:`timedelta`): scenario duration between time status messages
|
|
31
|
-
time_status_init (:obj:`datetime`): scenario time of first time status message
|
|
32
|
-
time_step (:obj:`timedelta`): scenario time step used in execution
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
def __init__(self, app_name: str, app_description: str = None):
|
|
36
|
-
"""
|
|
37
|
-
Initializes a new managed application.
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
app_name (str): application name
|
|
41
|
-
app_description (str): application description
|
|
42
|
-
"""
|
|
43
|
-
super().__init__(app_name, app_description)
|
|
44
|
-
self.time_step = None
|
|
45
|
-
self._sim_start_time = None
|
|
46
|
-
self._sim_stop_time = None
|
|
47
|
-
|
|
48
|
-
def start_up(
|
|
49
|
-
self,
|
|
50
|
-
prefix: str,
|
|
51
|
-
config: ConnectionConfig,
|
|
52
|
-
set_offset: bool = None,
|
|
53
|
-
time_status_step: timedelta = None,
|
|
54
|
-
time_status_init: datetime = None,
|
|
55
|
-
shut_down_when_terminated: bool = None,
|
|
56
|
-
time_step: timedelta = None,
|
|
57
|
-
manager_app_name: str = None,
|
|
58
|
-
) -> None:
|
|
59
|
-
"""
|
|
60
|
-
Starts up the application by connecting to message broker, starting a background event loop,
|
|
61
|
-
subscribing to manager events, and registering callback functions.
|
|
62
|
-
|
|
63
|
-
Args:
|
|
64
|
-
prefix (str): execution namespace (prefix)
|
|
65
|
-
config (:obj:`ConnectionConfig`): connection configuration
|
|
66
|
-
set_offset (bool): True, if the system clock offset shall be set using a NTP request prior to execution
|
|
67
|
-
time_status_step (:obj:`timedelta`): scenario duration between time status messages
|
|
68
|
-
time_status_init (:obj:`datetime`): scenario time for first time status message
|
|
69
|
-
shut_down_when_terminated (bool): True, if the application should shut down when the simulation is terminated
|
|
70
|
-
time_step (:obj:`timedelta`): scenario time step used in execution (Default: 1 second)
|
|
71
|
-
manager_app_name (str): manager application name (Default: manager)
|
|
72
|
-
"""
|
|
73
|
-
if (
|
|
74
|
-
set_offset is not None
|
|
75
|
-
and time_status_step is not None
|
|
76
|
-
and time_status_init is not None
|
|
77
|
-
and shut_down_when_terminated is not None
|
|
78
|
-
and time_step is not None
|
|
79
|
-
and manager_app_name is not None
|
|
80
|
-
):
|
|
81
|
-
self.set_offset = set_offset
|
|
82
|
-
self.time_status_step = time_status_step
|
|
83
|
-
self.time_status_init = time_status_init
|
|
84
|
-
self.shut_down_when_terminated = shut_down_when_terminated
|
|
85
|
-
self.time_step = time_step
|
|
86
|
-
self.manager_app_name = manager_app_name
|
|
87
|
-
else:
|
|
88
|
-
self.config = config
|
|
89
|
-
parameters = getattr(
|
|
90
|
-
self.config.rc.simulation_configuration.execution_parameters,
|
|
91
|
-
"managed_application",
|
|
92
|
-
None,
|
|
93
|
-
)
|
|
94
|
-
self.set_offset = parameters.set_offset
|
|
95
|
-
self.time_status_step = parameters.time_status_step
|
|
96
|
-
self.time_status_init = parameters.time_status_init
|
|
97
|
-
self.shut_down_when_terminated = parameters.shut_down_when_terminated
|
|
98
|
-
self.time_step = parameters.time_step
|
|
99
|
-
self.manager_app_name = parameters.manager_app_name
|
|
100
|
-
|
|
101
|
-
# start up base application
|
|
102
|
-
super().start_up(
|
|
103
|
-
prefix,
|
|
104
|
-
config,
|
|
105
|
-
self.set_offset,
|
|
106
|
-
self.time_status_step,
|
|
107
|
-
self.time_status_init,
|
|
108
|
-
self.shut_down_when_terminated,
|
|
109
|
-
)
|
|
110
|
-
self.time_step = self.time_step
|
|
111
|
-
self.manager_app_name = self.manager_app_name
|
|
112
|
-
|
|
113
|
-
# Register callback functions
|
|
114
|
-
self.add_message_callback(
|
|
115
|
-
app_name=self.manager_app_name,
|
|
116
|
-
app_topic="init",
|
|
117
|
-
user_callback=self.on_manager_init,
|
|
118
|
-
)
|
|
119
|
-
self.add_message_callback(
|
|
120
|
-
app_name=self.manager_app_name,
|
|
121
|
-
app_topic="start",
|
|
122
|
-
user_callback=self.on_manager_start,
|
|
123
|
-
)
|
|
124
|
-
self.add_message_callback(
|
|
125
|
-
app_name=self.manager_app_name,
|
|
126
|
-
app_topic="stop",
|
|
127
|
-
user_callback=self.on_manager_stop,
|
|
128
|
-
)
|
|
129
|
-
self.add_message_callback(
|
|
130
|
-
app_name=self.manager_app_name,
|
|
131
|
-
app_topic="update",
|
|
132
|
-
user_callback=self.on_manager_update,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
def shut_down(self) -> None:
|
|
136
|
-
"""
|
|
137
|
-
Shuts down the application by stopping the background event loop and disconnecting
|
|
138
|
-
the application from the broker.
|
|
139
|
-
"""
|
|
140
|
-
# shut down base application
|
|
141
|
-
super().shut_down()
|
|
142
|
-
|
|
143
|
-
def on_manager_init(self, ch, method, properties, body) -> None:
|
|
144
|
-
"""
|
|
145
|
-
Callback function for the managed application to respond to an initilize command sent from the manager.
|
|
146
|
-
Parses the scenario start/end times and signals ready.
|
|
147
|
-
|
|
148
|
-
Args:
|
|
149
|
-
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
150
|
-
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
151
|
-
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
152
|
-
body (bytes): The actual message body sent, containing the message payload.
|
|
153
|
-
"""
|
|
154
|
-
try:
|
|
155
|
-
# Parse message payload
|
|
156
|
-
message = body.decode("utf-8")
|
|
157
|
-
params = InitCommand.model_validate_json(message).tasking_parameters
|
|
158
|
-
# update default execution start/end time
|
|
159
|
-
self._sim_start_time = params.sim_start_time
|
|
160
|
-
self._sim_stop_time = params.sim_stop_time
|
|
161
|
-
self.ready()
|
|
162
|
-
|
|
163
|
-
except Exception as e:
|
|
164
|
-
logger.error(
|
|
165
|
-
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
166
|
-
)
|
|
167
|
-
print(traceback.format_exc())
|
|
168
|
-
|
|
169
|
-
def on_manager_start(self, ch, method, properties, body) -> None:
|
|
170
|
-
"""
|
|
171
|
-
Callback function for the managed application to respond to a start command sent from the manager.
|
|
172
|
-
Parses the scenario start/end time, wallclock epoch, and time scale factor and executes
|
|
173
|
-
the simulator in a background thread.
|
|
174
|
-
|
|
175
|
-
Args:
|
|
176
|
-
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
177
|
-
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
178
|
-
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
179
|
-
body (bytes): The actual message body sent, containing the message payload.
|
|
180
|
-
"""
|
|
181
|
-
# Parse message payload
|
|
182
|
-
message = body.decode("utf-8")
|
|
183
|
-
params = StartCommand.model_validate_json(message).tasking_parameters
|
|
184
|
-
logger.info(f"Received start command {params}")
|
|
185
|
-
try:
|
|
186
|
-
|
|
187
|
-
# check for optional start time
|
|
188
|
-
if params.sim_start_time is not None:
|
|
189
|
-
self._sim_start_time = params.sim_start_time
|
|
190
|
-
logger.info(f"Sim start time: {params.sim_start_time}")
|
|
191
|
-
# check for optional end time
|
|
192
|
-
if params.sim_stop_time is not None:
|
|
193
|
-
self._sim_stop_time = params.sim_stop_time
|
|
194
|
-
logger.info(f"Sim stop time: {params.sim_stop_time}")
|
|
195
|
-
|
|
196
|
-
threading.Thread(
|
|
197
|
-
target=self.simulator.execute,
|
|
198
|
-
kwargs={
|
|
199
|
-
"init_time": self._sim_start_time,
|
|
200
|
-
"duration": self._sim_stop_time - self._sim_start_time,
|
|
201
|
-
"time_step": self.time_step,
|
|
202
|
-
"wallclock_epoch": params.start_time,
|
|
203
|
-
"time_scale_factor": params.time_scaling_factor,
|
|
204
|
-
},
|
|
205
|
-
).start()
|
|
206
|
-
|
|
207
|
-
except Exception as e:
|
|
208
|
-
logger.error(
|
|
209
|
-
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
210
|
-
)
|
|
211
|
-
print(traceback.format_exc())
|
|
212
|
-
|
|
213
|
-
def on_manager_stop(self, ch, method, properties, body) -> None:
|
|
214
|
-
"""
|
|
215
|
-
Callback function for the managed application ('self') to respond to a stop command sent from the manager.
|
|
216
|
-
Parses the end time and updates the simulator.
|
|
217
|
-
|
|
218
|
-
Args:
|
|
219
|
-
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
220
|
-
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
221
|
-
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
222
|
-
body (bytes): The actual message body sent, containing the message payload.
|
|
223
|
-
"""
|
|
224
|
-
try:
|
|
225
|
-
# Parse message payload
|
|
226
|
-
message = body.decode("utf-8")
|
|
227
|
-
params = StopCommand.model_validate_json(message).tasking_parameters
|
|
228
|
-
logger.info(f"Received stop command {message}")
|
|
229
|
-
# update execution end time
|
|
230
|
-
self.simulator.set_end_time(params.sim_stop_time)
|
|
231
|
-
except Exception as e:
|
|
232
|
-
logger.error(
|
|
233
|
-
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
234
|
-
)
|
|
235
|
-
print(traceback.format_exc())
|
|
236
|
-
|
|
237
|
-
def on_manager_update(self, ch, method, properties, body) -> None:
|
|
238
|
-
"""
|
|
239
|
-
Callback function for the managed application ('self') to respond to an update command sent from the manager.
|
|
240
|
-
Parses the time scaling factor and scenario update time and updates the simulator.
|
|
241
|
-
|
|
242
|
-
Args:
|
|
243
|
-
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
244
|
-
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
245
|
-
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
246
|
-
body (bytes): The actual message body sent, containing the message payload.
|
|
247
|
-
"""
|
|
248
|
-
try:
|
|
249
|
-
# Parse message payload
|
|
250
|
-
message = body.decode("utf-8")
|
|
251
|
-
params = UpdateCommand.model_validate_json(message).tasking_parameters
|
|
252
|
-
logger.info(f"Received update command {message}")
|
|
253
|
-
# update execution time scale factor
|
|
254
|
-
self.simulator.set_time_scale_factor(
|
|
255
|
-
params.time_scaling_factor, params.sim_update_time
|
|
256
|
-
)
|
|
257
|
-
except Exception as e:
|
|
258
|
-
logger.error(
|
|
259
|
-
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
260
|
-
)
|
|
261
|
-
print(traceback.format_exc())
|
|
1
|
+
"""
|
|
2
|
+
Provides a base application that manages communication between a simulator and broker.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import threading
|
|
7
|
+
import traceback
|
|
8
|
+
from datetime import datetime, timedelta
|
|
9
|
+
|
|
10
|
+
from .application import Application
|
|
11
|
+
from .application_utils import ConnectionConfig
|
|
12
|
+
from .schemas import InitCommand, StartCommand, StopCommand, UpdateCommand
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ManagedApplication(Application):
|
|
18
|
+
"""
|
|
19
|
+
Managed NOS-T Application.
|
|
20
|
+
|
|
21
|
+
This object class defines the basic functionality for a NOS-T application
|
|
22
|
+
that utilizes an external Manager to command simulator execution.
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
prefix (str): execution namespace (prefix)
|
|
26
|
+
simulator (:obj:`Simulator`): simulator
|
|
27
|
+
client (:obj:`Client`): MQTT client
|
|
28
|
+
app_name (str): application name
|
|
29
|
+
app_description (str): application description
|
|
30
|
+
time_status_step (:obj:`timedelta`): scenario duration between time status messages
|
|
31
|
+
time_status_init (:obj:`datetime`): scenario time of first time status message
|
|
32
|
+
time_step (:obj:`timedelta`): scenario time step used in execution
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, app_name: str, app_description: str = None):
|
|
36
|
+
"""
|
|
37
|
+
Initializes a new managed application.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
app_name (str): application name
|
|
41
|
+
app_description (str): application description
|
|
42
|
+
"""
|
|
43
|
+
super().__init__(app_name, app_description)
|
|
44
|
+
self.time_step = None
|
|
45
|
+
self._sim_start_time = None
|
|
46
|
+
self._sim_stop_time = None
|
|
47
|
+
|
|
48
|
+
def start_up(
|
|
49
|
+
self,
|
|
50
|
+
prefix: str,
|
|
51
|
+
config: ConnectionConfig,
|
|
52
|
+
set_offset: bool = None,
|
|
53
|
+
time_status_step: timedelta = None,
|
|
54
|
+
time_status_init: datetime = None,
|
|
55
|
+
shut_down_when_terminated: bool = None,
|
|
56
|
+
time_step: timedelta = None,
|
|
57
|
+
manager_app_name: str = None,
|
|
58
|
+
) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Starts up the application by connecting to message broker, starting a background event loop,
|
|
61
|
+
subscribing to manager events, and registering callback functions.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
prefix (str): execution namespace (prefix)
|
|
65
|
+
config (:obj:`ConnectionConfig`): connection configuration
|
|
66
|
+
set_offset (bool): True, if the system clock offset shall be set using a NTP request prior to execution
|
|
67
|
+
time_status_step (:obj:`timedelta`): scenario duration between time status messages
|
|
68
|
+
time_status_init (:obj:`datetime`): scenario time for first time status message
|
|
69
|
+
shut_down_when_terminated (bool): True, if the application should shut down when the simulation is terminated
|
|
70
|
+
time_step (:obj:`timedelta`): scenario time step used in execution (Default: 1 second)
|
|
71
|
+
manager_app_name (str): manager application name (Default: manager)
|
|
72
|
+
"""
|
|
73
|
+
if (
|
|
74
|
+
set_offset is not None
|
|
75
|
+
and time_status_step is not None
|
|
76
|
+
and time_status_init is not None
|
|
77
|
+
and shut_down_when_terminated is not None
|
|
78
|
+
and time_step is not None
|
|
79
|
+
and manager_app_name is not None
|
|
80
|
+
):
|
|
81
|
+
self.set_offset = set_offset
|
|
82
|
+
self.time_status_step = time_status_step
|
|
83
|
+
self.time_status_init = time_status_init
|
|
84
|
+
self.shut_down_when_terminated = shut_down_when_terminated
|
|
85
|
+
self.time_step = time_step
|
|
86
|
+
self.manager_app_name = manager_app_name
|
|
87
|
+
else:
|
|
88
|
+
self.config = config
|
|
89
|
+
parameters = getattr(
|
|
90
|
+
self.config.rc.simulation_configuration.execution_parameters,
|
|
91
|
+
"managed_application",
|
|
92
|
+
None,
|
|
93
|
+
)
|
|
94
|
+
self.set_offset = parameters.set_offset
|
|
95
|
+
self.time_status_step = parameters.time_status_step
|
|
96
|
+
self.time_status_init = parameters.time_status_init
|
|
97
|
+
self.shut_down_when_terminated = parameters.shut_down_when_terminated
|
|
98
|
+
self.time_step = parameters.time_step
|
|
99
|
+
self.manager_app_name = parameters.manager_app_name
|
|
100
|
+
|
|
101
|
+
# start up base application
|
|
102
|
+
super().start_up(
|
|
103
|
+
prefix,
|
|
104
|
+
config,
|
|
105
|
+
self.set_offset,
|
|
106
|
+
self.time_status_step,
|
|
107
|
+
self.time_status_init,
|
|
108
|
+
self.shut_down_when_terminated,
|
|
109
|
+
)
|
|
110
|
+
self.time_step = self.time_step
|
|
111
|
+
self.manager_app_name = self.manager_app_name
|
|
112
|
+
|
|
113
|
+
# Register callback functions
|
|
114
|
+
self.add_message_callback(
|
|
115
|
+
app_name=self.manager_app_name,
|
|
116
|
+
app_topic="init",
|
|
117
|
+
user_callback=self.on_manager_init,
|
|
118
|
+
)
|
|
119
|
+
self.add_message_callback(
|
|
120
|
+
app_name=self.manager_app_name,
|
|
121
|
+
app_topic="start",
|
|
122
|
+
user_callback=self.on_manager_start,
|
|
123
|
+
)
|
|
124
|
+
self.add_message_callback(
|
|
125
|
+
app_name=self.manager_app_name,
|
|
126
|
+
app_topic="stop",
|
|
127
|
+
user_callback=self.on_manager_stop,
|
|
128
|
+
)
|
|
129
|
+
self.add_message_callback(
|
|
130
|
+
app_name=self.manager_app_name,
|
|
131
|
+
app_topic="update",
|
|
132
|
+
user_callback=self.on_manager_update,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def shut_down(self) -> None:
|
|
136
|
+
"""
|
|
137
|
+
Shuts down the application by stopping the background event loop and disconnecting
|
|
138
|
+
the application from the broker.
|
|
139
|
+
"""
|
|
140
|
+
# shut down base application
|
|
141
|
+
super().shut_down()
|
|
142
|
+
|
|
143
|
+
def on_manager_init(self, ch, method, properties, body) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Callback function for the managed application to respond to an initilize command sent from the manager.
|
|
146
|
+
Parses the scenario start/end times and signals ready.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
150
|
+
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
151
|
+
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
152
|
+
body (bytes): The actual message body sent, containing the message payload.
|
|
153
|
+
"""
|
|
154
|
+
try:
|
|
155
|
+
# Parse message payload
|
|
156
|
+
message = body.decode("utf-8")
|
|
157
|
+
params = InitCommand.model_validate_json(message).tasking_parameters
|
|
158
|
+
# update default execution start/end time
|
|
159
|
+
self._sim_start_time = params.sim_start_time
|
|
160
|
+
self._sim_stop_time = params.sim_stop_time
|
|
161
|
+
self.ready()
|
|
162
|
+
|
|
163
|
+
except Exception as e:
|
|
164
|
+
logger.error(
|
|
165
|
+
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
166
|
+
)
|
|
167
|
+
print(traceback.format_exc())
|
|
168
|
+
|
|
169
|
+
def on_manager_start(self, ch, method, properties, body) -> None:
|
|
170
|
+
"""
|
|
171
|
+
Callback function for the managed application to respond to a start command sent from the manager.
|
|
172
|
+
Parses the scenario start/end time, wallclock epoch, and time scale factor and executes
|
|
173
|
+
the simulator in a background thread.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
177
|
+
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
178
|
+
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
179
|
+
body (bytes): The actual message body sent, containing the message payload.
|
|
180
|
+
"""
|
|
181
|
+
# Parse message payload
|
|
182
|
+
message = body.decode("utf-8")
|
|
183
|
+
params = StartCommand.model_validate_json(message).tasking_parameters
|
|
184
|
+
logger.info(f"Received start command {params}")
|
|
185
|
+
try:
|
|
186
|
+
|
|
187
|
+
# check for optional start time
|
|
188
|
+
if params.sim_start_time is not None:
|
|
189
|
+
self._sim_start_time = params.sim_start_time
|
|
190
|
+
logger.info(f"Sim start time: {params.sim_start_time}")
|
|
191
|
+
# check for optional end time
|
|
192
|
+
if params.sim_stop_time is not None:
|
|
193
|
+
self._sim_stop_time = params.sim_stop_time
|
|
194
|
+
logger.info(f"Sim stop time: {params.sim_stop_time}")
|
|
195
|
+
|
|
196
|
+
threading.Thread(
|
|
197
|
+
target=self.simulator.execute,
|
|
198
|
+
kwargs={
|
|
199
|
+
"init_time": self._sim_start_time,
|
|
200
|
+
"duration": self._sim_stop_time - self._sim_start_time,
|
|
201
|
+
"time_step": self.time_step,
|
|
202
|
+
"wallclock_epoch": params.start_time,
|
|
203
|
+
"time_scale_factor": params.time_scaling_factor,
|
|
204
|
+
},
|
|
205
|
+
).start()
|
|
206
|
+
|
|
207
|
+
except Exception as e:
|
|
208
|
+
logger.error(
|
|
209
|
+
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
210
|
+
)
|
|
211
|
+
print(traceback.format_exc())
|
|
212
|
+
|
|
213
|
+
def on_manager_stop(self, ch, method, properties, body) -> None:
|
|
214
|
+
"""
|
|
215
|
+
Callback function for the managed application ('self') to respond to a stop command sent from the manager.
|
|
216
|
+
Parses the end time and updates the simulator.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
220
|
+
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
221
|
+
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
222
|
+
body (bytes): The actual message body sent, containing the message payload.
|
|
223
|
+
"""
|
|
224
|
+
try:
|
|
225
|
+
# Parse message payload
|
|
226
|
+
message = body.decode("utf-8")
|
|
227
|
+
params = StopCommand.model_validate_json(message).tasking_parameters
|
|
228
|
+
logger.info(f"Received stop command {message}")
|
|
229
|
+
# update execution end time
|
|
230
|
+
self.simulator.set_end_time(params.sim_stop_time)
|
|
231
|
+
except Exception as e:
|
|
232
|
+
logger.error(
|
|
233
|
+
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
234
|
+
)
|
|
235
|
+
print(traceback.format_exc())
|
|
236
|
+
|
|
237
|
+
def on_manager_update(self, ch, method, properties, body) -> None:
|
|
238
|
+
"""
|
|
239
|
+
Callback function for the managed application ('self') to respond to an update command sent from the manager.
|
|
240
|
+
Parses the time scaling factor and scenario update time and updates the simulator.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
ch (:obj:`pika.channel.Channel`): The channel object used to communicate with the RabbitMQ server.
|
|
244
|
+
method (:obj:`pika.spec.Basic.Deliver`): Delivery-related information such as delivery tag, exchange, and routing key.
|
|
245
|
+
properties (:obj:`pika.BasicProperties`): Message properties including content type, headers, and more.
|
|
246
|
+
body (bytes): The actual message body sent, containing the message payload.
|
|
247
|
+
"""
|
|
248
|
+
try:
|
|
249
|
+
# Parse message payload
|
|
250
|
+
message = body.decode("utf-8")
|
|
251
|
+
params = UpdateCommand.model_validate_json(message).tasking_parameters
|
|
252
|
+
logger.info(f"Received update command {message}")
|
|
253
|
+
# update execution time scale factor
|
|
254
|
+
self.simulator.set_time_scale_factor(
|
|
255
|
+
params.time_scaling_factor, params.sim_update_time
|
|
256
|
+
)
|
|
257
|
+
except Exception as e:
|
|
258
|
+
logger.error(
|
|
259
|
+
f"Exception (topic: {method.routing_key}, payload: {message}): {e}"
|
|
260
|
+
)
|
|
261
|
+
print(traceback.format_exc())
|