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.
Files changed (129) hide show
  1. isar/__init__.py +2 -5
  2. isar/apis/api.py +159 -66
  3. isar/apis/models/__init__.py +0 -1
  4. isar/apis/models/models.py +22 -12
  5. isar/apis/models/start_mission_definition.py +128 -123
  6. isar/apis/robot_control/robot_controller.py +41 -0
  7. isar/apis/schedule/scheduling_controller.py +135 -121
  8. isar/apis/security/authentication.py +5 -5
  9. isar/config/certs/ca-cert.pem +32 -32
  10. isar/config/keyvault/keyvault_service.py +1 -2
  11. isar/config/log.py +47 -39
  12. isar/config/logging.conf +16 -31
  13. isar/config/open_telemetry.py +102 -0
  14. isar/config/predefined_mission_definition/default_exr.json +49 -0
  15. isar/config/predefined_mission_definition/default_mission.json +1 -5
  16. isar/config/predefined_mission_definition/default_turtlebot.json +4 -11
  17. isar/config/predefined_missions/default.json +67 -87
  18. isar/config/predefined_missions/default_extra_capabilities.json +107 -0
  19. isar/config/settings.py +119 -142
  20. isar/eventhandlers/eventhandler.py +123 -0
  21. isar/mission_planner/local_planner.py +6 -20
  22. isar/mission_planner/mission_planner_interface.py +1 -1
  23. isar/models/events.py +184 -0
  24. isar/models/status.py +18 -0
  25. isar/modules.py +118 -205
  26. isar/robot/robot.py +377 -0
  27. isar/robot/robot_battery.py +60 -0
  28. isar/robot/robot_monitor_mission.py +357 -0
  29. isar/robot/robot_pause_mission.py +74 -0
  30. isar/robot/robot_resume_mission.py +67 -0
  31. isar/robot/robot_start_mission.py +66 -0
  32. isar/robot/robot_status.py +61 -0
  33. isar/robot/robot_stop_mission.py +68 -0
  34. isar/robot/robot_upload_inspection.py +75 -0
  35. isar/script.py +171 -0
  36. isar/services/service_connections/mqtt/mqtt_client.py +47 -11
  37. isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +32 -0
  38. isar/services/service_connections/mqtt/robot_info_publisher.py +4 -3
  39. isar/services/service_connections/persistent_memory.py +69 -0
  40. isar/services/utilities/mqtt_utilities.py +93 -0
  41. isar/services/utilities/robot_utilities.py +20 -0
  42. isar/services/utilities/scheduling_utilities.py +393 -65
  43. isar/state_machine/state_machine.py +227 -486
  44. isar/state_machine/states/__init__.py +0 -7
  45. isar/state_machine/states/await_next_mission.py +114 -0
  46. isar/state_machine/states/blocked_protective_stop.py +60 -0
  47. isar/state_machine/states/going_to_lockdown.py +95 -0
  48. isar/state_machine/states/going_to_recharging.py +92 -0
  49. isar/state_machine/states/home.py +115 -0
  50. isar/state_machine/states/intervention_needed.py +77 -0
  51. isar/state_machine/states/lockdown.py +38 -0
  52. isar/state_machine/states/maintenance.py +36 -0
  53. isar/state_machine/states/monitor.py +137 -166
  54. isar/state_machine/states/offline.py +60 -0
  55. isar/state_machine/states/paused.py +92 -23
  56. isar/state_machine/states/pausing.py +48 -0
  57. isar/state_machine/states/pausing_return_home.py +48 -0
  58. isar/state_machine/states/recharging.py +80 -0
  59. isar/state_machine/states/resuming.py +57 -0
  60. isar/state_machine/states/resuming_return_home.py +64 -0
  61. isar/state_machine/states/return_home_paused.py +109 -0
  62. isar/state_machine/states/returning_home.py +217 -0
  63. isar/state_machine/states/stopping.py +61 -0
  64. isar/state_machine/states/stopping_due_to_maintenance.py +61 -0
  65. isar/state_machine/states/stopping_go_to_lockdown.py +60 -0
  66. isar/state_machine/states/stopping_go_to_recharge.py +51 -0
  67. isar/state_machine/states/stopping_return_home.py +77 -0
  68. isar/state_machine/states/unknown_status.py +72 -0
  69. isar/state_machine/states_enum.py +22 -5
  70. isar/state_machine/transitions/mission.py +192 -0
  71. isar/state_machine/transitions/return_home.py +106 -0
  72. isar/state_machine/transitions/robot_status.py +80 -0
  73. isar/state_machine/utils/common_event_handlers.py +73 -0
  74. isar/storage/blob_storage.py +71 -45
  75. isar/storage/local_storage.py +28 -14
  76. isar/storage/storage_interface.py +28 -6
  77. isar/storage/uploader.py +184 -55
  78. isar/storage/utilities.py +35 -27
  79. isar-1.34.9.dist-info/METADATA +496 -0
  80. isar-1.34.9.dist-info/RECORD +135 -0
  81. {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/WHEEL +1 -1
  82. isar-1.34.9.dist-info/entry_points.txt +3 -0
  83. robot_interface/models/exceptions/__init__.py +0 -7
  84. robot_interface/models/exceptions/robot_exceptions.py +274 -4
  85. robot_interface/models/initialize/__init__.py +0 -1
  86. robot_interface/models/inspection/__init__.py +0 -13
  87. robot_interface/models/inspection/inspection.py +43 -34
  88. robot_interface/models/mission/mission.py +18 -14
  89. robot_interface/models/mission/status.py +20 -25
  90. robot_interface/models/mission/task.py +156 -92
  91. robot_interface/models/robots/battery_state.py +6 -0
  92. robot_interface/models/robots/media.py +13 -0
  93. robot_interface/models/robots/robot_model.py +7 -7
  94. robot_interface/robot_interface.py +135 -66
  95. robot_interface/telemetry/mqtt_client.py +84 -12
  96. robot_interface/telemetry/payloads.py +111 -12
  97. robot_interface/utilities/json_service.py +7 -1
  98. isar/config/predefined_missions/default_turtlebot.json +0 -110
  99. isar/config/predefined_poses/__init__.py +0 -0
  100. isar/config/predefined_poses/predefined_poses.py +0 -616
  101. isar/config/settings.env +0 -26
  102. isar/mission_planner/sequential_task_selector.py +0 -23
  103. isar/mission_planner/task_selector_interface.py +0 -31
  104. isar/models/communication/__init__.py +0 -0
  105. isar/models/communication/message.py +0 -12
  106. isar/models/communication/queues/__init__.py +0 -4
  107. isar/models/communication/queues/queue_io.py +0 -12
  108. isar/models/communication/queues/queue_timeout_error.py +0 -2
  109. isar/models/communication/queues/queues.py +0 -19
  110. isar/models/communication/queues/status_queue.py +0 -20
  111. isar/models/mission_metadata/__init__.py +0 -0
  112. isar/services/readers/__init__.py +0 -0
  113. isar/services/readers/base_reader.py +0 -37
  114. isar/services/service_connections/mqtt/robot_status_publisher.py +0 -93
  115. isar/services/service_connections/stid/__init__.py +0 -0
  116. isar/services/service_connections/stid/stid_service.py +0 -45
  117. isar/services/utilities/queue_utilities.py +0 -39
  118. isar/state_machine/states/idle.py +0 -40
  119. isar/state_machine/states/initialize.py +0 -60
  120. isar/state_machine/states/initiate.py +0 -129
  121. isar/state_machine/states/off.py +0 -18
  122. isar/state_machine/states/stop.py +0 -78
  123. isar/storage/slimm_storage.py +0 -181
  124. isar-1.15.0.dist-info/METADATA +0 -417
  125. isar-1.15.0.dist-info/RECORD +0 -113
  126. robot_interface/models/initialize/initialize_params.py +0 -9
  127. robot_interface/models/mission/step.py +0 -211
  128. {isar-1.15.0.dist-info → isar-1.34.9.dist-info/licenses}/LICENSE +0 -0
  129. {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 logging
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 injector import Injector, Module, multiprovider, provider, singleton
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.mission_planner.mission_planner_interface import MissionPlannerInterface
16
- from isar.mission_planner.sequential_task_selector import SequentialTaskSelector
17
- from isar.mission_planner.task_selector_interface import TaskSelectorInterface
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.robot_interface import RobotInterface
29
- from robot_interface.telemetry.mqtt_client import MqttClientInterface, MqttPublisher
30
-
31
-
32
- class APIModule(Module):
33
- @provider
34
- @singleton
35
- def provide_api(
36
- self,
37
- authenticator: Authenticator,
38
- scheduling_controller: SchedulingController,
39
- keyvault: Keyvault,
40
- ) -> API:
41
- return API(authenticator, scheduling_controller, keyvault)
42
-
43
- @provider
44
- @singleton
45
- def provide_scheduling_controller(
46
- self,
47
- scheduling_utilities: SchedulingUtilities,
48
- ) -> SchedulingController:
49
- return SchedulingController(scheduling_utilities)
50
-
51
-
52
- class AuthenticationModule(Module):
53
- @provider
54
- @singleton
55
- def provide_authenticator(self) -> Authenticator:
56
- return Authenticator()
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
- class UploaderModule(Module):
131
- @provider
132
- @singleton
133
- def provide_uploader(
134
- self,
135
- queues: Queues,
136
- storage_handlers: List[StorageInterface],
137
- mqtt_client: MqttClientInterface,
138
- ) -> Uploader:
139
- return Uploader(
140
- queues=queues,
141
- storage_handlers=storage_handlers,
142
- mqtt_publisher=mqtt_client,
143
- )
144
-
145
-
146
- class UtilitiesModule(Module):
147
- @provider
148
- @singleton
149
- def provide_scheduling_utilities(
150
- self, queues: Queues, mission_planner: MissionPlannerInterface
151
- ) -> SchedulingUtilities:
152
- return SchedulingUtilities(queues, mission_planner)
153
-
154
-
155
- class ServiceModule(Module):
156
- @provider
157
- @singleton
158
- def provide_keyvault(self) -> Keyvault:
159
- return Keyvault(keyvault_name=settings.KEYVAULT_NAME)
160
-
161
- @provider
162
- @singleton
163
- def provide_stid_service(self, request_handler: RequestHandler) -> StidService:
164
- return StidService(request_handler=request_handler)
165
-
166
-
167
- class MqttModule(Module):
168
- @provider
169
- @singleton
170
- def provide_mqtt_client(self, queues: Queues) -> MqttClientInterface:
171
- if settings.MQTT_ENABLED:
172
- return MqttPublisher(mqtt_queue=queues.mqtt_queue)
173
- return None
174
-
175
-
176
- class SequentialTaskSelectorModule(Module):
177
- @provider
178
- @singleton
179
- def provide_task_selector(self) -> TaskSelectorInterface:
180
- return SequentialTaskSelector()
181
-
182
-
183
- modules: Dict[str, Tuple[Module, Union[str, bool]]] = {
184
- "api": (APIModule, "required"),
185
- "authentication": (AuthenticationModule, "required"),
186
- "queues": (QueuesModule, "required"),
187
- "request_handler": (RequestHandlerModule, "required"),
188
- "robot_package": (RobotModule, settings.ROBOT_PACKAGE),
189
- "isar_id": (RobotModule, settings.ISAR_ID),
190
- "robot_name": (RobotModule, settings.ROBOT_NAME),
191
- "mission_planner": (LocalPlannerModule, settings.MISSION_PLANNER),
192
- "task_selector": (
193
- {"sequential": SequentialTaskSelectorModule}[settings.TASK_SELECTOR],
194
- settings.TASK_SELECTOR,
195
- ),
196
- "service": (ServiceModule, "required"),
197
- "state_machine": (StateMachineModule, "required"),
198
- "storage_local": (LocalStorageModule, settings.STORAGE_LOCAL_ENABLED),
199
- "storage_blob": (BlobStorageModule, settings.STORAGE_BLOB_ENABLED),
200
- "storage_slimm": (SlimmStorageModule, settings.STORAGE_SLIMM_ENABLED),
201
- "mqtt": (MqttModule, "required"),
202
- "utilities": (UtilitiesModule, "required"),
203
- }
204
-
205
-
206
- def get_injector() -> Injector:
207
- injector_modules: List[Module] = []
208
- module_overview: str = ""
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