isar 1.30.3__py3-none-any.whl → 1.30.4__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 isar might be problematic. Click here for more details.
- isar/apis/api.py +40 -3
- isar/config/settings.py +2 -0
- isar/modules.py +11 -10
- isar/script.py +3 -1
- isar/state_machine/transitions/functions/start_mission.py +1 -1
- {isar-1.30.3.dist-info → isar-1.30.4.dist-info}/METADATA +1 -1
- {isar-1.30.3.dist-info → isar-1.30.4.dist-info}/RECORD +12 -12
- robot_interface/telemetry/payloads.py +6 -0
- {isar-1.30.3.dist-info → isar-1.30.4.dist-info}/WHEEL +0 -0
- {isar-1.30.3.dist-info → isar-1.30.4.dist-info}/entry_points.txt +0 -0
- {isar-1.30.3.dist-info → isar-1.30.4.dist-info}/licenses/LICENSE +0 -0
- {isar-1.30.3.dist-info → isar-1.30.4.dist-info}/top_level.txt +0 -0
isar/apis/api.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import logging
|
|
3
|
+
import time
|
|
4
|
+
from datetime import datetime, timezone
|
|
2
5
|
from http import HTTPStatus
|
|
3
6
|
from logging import Logger
|
|
4
7
|
from typing import List, Union
|
|
@@ -24,6 +27,9 @@ from isar.config.configuration_error import ConfigurationError
|
|
|
24
27
|
from isar.config.keyvault.keyvault_error import KeyvaultError
|
|
25
28
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
26
29
|
from isar.config.settings import settings
|
|
30
|
+
from robot_interface.telemetry.mqtt_client import MqttClientInterface
|
|
31
|
+
from robot_interface.telemetry.payloads import StartUpMessagePayload
|
|
32
|
+
from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
27
33
|
|
|
28
34
|
HTTP_URL = COMMON_ATTRIBUTES["HTTP_URL"]
|
|
29
35
|
HTTP_STATUS_CODE = COMMON_ATTRIBUTES["HTTP_STATUS_CODE"]
|
|
@@ -37,6 +43,7 @@ class API:
|
|
|
37
43
|
scheduling_controller: SchedulingController,
|
|
38
44
|
robot_controller: RobotController,
|
|
39
45
|
keyvault: Keyvault,
|
|
46
|
+
mqtt_publisher: MqttClientInterface,
|
|
40
47
|
port: int = settings.API_PORT,
|
|
41
48
|
azure_ai_logging_enabled: bool = settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED,
|
|
42
49
|
) -> None:
|
|
@@ -47,22 +54,31 @@ class API:
|
|
|
47
54
|
self.host: str = "0.0.0.0" # Locking uvicorn to use 0.0.0.0
|
|
48
55
|
self.port: int = port
|
|
49
56
|
self.azure_ai_logging_enabled: bool = azure_ai_logging_enabled
|
|
57
|
+
self.mqtt_publisher: MqttClientInterface = mqtt_publisher
|
|
50
58
|
|
|
51
59
|
self.logger: Logger = logging.getLogger("api")
|
|
52
60
|
|
|
53
61
|
self.app: FastAPI = self._create_app()
|
|
62
|
+
self.server = self._setup_server()
|
|
54
63
|
|
|
55
64
|
def get_app(self) -> FastAPI:
|
|
56
65
|
return self.app
|
|
57
66
|
|
|
58
|
-
def
|
|
59
|
-
uvicorn.
|
|
67
|
+
def _setup_server(self) -> uvicorn.Server:
|
|
68
|
+
config = uvicorn.Config(
|
|
60
69
|
self.app,
|
|
61
70
|
port=self.port,
|
|
62
71
|
host=self.host,
|
|
63
72
|
reload=False,
|
|
64
73
|
log_config=None,
|
|
65
74
|
)
|
|
75
|
+
return uvicorn.Server(config)
|
|
76
|
+
|
|
77
|
+
def wait_for_api_server_ready(self) -> None:
|
|
78
|
+
while not self.server.started:
|
|
79
|
+
time.sleep(0.01)
|
|
80
|
+
self.logger.info("Uvicorn server has been started")
|
|
81
|
+
self._publish_startup_message()
|
|
66
82
|
|
|
67
83
|
def _create_app(self) -> FastAPI:
|
|
68
84
|
tags_metadata = [
|
|
@@ -73,7 +89,10 @@ class API:
|
|
|
73
89
|
]
|
|
74
90
|
app = FastAPI(
|
|
75
91
|
openapi_tags=tags_metadata,
|
|
76
|
-
on_startup=[
|
|
92
|
+
on_startup=[
|
|
93
|
+
self.authenticator.load_config,
|
|
94
|
+
self._log_startup_message,
|
|
95
|
+
],
|
|
77
96
|
swagger_ui_oauth2_redirect_url="/oauth2-redirect",
|
|
78
97
|
swagger_ui_init_oauth={
|
|
79
98
|
"usePkceWithAuthorizationCodeGrant": True,
|
|
@@ -349,3 +368,21 @@ class API:
|
|
|
349
368
|
)
|
|
350
369
|
|
|
351
370
|
return response
|
|
371
|
+
|
|
372
|
+
def _publish_startup_message(self) -> None:
|
|
373
|
+
if not self.mqtt_publisher:
|
|
374
|
+
return
|
|
375
|
+
|
|
376
|
+
payload: StartUpMessagePayload = StartUpMessagePayload(
|
|
377
|
+
isar_id=settings.ISAR_ID,
|
|
378
|
+
timestamp=datetime.now(timezone.utc),
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
self.logger.info("Publishing startup message to MQTT broker")
|
|
382
|
+
|
|
383
|
+
self.mqtt_publisher.publish(
|
|
384
|
+
topic=settings.TOPIC_ISAR_STARTUP,
|
|
385
|
+
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
386
|
+
qos=1,
|
|
387
|
+
retain=True,
|
|
388
|
+
)
|
isar/config/settings.py
CHANGED
|
@@ -211,6 +211,7 @@ class Settings(BaseSettings):
|
|
|
211
211
|
TOPIC_ISAR_ROBOT_HEARTBEAT: str = Field(
|
|
212
212
|
default="robot_heartbeat", validate_default=True
|
|
213
213
|
)
|
|
214
|
+
TOPIC_ISAR_STARTUP: str = Field(default="startup", validate_default=True)
|
|
214
215
|
|
|
215
216
|
# Logging
|
|
216
217
|
|
|
@@ -261,6 +262,7 @@ class Settings(BaseSettings):
|
|
|
261
262
|
"TOPIC_ISAR_ROBOT_HEARTBEAT",
|
|
262
263
|
"TOPIC_ISAR_INSPECTION_RESULT",
|
|
263
264
|
"TOPIC_ISAR_INSPECTION_VALUE",
|
|
265
|
+
"TOPIC_ISAR_STARTUP",
|
|
264
266
|
)
|
|
265
267
|
@classmethod
|
|
266
268
|
def prefix_isar_topics(cls, v: Any, info: ValidationInfo):
|
isar/modules.py
CHANGED
|
@@ -45,6 +45,16 @@ class ApplicationContainer(containers.DeclarativeContainer):
|
|
|
45
45
|
)
|
|
46
46
|
robot_utilities = providers.Singleton(RobotUtilities, robot=robot_interface)
|
|
47
47
|
|
|
48
|
+
# Mqtt client
|
|
49
|
+
mqtt_client = (
|
|
50
|
+
providers.Singleton(
|
|
51
|
+
MqttPublisher,
|
|
52
|
+
mqtt_queue=providers.Callable(events.provided.mqtt_queue),
|
|
53
|
+
)
|
|
54
|
+
if settings.MQTT_ENABLED
|
|
55
|
+
else None
|
|
56
|
+
)
|
|
57
|
+
|
|
48
58
|
# API and controllers
|
|
49
59
|
authenticator = providers.Singleton(Authenticator)
|
|
50
60
|
scheduling_utilities = providers.Singleton(
|
|
@@ -65,6 +75,7 @@ class ApplicationContainer(containers.DeclarativeContainer):
|
|
|
65
75
|
scheduling_controller=scheduling_controller,
|
|
66
76
|
robot_controller=robot_controller,
|
|
67
77
|
keyvault=keyvault,
|
|
78
|
+
mqtt_publisher=mqtt_client,
|
|
68
79
|
)
|
|
69
80
|
|
|
70
81
|
# Storage
|
|
@@ -77,16 +88,6 @@ class ApplicationContainer(containers.DeclarativeContainer):
|
|
|
77
88
|
storage_handlers_temp.append(blob_storage)
|
|
78
89
|
storage_handlers = providers.List(*storage_handlers_temp)
|
|
79
90
|
|
|
80
|
-
# Mqtt client
|
|
81
|
-
mqtt_client = (
|
|
82
|
-
providers.Singleton(
|
|
83
|
-
MqttPublisher,
|
|
84
|
-
mqtt_queue=providers.Callable(events.provided.mqtt_queue),
|
|
85
|
-
)
|
|
86
|
-
if settings.MQTT_ENABLED
|
|
87
|
-
else None
|
|
88
|
-
)
|
|
89
|
-
|
|
90
91
|
# State machine
|
|
91
92
|
task_selector = providers.Singleton(
|
|
92
93
|
SequentialTaskSelector
|
isar/script.py
CHANGED
|
@@ -160,13 +160,15 @@ def start() -> None:
|
|
|
160
160
|
threads.extend(publishers)
|
|
161
161
|
|
|
162
162
|
api: API = injector.api()
|
|
163
|
-
api_thread: Thread = Thread(target=api.
|
|
163
|
+
api_thread: Thread = Thread(target=api.server.run, name="ISAR API", daemon=True)
|
|
164
164
|
threads.append(api_thread)
|
|
165
165
|
|
|
166
166
|
for thread in threads:
|
|
167
167
|
thread.start()
|
|
168
168
|
logger.info("Started thread: %s", thread.name)
|
|
169
169
|
|
|
170
|
+
api.wait_for_api_server_ready()
|
|
171
|
+
|
|
170
172
|
while True:
|
|
171
173
|
for thread in threads:
|
|
172
174
|
if not thread.is_alive():
|
|
@@ -18,7 +18,7 @@ def put_start_mission_on_queue(state_machine: "StateMachine") -> bool:
|
|
|
18
18
|
|
|
19
19
|
def initiate_mission(state_machine: "StateMachine") -> bool:
|
|
20
20
|
state_machine.logger.info(
|
|
21
|
-
"
|
|
21
|
+
"Initiating mission:\n"
|
|
22
22
|
f" Mission ID: {state_machine.current_mission.id}\n"
|
|
23
23
|
f" Mission Name: {state_machine.current_mission.name}\n"
|
|
24
24
|
f" Number of Tasks: {len(state_machine.current_mission.tasks)}"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
isar/__init__.py,sha256=cH8p8bVveu3FUL6kBhldcSlLaoHgD82Kd0-SwSNfGXw,87
|
|
2
|
-
isar/modules.py,sha256=
|
|
3
|
-
isar/script.py,sha256=
|
|
2
|
+
isar/modules.py,sha256=QBB1pge1i17HVMLA5n-qd9K3APCrX9bFF2vlfjheOhU,4778
|
|
3
|
+
isar/script.py,sha256=0oUUfytKDOsWrPv4iWemTWl5L3Ug66mQsbvqGqQrVWk,6050
|
|
4
4
|
isar/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
isar/apis/api.py,sha256=
|
|
5
|
+
isar/apis/api.py,sha256=2hggLxcdsHqTYDAfVUMwMIBgpuB-0ba2HWMscHkRGzA,15072
|
|
6
6
|
isar/apis/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
isar/apis/models/models.py,sha256=HzLaWhjAv0uJRBWipIgYg_F75eaQ5jl9Pi4UnYbDJ-M,1749
|
|
8
8
|
isar/apis/models/start_mission_definition.py,sha256=S87i_vrgXTY1nTMTiXMJAnx_q5uVxuiRNcrQrAYWKeo,6152
|
|
@@ -15,7 +15,7 @@ isar/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
15
15
|
isar/config/configuration_error.py,sha256=rO6WOhafX6xvVib8WxV-eY483Z0PpN-9PxGsq5ATfKc,46
|
|
16
16
|
isar/config/log.py,sha256=SzEWbzXU1DpN7YONIRT8k0zBOGm_qVkXlJuuZtb8STc,2300
|
|
17
17
|
isar/config/logging.conf,sha256=mYO1xf27gAopEMHhGzY7-mwyfN16rwRLkPNMvy3zn2g,1127
|
|
18
|
-
isar/config/settings.py,sha256=
|
|
18
|
+
isar/config/settings.py,sha256=dn9fEKX7GpzD9Y7q0TjQxW9Xf0iY-pCl3NV7bkxH1E8,12487
|
|
19
19
|
isar/config/certs/ca-cert.pem,sha256=qoNljfad_qcMxhXJIUMLd7nT-Qwf_d4dYSdoOFEOE8I,2179
|
|
20
20
|
isar/config/keyvault/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
isar/config/keyvault/keyvault_error.py,sha256=zvPCsZLjboxsxthYkxpRERCTFxYV8R5WmACewAUQLwk,41
|
|
@@ -95,7 +95,7 @@ isar/state_machine/transitions/functions/pause.py,sha256=aoDkq2nV6wBY0YQX3KbjvBR
|
|
|
95
95
|
isar/state_machine/transitions/functions/resume.py,sha256=9KQjH_6YBGyxFhb7G5dgDe3WH0xHawhEIw6yTVEm9os,998
|
|
96
96
|
isar/state_machine/transitions/functions/return_home.py,sha256=UlniwYvpz74hxqgN0TyVv3LCmiMsqsosKEtEGLqkNj0,1139
|
|
97
97
|
isar/state_machine/transitions/functions/robot_status.py,sha256=xhKZ5u_X8uDvnhvGnAIABuKaPXeVqFjkgj4H2Om-j_A,1013
|
|
98
|
-
isar/state_machine/transitions/functions/start_mission.py,sha256=
|
|
98
|
+
isar/state_machine/transitions/functions/start_mission.py,sha256=ricRfhLH1_lNpqWxneMZcm7ps2YfY6sQGHkiT0Glf6M,2564
|
|
99
99
|
isar/state_machine/transitions/functions/stop.py,sha256=aIj3EPnpgNLdsJwOK1ehhI1TpenQa9JjBxZH0Nm6dLg,1649
|
|
100
100
|
isar/state_machine/transitions/functions/utils.py,sha256=Wa72Ocq4QT1E6qkpEJZQ3h5o33pGvx7Tlkt2JZ2Grbk,314
|
|
101
101
|
isar/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -104,7 +104,7 @@ isar/storage/local_storage.py,sha256=Bnmoi5gyN8r-oRh0aHrOdGqaH3JqRScFKMRXYojW5kY
|
|
|
104
104
|
isar/storage/storage_interface.py,sha256=DYDry4I7aZpDHJhsBF6s8zrgokFAc7fdKJKfA8AvL7o,828
|
|
105
105
|
isar/storage/uploader.py,sha256=HAC3ssuPQCQ1xH4aTQfHIaq-ZoEzKwONWmsAOpNXOzw,9523
|
|
106
106
|
isar/storage/utilities.py,sha256=oLH0Rp7UtrQQdilfITnmXO1Z0ExdeDhBImYHid55vBA,3449
|
|
107
|
-
isar-1.30.
|
|
107
|
+
isar-1.30.4.dist-info/licenses/LICENSE,sha256=3fc2-ebLwHWwzfQbulGNRdcNob3SBQeCfEVUDYxsuqw,14058
|
|
108
108
|
robot_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
109
109
|
robot_interface/robot_interface.py,sha256=Miout0IRX7QniUNu_upyNzkB8KDUWin7GGCqIeMh83E,8195
|
|
110
110
|
robot_interface/test_robot_interface.py,sha256=FV1urn7SbsMyWBIcTKjsBwAG4IsXeZ6pLHE0mA9EGGs,692
|
|
@@ -124,12 +124,12 @@ robot_interface/models/robots/media.py,sha256=8A-CuuubfngzPprs6zWB9hSaqe3jzgsE8r
|
|
|
124
124
|
robot_interface/models/robots/robot_model.py,sha256=-0jNKWPcEgtF_2klb1It3u0SCoAR0hSW9nce58Zq0Co,417
|
|
125
125
|
robot_interface/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
126
|
robot_interface/telemetry/mqtt_client.py,sha256=ueXdtIFNCwciTj4spvdJj9emd-IOmUuJjpsXQSSWZPY,2987
|
|
127
|
-
robot_interface/telemetry/payloads.py,sha256=
|
|
127
|
+
robot_interface/telemetry/payloads.py,sha256=PpvmV7XeGgfhc_aRUYFOdwBTwV2x8TwTBINJ-rKchVw,2804
|
|
128
128
|
robot_interface/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
129
129
|
robot_interface/utilities/json_service.py,sha256=qkzVkb60Gi_pto-b5n1vNzCrQze2yqgIJqSLNLYj1Fg,1034
|
|
130
130
|
robot_interface/utilities/uuid_string_factory.py,sha256=_NQIbBQ56w0qqO0MUDP6aPpHbxW7ATRhK8HnQiBSLkc,76
|
|
131
|
-
isar-1.30.
|
|
132
|
-
isar-1.30.
|
|
133
|
-
isar-1.30.
|
|
134
|
-
isar-1.30.
|
|
135
|
-
isar-1.30.
|
|
131
|
+
isar-1.30.4.dist-info/METADATA,sha256=SaISJES198lknEfIqlqwrZ1CZe4A0vzi_mKYuu1fZrU,31063
|
|
132
|
+
isar-1.30.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
133
|
+
isar-1.30.4.dist-info/entry_points.txt,sha256=TFam7uNNw7J0iiDYzsH2gfG0u1eV1wh3JTw_HkhgKLk,49
|
|
134
|
+
isar-1.30.4.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
|
|
135
|
+
isar-1.30.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|