isar 1.15.0__py3-none-any.whl → 1.34.9__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.
- isar/__init__.py +2 -5
- isar/apis/api.py +159 -66
- isar/apis/models/__init__.py +0 -1
- isar/apis/models/models.py +22 -12
- isar/apis/models/start_mission_definition.py +128 -123
- isar/apis/robot_control/robot_controller.py +41 -0
- isar/apis/schedule/scheduling_controller.py +135 -121
- isar/apis/security/authentication.py +5 -5
- isar/config/certs/ca-cert.pem +32 -32
- isar/config/keyvault/keyvault_service.py +1 -2
- isar/config/log.py +47 -39
- isar/config/logging.conf +16 -31
- isar/config/open_telemetry.py +102 -0
- isar/config/predefined_mission_definition/default_exr.json +49 -0
- isar/config/predefined_mission_definition/default_mission.json +1 -5
- isar/config/predefined_mission_definition/default_turtlebot.json +4 -11
- isar/config/predefined_missions/default.json +67 -87
- isar/config/predefined_missions/default_extra_capabilities.json +107 -0
- isar/config/settings.py +119 -142
- isar/eventhandlers/eventhandler.py +123 -0
- isar/mission_planner/local_planner.py +6 -20
- isar/mission_planner/mission_planner_interface.py +1 -1
- isar/models/events.py +184 -0
- isar/models/status.py +18 -0
- isar/modules.py +118 -205
- isar/robot/robot.py +377 -0
- isar/robot/robot_battery.py +60 -0
- isar/robot/robot_monitor_mission.py +357 -0
- isar/robot/robot_pause_mission.py +74 -0
- isar/robot/robot_resume_mission.py +67 -0
- isar/robot/robot_start_mission.py +66 -0
- isar/robot/robot_status.py +61 -0
- isar/robot/robot_stop_mission.py +68 -0
- isar/robot/robot_upload_inspection.py +75 -0
- isar/script.py +171 -0
- isar/services/service_connections/mqtt/mqtt_client.py +47 -11
- isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +32 -0
- isar/services/service_connections/mqtt/robot_info_publisher.py +4 -3
- isar/services/service_connections/persistent_memory.py +69 -0
- isar/services/utilities/mqtt_utilities.py +93 -0
- isar/services/utilities/robot_utilities.py +20 -0
- isar/services/utilities/scheduling_utilities.py +393 -65
- isar/state_machine/state_machine.py +227 -486
- isar/state_machine/states/__init__.py +0 -7
- isar/state_machine/states/await_next_mission.py +114 -0
- isar/state_machine/states/blocked_protective_stop.py +60 -0
- isar/state_machine/states/going_to_lockdown.py +95 -0
- isar/state_machine/states/going_to_recharging.py +92 -0
- isar/state_machine/states/home.py +115 -0
- isar/state_machine/states/intervention_needed.py +77 -0
- isar/state_machine/states/lockdown.py +38 -0
- isar/state_machine/states/maintenance.py +36 -0
- isar/state_machine/states/monitor.py +137 -166
- isar/state_machine/states/offline.py +60 -0
- isar/state_machine/states/paused.py +92 -23
- isar/state_machine/states/pausing.py +48 -0
- isar/state_machine/states/pausing_return_home.py +48 -0
- isar/state_machine/states/recharging.py +80 -0
- isar/state_machine/states/resuming.py +57 -0
- isar/state_machine/states/resuming_return_home.py +64 -0
- isar/state_machine/states/return_home_paused.py +109 -0
- isar/state_machine/states/returning_home.py +217 -0
- isar/state_machine/states/stopping.py +61 -0
- isar/state_machine/states/stopping_due_to_maintenance.py +61 -0
- isar/state_machine/states/stopping_go_to_lockdown.py +60 -0
- isar/state_machine/states/stopping_go_to_recharge.py +51 -0
- isar/state_machine/states/stopping_return_home.py +77 -0
- isar/state_machine/states/unknown_status.py +72 -0
- isar/state_machine/states_enum.py +22 -5
- isar/state_machine/transitions/mission.py +192 -0
- isar/state_machine/transitions/return_home.py +106 -0
- isar/state_machine/transitions/robot_status.py +80 -0
- isar/state_machine/utils/common_event_handlers.py +73 -0
- isar/storage/blob_storage.py +71 -45
- isar/storage/local_storage.py +28 -14
- isar/storage/storage_interface.py +28 -6
- isar/storage/uploader.py +184 -55
- isar/storage/utilities.py +35 -27
- isar-1.34.9.dist-info/METADATA +496 -0
- isar-1.34.9.dist-info/RECORD +135 -0
- {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/WHEEL +1 -1
- isar-1.34.9.dist-info/entry_points.txt +3 -0
- robot_interface/models/exceptions/__init__.py +0 -7
- robot_interface/models/exceptions/robot_exceptions.py +274 -4
- robot_interface/models/initialize/__init__.py +0 -1
- robot_interface/models/inspection/__init__.py +0 -13
- robot_interface/models/inspection/inspection.py +43 -34
- robot_interface/models/mission/mission.py +18 -14
- robot_interface/models/mission/status.py +20 -25
- robot_interface/models/mission/task.py +156 -92
- robot_interface/models/robots/battery_state.py +6 -0
- robot_interface/models/robots/media.py +13 -0
- robot_interface/models/robots/robot_model.py +7 -7
- robot_interface/robot_interface.py +135 -66
- robot_interface/telemetry/mqtt_client.py +84 -12
- robot_interface/telemetry/payloads.py +111 -12
- robot_interface/utilities/json_service.py +7 -1
- isar/config/predefined_missions/default_turtlebot.json +0 -110
- isar/config/predefined_poses/__init__.py +0 -0
- isar/config/predefined_poses/predefined_poses.py +0 -616
- isar/config/settings.env +0 -26
- isar/mission_planner/sequential_task_selector.py +0 -23
- isar/mission_planner/task_selector_interface.py +0 -31
- isar/models/communication/__init__.py +0 -0
- isar/models/communication/message.py +0 -12
- isar/models/communication/queues/__init__.py +0 -4
- isar/models/communication/queues/queue_io.py +0 -12
- isar/models/communication/queues/queue_timeout_error.py +0 -2
- isar/models/communication/queues/queues.py +0 -19
- isar/models/communication/queues/status_queue.py +0 -20
- isar/models/mission_metadata/__init__.py +0 -0
- isar/services/readers/__init__.py +0 -0
- isar/services/readers/base_reader.py +0 -37
- isar/services/service_connections/mqtt/robot_status_publisher.py +0 -93
- isar/services/service_connections/stid/__init__.py +0 -0
- isar/services/service_connections/stid/stid_service.py +0 -45
- isar/services/utilities/queue_utilities.py +0 -39
- isar/state_machine/states/idle.py +0 -40
- isar/state_machine/states/initialize.py +0 -60
- isar/state_machine/states/initiate.py +0 -129
- isar/state_machine/states/off.py +0 -18
- isar/state_machine/states/stop.py +0 -78
- isar/storage/slimm_storage.py +0 -181
- isar-1.15.0.dist-info/METADATA +0 -417
- isar-1.15.0.dist-info/RECORD +0 -113
- robot_interface/models/initialize/initialize_params.py +0 -9
- robot_interface/models/mission/step.py +0 -211
- {isar-1.15.0.dist-info → isar-1.34.9.dist-info/licenses}/LICENSE +0 -0
- {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/top_level.txt +0 -0
isar/__init__.py
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
from
|
|
1
|
+
from importlib.metadata import version
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
__version__ = get_distribution(__name__).version
|
|
5
|
-
except DistributionNotFound:
|
|
6
|
-
pass # package is not installed
|
|
3
|
+
__version__ = version(__package__ or __name__)
|
isar/apis/api.py
CHANGED
|
@@ -1,66 +1,70 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import logging
|
|
2
|
-
import
|
|
3
|
+
import time
|
|
4
|
+
from datetime import datetime, timezone
|
|
3
5
|
from http import HTTPStatus
|
|
4
6
|
from logging import Logger
|
|
5
7
|
from typing import List, Union
|
|
6
8
|
|
|
7
9
|
import click
|
|
8
10
|
import uvicorn
|
|
9
|
-
from fastapi import FastAPI,
|
|
11
|
+
from fastapi import FastAPI, Security
|
|
10
12
|
from fastapi.middleware.cors import CORSMiddleware
|
|
11
13
|
from fastapi.routing import APIRouter
|
|
12
|
-
from injector import inject
|
|
13
|
-
from opencensus.ext.azure.trace_exporter import AzureExporter
|
|
14
|
-
from opencensus.trace.attributes_helper import COMMON_ATTRIBUTES
|
|
15
|
-
from opencensus.trace.samplers import ProbabilitySampler
|
|
16
|
-
from opencensus.trace.span import SpanKind
|
|
17
|
-
from opencensus.trace.tracer import Tracer
|
|
18
14
|
from pydantic import AnyHttpUrl
|
|
19
15
|
|
|
20
16
|
from isar.apis.models.models import ControlMissionResponse, StartMissionResponse
|
|
17
|
+
from isar.apis.robot_control.robot_controller import RobotController
|
|
21
18
|
from isar.apis.schedule.scheduling_controller import SchedulingController
|
|
22
19
|
from isar.apis.security.authentication import Authenticator
|
|
23
|
-
from isar.config.configuration_error import ConfigurationError
|
|
24
|
-
from isar.config.keyvault.keyvault_error import KeyvaultError
|
|
25
20
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
26
21
|
from isar.config.settings import settings
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
from robot_interface.telemetry.mqtt_client import MqttClientInterface
|
|
23
|
+
from robot_interface.telemetry.payloads import StartUpMessagePayload
|
|
24
|
+
from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
30
25
|
|
|
31
26
|
|
|
32
27
|
class API:
|
|
33
|
-
@inject
|
|
34
28
|
def __init__(
|
|
35
29
|
self,
|
|
36
30
|
authenticator: Authenticator,
|
|
37
31
|
scheduling_controller: SchedulingController,
|
|
38
|
-
|
|
32
|
+
robot_controller: RobotController,
|
|
33
|
+
keyvault: Keyvault,
|
|
34
|
+
mqtt_publisher: MqttClientInterface,
|
|
39
35
|
port: int = settings.API_PORT,
|
|
40
|
-
azure_ai_logging_enabled: bool = settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED,
|
|
41
36
|
) -> None:
|
|
42
37
|
self.authenticator: Authenticator = authenticator
|
|
43
38
|
self.scheduling_controller: SchedulingController = scheduling_controller
|
|
44
|
-
self.
|
|
39
|
+
self.robot_controller: RobotController = robot_controller
|
|
40
|
+
self.keyvault: Keyvault = keyvault
|
|
45
41
|
self.host: str = "0.0.0.0" # Locking uvicorn to use 0.0.0.0
|
|
46
42
|
self.port: int = port
|
|
47
|
-
self.
|
|
43
|
+
self.mqtt_publisher: MqttClientInterface = mqtt_publisher
|
|
48
44
|
|
|
49
45
|
self.logger: Logger = logging.getLogger("api")
|
|
50
46
|
|
|
51
47
|
self.app: FastAPI = self._create_app()
|
|
48
|
+
self.server = self._setup_server()
|
|
52
49
|
|
|
53
50
|
def get_app(self) -> FastAPI:
|
|
54
51
|
return self.app
|
|
55
52
|
|
|
56
|
-
def
|
|
57
|
-
uvicorn.
|
|
53
|
+
def _setup_server(self) -> uvicorn.Server:
|
|
54
|
+
config = uvicorn.Config(
|
|
58
55
|
self.app,
|
|
59
56
|
port=self.port,
|
|
60
57
|
host=self.host,
|
|
61
58
|
reload=False,
|
|
62
59
|
log_config=None,
|
|
63
60
|
)
|
|
61
|
+
return uvicorn.Server(config)
|
|
62
|
+
|
|
63
|
+
def wait_for_api_server_ready(self) -> None:
|
|
64
|
+
while not self.server.started:
|
|
65
|
+
time.sleep(0.01)
|
|
66
|
+
self.logger.info("Uvicorn server has been started")
|
|
67
|
+
self._publish_startup_message()
|
|
64
68
|
|
|
65
69
|
def _create_app(self) -> FastAPI:
|
|
66
70
|
tags_metadata = [
|
|
@@ -71,7 +75,10 @@ class API:
|
|
|
71
75
|
]
|
|
72
76
|
app = FastAPI(
|
|
73
77
|
openapi_tags=tags_metadata,
|
|
74
|
-
on_startup=[
|
|
78
|
+
on_startup=[
|
|
79
|
+
self.authenticator.load_config,
|
|
80
|
+
self._log_startup_message,
|
|
81
|
+
],
|
|
75
82
|
swagger_ui_oauth2_redirect_url="/oauth2-redirect",
|
|
76
83
|
swagger_ui_init_oauth={
|
|
77
84
|
"usePkceWithAuthorizationCodeGrant": True,
|
|
@@ -92,13 +99,12 @@ class API:
|
|
|
92
99
|
allow_headers=["*"],
|
|
93
100
|
)
|
|
94
101
|
|
|
95
|
-
if self.azure_ai_logging_enabled:
|
|
96
|
-
self._add_request_logging_middleware(app)
|
|
97
|
-
|
|
98
102
|
app.include_router(router=self._create_scheduler_router())
|
|
99
103
|
|
|
100
104
|
app.include_router(router=self._create_info_router())
|
|
101
105
|
|
|
106
|
+
app.include_router(router=self._create_media_control_router())
|
|
107
|
+
|
|
102
108
|
return app
|
|
103
109
|
|
|
104
110
|
def _create_scheduler_router(self) -> APIRouter:
|
|
@@ -146,6 +152,31 @@ class API:
|
|
|
146
152
|
HTTPStatus.CONFLICT.value: {
|
|
147
153
|
"description": "Conflict - Invalid command in the current state",
|
|
148
154
|
},
|
|
155
|
+
HTTPStatus.BAD_REQUEST.value: {
|
|
156
|
+
"description": "Bad request - Robot does not have the capabilities to perform the mission",
|
|
157
|
+
},
|
|
158
|
+
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
159
|
+
"description": "Internal Server Error - Current state of state machine unknown",
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
)
|
|
163
|
+
router.add_api_route(
|
|
164
|
+
path="/schedule/return-home",
|
|
165
|
+
endpoint=self.scheduling_controller.return_home,
|
|
166
|
+
methods=["POST"],
|
|
167
|
+
dependencies=[authentication_dependency],
|
|
168
|
+
summary="Start return home mission",
|
|
169
|
+
responses={
|
|
170
|
+
HTTPStatus.OK.value: {
|
|
171
|
+
"description": "Return home mission succesfully started",
|
|
172
|
+
"model": StartMissionResponse,
|
|
173
|
+
},
|
|
174
|
+
HTTPStatus.UNPROCESSABLE_ENTITY.value: {
|
|
175
|
+
"description": "Invalid body - The JSON is incorrect",
|
|
176
|
+
},
|
|
177
|
+
HTTPStatus.CONFLICT.value: {
|
|
178
|
+
"description": "Conflict - Invalid command in the current state",
|
|
179
|
+
},
|
|
149
180
|
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
150
181
|
"description": "Internal Server Error - Current state of state machine unknown",
|
|
151
182
|
},
|
|
@@ -162,9 +193,15 @@ class API:
|
|
|
162
193
|
"description": "Mission succesfully stopped",
|
|
163
194
|
"model": ControlMissionResponse,
|
|
164
195
|
},
|
|
196
|
+
HTTPStatus.UNPROCESSABLE_ENTITY.value: {
|
|
197
|
+
"description": "Invalid body - The JSON is incorrect",
|
|
198
|
+
},
|
|
165
199
|
HTTPStatus.CONFLICT.value: {
|
|
166
200
|
"description": "Conflict - Invalid command in the current state",
|
|
167
201
|
},
|
|
202
|
+
HTTPStatus.BAD_REQUEST.value: {
|
|
203
|
+
"description": "Bad request - Robot does not have the capabilities to perform the mission",
|
|
204
|
+
},
|
|
168
205
|
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
169
206
|
"description": "Internal Server Error - Current state of state machine unknown",
|
|
170
207
|
},
|
|
@@ -209,38 +246,86 @@ class API:
|
|
|
209
246
|
},
|
|
210
247
|
)
|
|
211
248
|
router.add_api_route(
|
|
212
|
-
path="/schedule/
|
|
213
|
-
endpoint=self.scheduling_controller.
|
|
249
|
+
path="/schedule/lockdown",
|
|
250
|
+
endpoint=self.scheduling_controller.lockdown,
|
|
251
|
+
methods=["POST"],
|
|
252
|
+
dependencies=[authentication_dependency],
|
|
253
|
+
summary="Send the robot to dock and ensure that it stays there",
|
|
254
|
+
responses={
|
|
255
|
+
HTTPStatus.OK.value: {"description": "Robot going to dock"},
|
|
256
|
+
HTTPStatus.CONFLICT.value: {
|
|
257
|
+
"description": "Conflict - Invalid command in the current state"
|
|
258
|
+
},
|
|
259
|
+
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
260
|
+
"description": "Internal Server Error - Current state of state machine unknown"
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
)
|
|
264
|
+
router.add_api_route(
|
|
265
|
+
path="/schedule/release-lockdown",
|
|
266
|
+
endpoint=self.scheduling_controller.release_lockdown,
|
|
214
267
|
methods=["POST"],
|
|
215
268
|
dependencies=[authentication_dependency],
|
|
216
|
-
summary="
|
|
269
|
+
summary="Allow the robot to start missions again",
|
|
217
270
|
responses={
|
|
218
271
|
HTTPStatus.OK.value: {
|
|
219
|
-
"description": "
|
|
272
|
+
"description": "Robot is able to receive missions again"
|
|
220
273
|
},
|
|
221
274
|
HTTPStatus.CONFLICT.value: {
|
|
222
|
-
"description": "Conflict - Invalid command in the current state"
|
|
275
|
+
"description": "Conflict - Invalid command in the current state"
|
|
223
276
|
},
|
|
224
277
|
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
225
|
-
"description": "Internal Server Error - Current state of state machine unknown"
|
|
278
|
+
"description": "Internal Server Error - Current state of state machine unknown"
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
)
|
|
282
|
+
router.add_api_route(
|
|
283
|
+
path="/schedule/maintenance-mode",
|
|
284
|
+
endpoint=self.scheduling_controller.set_maintenance_mode,
|
|
285
|
+
methods=["POST"],
|
|
286
|
+
dependencies=[authentication_dependency],
|
|
287
|
+
summary="Place the robot in maintenance mode, where it will not run missions before begin released from maintenance mode",
|
|
288
|
+
responses={
|
|
289
|
+
HTTPStatus.OK.value: {
|
|
290
|
+
"description": "Robot is in maintenance mode and cannot receive missions"
|
|
291
|
+
},
|
|
292
|
+
HTTPStatus.CONFLICT.value: {"description": "Conflict"},
|
|
293
|
+
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
294
|
+
"description": "Internal Server Error"
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
)
|
|
298
|
+
router.add_api_route(
|
|
299
|
+
path="/schedule/release-maintenance-mode",
|
|
300
|
+
endpoint=self.scheduling_controller.release_maintenance_mode,
|
|
301
|
+
methods=["POST"],
|
|
302
|
+
dependencies=[authentication_dependency],
|
|
303
|
+
summary="Allow the robot to start missions again",
|
|
304
|
+
responses={
|
|
305
|
+
HTTPStatus.OK.value: {
|
|
306
|
+
"description": "Robot is able to receive missions again"
|
|
307
|
+
},
|
|
308
|
+
HTTPStatus.CONFLICT.value: {"description": "Conflict"},
|
|
309
|
+
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
310
|
+
"description": "Internal Server Error"
|
|
226
311
|
},
|
|
227
312
|
},
|
|
228
313
|
)
|
|
229
314
|
router.add_api_route(
|
|
230
|
-
path="/schedule/
|
|
231
|
-
endpoint=self.scheduling_controller.
|
|
315
|
+
path="/schedule/release-intervention-needed",
|
|
316
|
+
endpoint=self.scheduling_controller.release_intervention_needed,
|
|
232
317
|
methods=["POST"],
|
|
233
318
|
dependencies=[authentication_dependency],
|
|
234
|
-
summary="
|
|
319
|
+
summary="Release the intervention needed state",
|
|
235
320
|
responses={
|
|
236
321
|
HTTPStatus.OK.value: {
|
|
237
|
-
"description": "
|
|
322
|
+
"description": "Robot released from intervention needed state"
|
|
238
323
|
},
|
|
239
324
|
HTTPStatus.CONFLICT.value: {
|
|
240
|
-
"description": "Conflict - Invalid command in the current state"
|
|
325
|
+
"description": "Conflict - Invalid command in the current state"
|
|
241
326
|
},
|
|
242
327
|
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
243
|
-
"description": "Internal Server Error - Current state of state machine unknown"
|
|
328
|
+
"description": "Internal Server Error - Current state of state machine unknown"
|
|
244
329
|
},
|
|
245
330
|
},
|
|
246
331
|
)
|
|
@@ -254,7 +339,7 @@ class API:
|
|
|
254
339
|
|
|
255
340
|
router.add_api_route(
|
|
256
341
|
path="/info/robot-settings",
|
|
257
|
-
endpoint=self.
|
|
342
|
+
endpoint=self.robot_controller.get_info,
|
|
258
343
|
methods=["GET"],
|
|
259
344
|
dependencies=[authentication_dependency],
|
|
260
345
|
summary="Information about the robot-settings",
|
|
@@ -262,6 +347,29 @@ class API:
|
|
|
262
347
|
|
|
263
348
|
return router
|
|
264
349
|
|
|
350
|
+
def _create_media_control_router(self) -> APIRouter:
|
|
351
|
+
router: APIRouter = APIRouter(tags=["Media"])
|
|
352
|
+
|
|
353
|
+
authentication_dependency: Security = Security(self.authenticator.get_scheme())
|
|
354
|
+
|
|
355
|
+
router.add_api_route(
|
|
356
|
+
path="/media/media-stream-config",
|
|
357
|
+
endpoint=self.robot_controller.generate_media_config,
|
|
358
|
+
methods=["GET"],
|
|
359
|
+
dependencies=[authentication_dependency],
|
|
360
|
+
summary="Generates a media stream connection config",
|
|
361
|
+
responses={
|
|
362
|
+
HTTPStatus.OK.value: {
|
|
363
|
+
"description": "Media stream was successfully generated",
|
|
364
|
+
},
|
|
365
|
+
HTTPStatus.NO_CONTENT.value: {
|
|
366
|
+
"description": "Robot has no media config",
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
return router
|
|
372
|
+
|
|
265
373
|
def _log_startup_message(self) -> None:
|
|
266
374
|
address_format = "%s://%s:%d/docs"
|
|
267
375
|
message = f"Uvicorn running on {address_format} (Press CTRL+C to quit)"
|
|
@@ -279,35 +387,20 @@ class API:
|
|
|
279
387
|
extra={"color_message": color_message},
|
|
280
388
|
)
|
|
281
389
|
|
|
282
|
-
def
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
connection_string = self.keyvault_client.get_secret(
|
|
286
|
-
"application-insights-connection-string"
|
|
287
|
-
).value
|
|
288
|
-
except KeyvaultError:
|
|
289
|
-
message: str = (
|
|
290
|
-
"Missing connection string for Application Insights in key vault. "
|
|
291
|
-
)
|
|
292
|
-
self.logger.critical(message)
|
|
293
|
-
raise ConfigurationError(message)
|
|
294
|
-
|
|
295
|
-
@app.middleware("http")
|
|
296
|
-
async def middlewareOpencensus(request: Request, call_next):
|
|
297
|
-
tracer = Tracer(
|
|
298
|
-
exporter=AzureExporter(connection_string=connection_string),
|
|
299
|
-
sampler=ProbabilitySampler(1.0),
|
|
300
|
-
)
|
|
301
|
-
with tracer.span("main") as span:
|
|
302
|
-
span.span_kind = SpanKind.SERVER
|
|
390
|
+
def _publish_startup_message(self) -> None:
|
|
391
|
+
if not self.mqtt_publisher:
|
|
392
|
+
return
|
|
303
393
|
|
|
304
|
-
|
|
394
|
+
payload: StartUpMessagePayload = StartUpMessagePayload(
|
|
395
|
+
isar_id=settings.ISAR_ID,
|
|
396
|
+
timestamp=datetime.now(timezone.utc),
|
|
397
|
+
)
|
|
305
398
|
|
|
306
|
-
|
|
307
|
-
attribute_key=HTTP_STATUS_CODE, attribute_value=response.status_code
|
|
308
|
-
)
|
|
309
|
-
tracer.add_attribute_to_current_span(
|
|
310
|
-
attribute_key=HTTP_URL, attribute_value=str(request.url)
|
|
311
|
-
)
|
|
399
|
+
self.logger.info("Publishing startup message to MQTT broker")
|
|
312
400
|
|
|
313
|
-
|
|
401
|
+
self.mqtt_publisher.publish(
|
|
402
|
+
topic=settings.TOPIC_ISAR_STARTUP,
|
|
403
|
+
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
404
|
+
qos=1,
|
|
405
|
+
retain=True,
|
|
406
|
+
)
|
isar/apis/models/__init__.py
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .models import InputPose, StartMissionResponse
|
isar/apis/models/models.py
CHANGED
|
@@ -3,16 +3,14 @@ from typing import List, Optional
|
|
|
3
3
|
from alitra import Frame, Orientation, Pose, Position
|
|
4
4
|
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
class StepResponse(BaseModel):
|
|
8
|
-
id: str
|
|
9
|
-
type: str
|
|
6
|
+
from robot_interface.models.mission.task import TaskTypes
|
|
10
7
|
|
|
11
8
|
|
|
12
9
|
class TaskResponse(BaseModel):
|
|
13
10
|
id: str
|
|
14
|
-
tag_id: Optional[str]
|
|
15
|
-
|
|
11
|
+
tag_id: Optional[str] = None
|
|
12
|
+
inspection_id: Optional[str] = None
|
|
13
|
+
type: TaskTypes
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class StartMissionResponse(BaseModel):
|
|
@@ -21,12 +19,24 @@ class StartMissionResponse(BaseModel):
|
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
class ControlMissionResponse(BaseModel):
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
success: bool
|
|
23
|
+
failure_reason: Optional[str] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MissionStartResponse(BaseModel):
|
|
27
|
+
mission_id: Optional[str] = None
|
|
28
|
+
mission_started: bool
|
|
29
|
+
mission_not_started_reason: Optional[str] = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class LockdownResponse(BaseModel):
|
|
33
|
+
lockdown_started: bool
|
|
34
|
+
failure_reason: Optional[str] = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class MaintenanceResponse(BaseModel):
|
|
38
|
+
is_maintenance_mode: bool
|
|
39
|
+
failure_reason: Optional[str] = None
|
|
30
40
|
|
|
31
41
|
|
|
32
42
|
class RobotInfoResponse(BaseModel):
|