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/models/events.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
from collections import deque
|
|
2
|
+
from queue import Empty, Queue
|
|
3
|
+
from typing import Generic, Optional, Tuple, TypeVar
|
|
4
|
+
|
|
5
|
+
from transitions import State
|
|
6
|
+
|
|
7
|
+
from isar.apis.models.models import (
|
|
8
|
+
ControlMissionResponse,
|
|
9
|
+
LockdownResponse,
|
|
10
|
+
MaintenanceResponse,
|
|
11
|
+
MissionStartResponse,
|
|
12
|
+
)
|
|
13
|
+
from isar.config.settings import settings
|
|
14
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
15
|
+
from robot_interface.models.mission.mission import Mission
|
|
16
|
+
from robot_interface.models.mission.status import MissionStatus, RobotStatus
|
|
17
|
+
from robot_interface.models.mission.task import TASKS
|
|
18
|
+
|
|
19
|
+
T = TypeVar("T")
|
|
20
|
+
T1 = TypeVar("T1")
|
|
21
|
+
T2 = TypeVar("T2")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Event(Queue[T]):
|
|
25
|
+
def __init__(self, name: str) -> None:
|
|
26
|
+
super().__init__(maxsize=1)
|
|
27
|
+
self.name = name
|
|
28
|
+
|
|
29
|
+
def trigger_event(self, data: T, timeout: int = None) -> None:
|
|
30
|
+
try:
|
|
31
|
+
# We always want a timeout when blocking for results, so that
|
|
32
|
+
# the thread will never get stuck waiting for a result
|
|
33
|
+
self.put(data, block=timeout is not None, timeout=timeout)
|
|
34
|
+
except Exception:
|
|
35
|
+
if timeout is not None:
|
|
36
|
+
raise EventTimeoutError
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
def consume_event(self, timeout: int = None) -> Optional[T]:
|
|
40
|
+
try:
|
|
41
|
+
return self.get(block=timeout is not None, timeout=timeout)
|
|
42
|
+
except Empty:
|
|
43
|
+
if timeout is not None:
|
|
44
|
+
raise EventTimeoutError
|
|
45
|
+
return None
|
|
46
|
+
except ValueError:
|
|
47
|
+
raise EventConflictError
|
|
48
|
+
|
|
49
|
+
def clear_event(self) -> None:
|
|
50
|
+
while True:
|
|
51
|
+
try:
|
|
52
|
+
self.get(block=False)
|
|
53
|
+
except Empty:
|
|
54
|
+
break
|
|
55
|
+
except ValueError:
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
def has_event(self) -> bool:
|
|
59
|
+
return (
|
|
60
|
+
self.qsize() != 0
|
|
61
|
+
) # Queue size is not reliable, but should be sufficient for this case
|
|
62
|
+
|
|
63
|
+
def check(self) -> Optional[T]:
|
|
64
|
+
if not self._qsize():
|
|
65
|
+
return None
|
|
66
|
+
with self.mutex:
|
|
67
|
+
queueList = list(self.queue)
|
|
68
|
+
return queueList.pop()
|
|
69
|
+
|
|
70
|
+
def update(self, item: T):
|
|
71
|
+
with self.mutex:
|
|
72
|
+
self.queue: deque[T] = deque()
|
|
73
|
+
self.queue.append(item)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Events:
|
|
77
|
+
def __init__(self) -> None:
|
|
78
|
+
self.api_requests: APIRequests = APIRequests()
|
|
79
|
+
self.state_machine_events: StateMachineEvents = StateMachineEvents()
|
|
80
|
+
self.robot_service_events: RobotServiceEvents = RobotServiceEvents()
|
|
81
|
+
|
|
82
|
+
self.upload_queue: Queue = Queue(maxsize=10)
|
|
83
|
+
|
|
84
|
+
if settings.MQTT_ENABLED:
|
|
85
|
+
self.mqtt_queue: Queue = Queue()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class APIEvent(Generic[T1, T2]):
|
|
89
|
+
"""
|
|
90
|
+
Creates request and response event. The events are defined such that the request is from
|
|
91
|
+
api to state machine while the response is from state machine to api.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
def __init__(self, name: str):
|
|
95
|
+
self.request: Event[T1] = Event("api-" + name + "-request")
|
|
96
|
+
self.response: Event[T2] = Event("api-" + name + "-request")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class APIRequests:
|
|
100
|
+
def __init__(self) -> None:
|
|
101
|
+
self.start_mission: APIEvent[Mission, MissionStartResponse] = APIEvent(
|
|
102
|
+
"start_mission"
|
|
103
|
+
)
|
|
104
|
+
self.stop_mission: APIEvent[str, ControlMissionResponse] = APIEvent(
|
|
105
|
+
"stop_mission"
|
|
106
|
+
)
|
|
107
|
+
self.pause_mission: APIEvent[bool, ControlMissionResponse] = APIEvent(
|
|
108
|
+
"pause_mission"
|
|
109
|
+
)
|
|
110
|
+
self.resume_mission: APIEvent[bool, ControlMissionResponse] = APIEvent(
|
|
111
|
+
"resume_mission"
|
|
112
|
+
)
|
|
113
|
+
self.return_home: APIEvent[bool, bool] = APIEvent("return_home")
|
|
114
|
+
self.release_intervention_needed: APIEvent[bool, bool] = APIEvent(
|
|
115
|
+
"release_intervention_needed"
|
|
116
|
+
)
|
|
117
|
+
self.send_to_lockdown: APIEvent[bool, LockdownResponse] = APIEvent(
|
|
118
|
+
"send_to_lockdown"
|
|
119
|
+
)
|
|
120
|
+
self.release_from_lockdown: APIEvent[bool, bool] = APIEvent(
|
|
121
|
+
"release_from_lockdown"
|
|
122
|
+
)
|
|
123
|
+
self.set_maintenance_mode: APIEvent[bool, MaintenanceResponse] = APIEvent(
|
|
124
|
+
"set_maintenance_mode"
|
|
125
|
+
)
|
|
126
|
+
self.release_from_maintenance_mode: APIEvent[bool, bool] = APIEvent(
|
|
127
|
+
"release_from_maintenance_mode"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class StateMachineEvents:
|
|
132
|
+
def __init__(self) -> None:
|
|
133
|
+
self.start_mission: Event[Mission] = Event("start_mission")
|
|
134
|
+
self.stop_mission: Event[bool] = Event("stop_mission")
|
|
135
|
+
self.pause_mission: Event[bool] = Event("pause_mission")
|
|
136
|
+
self.resume_mission: Event[bool] = Event("resume_mission")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class RobotServiceEvents:
|
|
140
|
+
def __init__(self) -> None:
|
|
141
|
+
self.mission_status_updated: Event[MissionStatus] = Event(
|
|
142
|
+
"mission_status_updated"
|
|
143
|
+
)
|
|
144
|
+
self.mission_started: Event[bool] = Event("mission_started")
|
|
145
|
+
self.mission_failed: Event[ErrorMessage] = Event("mission_failed")
|
|
146
|
+
self.robot_status_changed: Event[bool] = Event("robot_status_changed")
|
|
147
|
+
self.mission_failed_to_stop: Event[ErrorMessage] = Event(
|
|
148
|
+
"mission_failed_to_stop"
|
|
149
|
+
)
|
|
150
|
+
self.mission_successfully_stopped: Event[bool] = Event(
|
|
151
|
+
"mission_successfully_stopped"
|
|
152
|
+
)
|
|
153
|
+
self.mission_failed_to_pause: Event[ErrorMessage] = Event(
|
|
154
|
+
"mission_failed_to_pause"
|
|
155
|
+
)
|
|
156
|
+
self.mission_successfully_paused: Event[bool] = Event(
|
|
157
|
+
"mission_successfully_paused"
|
|
158
|
+
)
|
|
159
|
+
self.mission_failed_to_resume: Event[ErrorMessage] = Event(
|
|
160
|
+
"mission_failed_to_resume"
|
|
161
|
+
)
|
|
162
|
+
self.mission_successfully_resumed: Event[bool] = Event(
|
|
163
|
+
"mission_successfully_resumed"
|
|
164
|
+
)
|
|
165
|
+
self.request_inspection_upload: Event[Tuple[TASKS, Mission]] = Event(
|
|
166
|
+
"request_inspection_upload"
|
|
167
|
+
)
|
|
168
|
+
self.robot_already_home: Event[bool] = Event("robot_already_home")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class SharedState:
|
|
172
|
+
def __init__(self) -> None:
|
|
173
|
+
self.state: Event[State] = Event("state")
|
|
174
|
+
self.robot_status: Event[RobotStatus] = Event("robot_status")
|
|
175
|
+
self.robot_battery_level: Event[float] = Event("robot_battery_level")
|
|
176
|
+
self.mission_id: Event[Optional[str]] = Event("mission_id")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class EventTimeoutError(Exception):
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class EventConflictError(Exception):
|
|
184
|
+
pass
|
isar/models/status.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class IsarStatus(Enum):
|
|
5
|
+
Available = "available"
|
|
6
|
+
ReturnHomePaused = "returnhomepaused"
|
|
7
|
+
Paused = "paused"
|
|
8
|
+
Busy = "busy"
|
|
9
|
+
Home = "home"
|
|
10
|
+
Offline = "offline"
|
|
11
|
+
BlockedProtectiveStop = "blockedprotectivestop"
|
|
12
|
+
ReturningHome = "returninghome"
|
|
13
|
+
InterventionNeeded = "interventionneeded"
|
|
14
|
+
Recharging = "recharging"
|
|
15
|
+
Lockdown = "lockdown"
|
|
16
|
+
GoingToLockdown = "goingtolockdown"
|
|
17
|
+
GoingToRecharging = "goingtorecharging"
|
|
18
|
+
Maintenance = "maintenance"
|
isar/modules.py
CHANGED
|
@@ -1,220 +1,133 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
2
|
from importlib import import_module
|
|
3
|
-
from logging import Logger
|
|
4
|
-
from types import ModuleType
|
|
5
|
-
from typing import Dict, List, Tuple, Union
|
|
6
3
|
|
|
7
|
-
from
|
|
4
|
+
from dependency_injector import containers, providers
|
|
8
5
|
|
|
9
6
|
from isar.apis.api import API
|
|
7
|
+
from isar.apis.robot_control.robot_controller import RobotController
|
|
10
8
|
from isar.apis.schedule.scheduling_controller import SchedulingController
|
|
11
9
|
from isar.apis.security.authentication import Authenticator
|
|
12
10
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
13
11
|
from isar.config.settings import settings
|
|
14
12
|
from isar.mission_planner.local_planner import LocalPlanner
|
|
15
|
-
from isar.
|
|
16
|
-
from isar.
|
|
17
|
-
from isar.
|
|
18
|
-
from isar.models.communication.queues.queues import Queues
|
|
19
|
-
from isar.services.service_connections.request_handler import RequestHandler
|
|
20
|
-
from isar.services.service_connections.stid.stid_service import StidService
|
|
13
|
+
from isar.models.events import Events, SharedState
|
|
14
|
+
from isar.robot.robot import Robot
|
|
15
|
+
from isar.services.utilities.robot_utilities import RobotUtilities
|
|
21
16
|
from isar.services.utilities.scheduling_utilities import SchedulingUtilities
|
|
22
17
|
from isar.state_machine.state_machine import StateMachine
|
|
23
18
|
from isar.storage.blob_storage import BlobStorage
|
|
24
19
|
from isar.storage.local_storage import LocalStorage
|
|
25
|
-
from isar.storage.slimm_storage import SlimmStorage
|
|
26
|
-
from isar.storage.storage_interface import StorageInterface
|
|
27
20
|
from isar.storage.uploader import Uploader
|
|
28
|
-
from robot_interface.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class RobotModule(Module):
|
|
60
|
-
@provider
|
|
61
|
-
@singleton
|
|
62
|
-
def provide_robot_interface(self) -> RobotInterface:
|
|
63
|
-
robot_package_name: str = settings.ROBOT_PACKAGE
|
|
64
|
-
robot: ModuleType = import_module(robot_package_name)
|
|
65
|
-
return robot.robotinterface.Robot() # type: ignore
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class QueuesModule(Module):
|
|
69
|
-
@provider
|
|
70
|
-
@singleton
|
|
71
|
-
def provide_queues(self) -> Queues:
|
|
72
|
-
return Queues()
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class RequestHandlerModule(Module):
|
|
76
|
-
@provider
|
|
77
|
-
@singleton
|
|
78
|
-
def provide_request_handler(self) -> RequestHandler:
|
|
79
|
-
return RequestHandler()
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class BlobStorageModule(Module):
|
|
83
|
-
@multiprovider
|
|
84
|
-
@singleton
|
|
85
|
-
def provide_blob_storage(self, keyvault: Keyvault) -> List[StorageInterface]:
|
|
86
|
-
return [BlobStorage(keyvault)]
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
class LocalStorageModule(Module):
|
|
90
|
-
@multiprovider
|
|
91
|
-
@singleton
|
|
92
|
-
def provide_local_storage(self) -> List[StorageInterface]:
|
|
93
|
-
return [LocalStorage()]
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class SlimmStorageModule(Module):
|
|
97
|
-
@multiprovider
|
|
98
|
-
@singleton
|
|
99
|
-
def provide_slimm_storage(
|
|
100
|
-
self, request_handler: RequestHandler
|
|
101
|
-
) -> List[StorageInterface]:
|
|
102
|
-
return [SlimmStorage(request_handler=request_handler)]
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
class LocalPlannerModule(Module):
|
|
106
|
-
@provider
|
|
107
|
-
@singleton
|
|
108
|
-
def provide_local_planner(self) -> MissionPlannerInterface:
|
|
109
|
-
return LocalPlanner()
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class StateMachineModule(Module):
|
|
113
|
-
@provider
|
|
114
|
-
@singleton
|
|
115
|
-
def provide_state_machine(
|
|
116
|
-
self,
|
|
117
|
-
queues: Queues,
|
|
118
|
-
robot: RobotInterface,
|
|
119
|
-
mqtt_client: MqttClientInterface,
|
|
120
|
-
task_selector: TaskSelectorInterface,
|
|
121
|
-
) -> StateMachine:
|
|
122
|
-
return StateMachine(
|
|
123
|
-
queues=queues,
|
|
124
|
-
robot=robot,
|
|
125
|
-
mqtt_publisher=mqtt_client,
|
|
126
|
-
task_selector=task_selector,
|
|
21
|
+
from robot_interface.telemetry.mqtt_client import MqttPublisher
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ApplicationContainer(containers.DeclarativeContainer):
|
|
25
|
+
config = providers.Configuration(pydantic_settings=[settings])
|
|
26
|
+
|
|
27
|
+
# Core services
|
|
28
|
+
keyvault = providers.Singleton(
|
|
29
|
+
Keyvault,
|
|
30
|
+
keyvault_name=settings.KEYVAULT_NAME,
|
|
31
|
+
client_id=settings.AZURE_CLIENT_ID,
|
|
32
|
+
client_secret=os.environ.get("AZURE_CLIENT_SECRET"),
|
|
33
|
+
tenant_id=settings.AZURE_TENANT_ID,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Events and shared state
|
|
37
|
+
events = providers.Singleton(Events)
|
|
38
|
+
shared_state = providers.Singleton(SharedState)
|
|
39
|
+
|
|
40
|
+
# Robot-related services
|
|
41
|
+
robot_interface = providers.Singleton(
|
|
42
|
+
lambda: import_module(f"{settings.ROBOT_PACKAGE}.robotinterface").Robot()
|
|
43
|
+
)
|
|
44
|
+
robot_utilities = providers.Singleton(RobotUtilities, robot=robot_interface)
|
|
45
|
+
|
|
46
|
+
# Mqtt client
|
|
47
|
+
mqtt_client = (
|
|
48
|
+
providers.Singleton(
|
|
49
|
+
MqttPublisher,
|
|
50
|
+
mqtt_queue=providers.Callable(events.provided.mqtt_queue),
|
|
127
51
|
)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
for category, (module, config_option) in modules.items():
|
|
211
|
-
if config_option:
|
|
212
|
-
injector_modules.append(module)
|
|
213
|
-
module_overview += (
|
|
214
|
-
f"\n {category:<15} : {config_option:<20} ({module.__name__})"
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
logger: Logger = logging.getLogger("modules")
|
|
218
|
-
logger.info(f"Loaded the following module configurations:{module_overview}")
|
|
219
|
-
|
|
220
|
-
return Injector(injector_modules)
|
|
52
|
+
if settings.MQTT_ENABLED
|
|
53
|
+
else None
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# API and controllers
|
|
57
|
+
authenticator = providers.Singleton(Authenticator)
|
|
58
|
+
scheduling_utilities = providers.Singleton(
|
|
59
|
+
SchedulingUtilities,
|
|
60
|
+
events=events,
|
|
61
|
+
shared_state=shared_state,
|
|
62
|
+
mission_planner=providers.Singleton(LocalPlanner),
|
|
63
|
+
)
|
|
64
|
+
scheduling_controller = providers.Singleton(
|
|
65
|
+
SchedulingController, scheduling_utilities=scheduling_utilities
|
|
66
|
+
)
|
|
67
|
+
robot_controller = providers.Singleton(
|
|
68
|
+
RobotController, robot_utilities=robot_utilities
|
|
69
|
+
)
|
|
70
|
+
api = providers.Singleton(
|
|
71
|
+
API,
|
|
72
|
+
authenticator=authenticator,
|
|
73
|
+
scheduling_controller=scheduling_controller,
|
|
74
|
+
robot_controller=robot_controller,
|
|
75
|
+
keyvault=keyvault,
|
|
76
|
+
mqtt_publisher=mqtt_client,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Storage
|
|
80
|
+
storage_handlers_temp = []
|
|
81
|
+
if settings.STORAGE_LOCAL_ENABLED:
|
|
82
|
+
local_storage = providers.Singleton(LocalStorage)
|
|
83
|
+
storage_handlers_temp.append(local_storage)
|
|
84
|
+
if settings.STORAGE_BLOB_ENABLED:
|
|
85
|
+
blob_storage = providers.Singleton(BlobStorage, keyvault=keyvault)
|
|
86
|
+
storage_handlers_temp.append(blob_storage)
|
|
87
|
+
storage_handlers = providers.List(*storage_handlers_temp)
|
|
88
|
+
|
|
89
|
+
# State machine
|
|
90
|
+
state_machine = providers.Singleton(
|
|
91
|
+
StateMachine,
|
|
92
|
+
events=events,
|
|
93
|
+
shared_state=shared_state,
|
|
94
|
+
robot=robot_interface,
|
|
95
|
+
mqtt_publisher=mqtt_client,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Robot
|
|
99
|
+
robot = providers.Singleton(
|
|
100
|
+
Robot,
|
|
101
|
+
events=events,
|
|
102
|
+
robot=robot_interface,
|
|
103
|
+
shared_state=shared_state,
|
|
104
|
+
mqtt_publisher=mqtt_client,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Uploader
|
|
108
|
+
uploader = providers.Singleton(
|
|
109
|
+
Uploader,
|
|
110
|
+
events=events,
|
|
111
|
+
storage_handlers=storage_handlers,
|
|
112
|
+
mqtt_publisher=mqtt_client,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def get_injector() -> ApplicationContainer:
|
|
117
|
+
container = ApplicationContainer()
|
|
118
|
+
container.init_resources()
|
|
119
|
+
container.wire(modules=[__name__])
|
|
120
|
+
container.config.from_dict(
|
|
121
|
+
{
|
|
122
|
+
"KEYVAULT_NAME": settings.KEYVAULT_NAME,
|
|
123
|
+
"MQTT_ENABLED": settings.MQTT_ENABLED,
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
print("Loaded the following module configurations:")
|
|
128
|
+
for provider_name, provider in container.providers.items():
|
|
129
|
+
provider_repr = repr(provider)
|
|
130
|
+
simplified_provider = provider_repr.split(".")[-1].split(">")[0]
|
|
131
|
+
print(f" {provider_name:<20}: {simplified_provider}")
|
|
132
|
+
|
|
133
|
+
return container
|