horiba-sdk 0.3.2__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 (48) hide show
  1. horiba_sdk/__init__.py +19 -0
  2. horiba_sdk/communication/__init__.py +44 -0
  3. horiba_sdk/communication/abstract_communicator.py +59 -0
  4. horiba_sdk/communication/communication_exception.py +19 -0
  5. horiba_sdk/communication/messages.py +87 -0
  6. horiba_sdk/communication/websocket_communicator.py +213 -0
  7. horiba_sdk/core/resolution.py +45 -0
  8. horiba_sdk/devices/__init__.py +11 -0
  9. horiba_sdk/devices/abstract_device_discovery.py +7 -0
  10. horiba_sdk/devices/abstract_device_manager.py +68 -0
  11. horiba_sdk/devices/ccd_discovery.py +57 -0
  12. horiba_sdk/devices/device_manager.py +250 -0
  13. horiba_sdk/devices/fake_device_manager.py +133 -0
  14. horiba_sdk/devices/fake_icl_server.py +56 -0
  15. horiba_sdk/devices/fake_responses/ccd.json +168 -0
  16. horiba_sdk/devices/fake_responses/icl.json +29 -0
  17. horiba_sdk/devices/fake_responses/monochromator.json +187 -0
  18. horiba_sdk/devices/monochromator_discovery.py +48 -0
  19. horiba_sdk/devices/single_devices/__init__.py +5 -0
  20. horiba_sdk/devices/single_devices/abstract_device.py +79 -0
  21. horiba_sdk/devices/single_devices/ccd.py +443 -0
  22. horiba_sdk/devices/single_devices/monochromator.py +395 -0
  23. horiba_sdk/icl_error/__init__.py +34 -0
  24. horiba_sdk/icl_error/abstract_error.py +65 -0
  25. horiba_sdk/icl_error/abstract_error_db.py +25 -0
  26. horiba_sdk/icl_error/error_list.json +265 -0
  27. horiba_sdk/icl_error/icl_error.py +30 -0
  28. horiba_sdk/icl_error/icl_error_db.py +81 -0
  29. horiba_sdk/sync/__init__.py +0 -0
  30. horiba_sdk/sync/communication/__init__.py +7 -0
  31. horiba_sdk/sync/communication/abstract_communicator.py +48 -0
  32. horiba_sdk/sync/communication/test_client.py +16 -0
  33. horiba_sdk/sync/communication/websocket_communicator.py +212 -0
  34. horiba_sdk/sync/devices/__init__.py +15 -0
  35. horiba_sdk/sync/devices/abstract_device_discovery.py +17 -0
  36. horiba_sdk/sync/devices/abstract_device_manager.py +68 -0
  37. horiba_sdk/sync/devices/device_discovery.py +82 -0
  38. horiba_sdk/sync/devices/device_manager.py +209 -0
  39. horiba_sdk/sync/devices/fake_device_manager.py +91 -0
  40. horiba_sdk/sync/devices/fake_icl_server.py +79 -0
  41. horiba_sdk/sync/devices/single_devices/__init__.py +5 -0
  42. horiba_sdk/sync/devices/single_devices/abstract_device.py +83 -0
  43. horiba_sdk/sync/devices/single_devices/ccd.py +219 -0
  44. horiba_sdk/sync/devices/single_devices/monochromator.py +150 -0
  45. horiba_sdk-0.3.2.dist-info/LICENSE +20 -0
  46. horiba_sdk-0.3.2.dist-info/METADATA +438 -0
  47. horiba_sdk-0.3.2.dist-info/RECORD +48 -0
  48. horiba_sdk-0.3.2.dist-info/WHEEL +4 -0
@@ -0,0 +1,187 @@
1
+ {
2
+ "mono_discover": {
3
+ "id": 1234,
4
+ "command": "mono_discover",
5
+ "results": {
6
+ "count": 1
7
+
8
+ },
9
+ "errors": []
10
+ },
11
+ "mono_list": {
12
+ "id": 1234,
13
+ "command": "mono_list",
14
+ "results": {
15
+ "list": [
16
+ "0;iHR550;sn12345",
17
+ "1;iHR320;snabscde"
18
+ ]
19
+ },
20
+ "errors": []
21
+ },
22
+ "mono_listCount": {
23
+ "id": 1234,
24
+ "command": "mono_listCount",
25
+ "results": {
26
+ "count": 2
27
+ },
28
+ "errors": []
29
+ },
30
+ "mono_open": {
31
+ "id": 1234,
32
+ "command": "mono_open",
33
+ "errors": []
34
+ },
35
+ "mono_close": {
36
+ "id": 1234,
37
+ "command": "mono_close",
38
+ "errors": []
39
+ },
40
+ "mono_isOpen": {
41
+ "id": 1234,
42
+ "command": "mono_isOpen",
43
+ "results":{
44
+ "open": true
45
+ },
46
+ "errors": []
47
+ },
48
+ "mono_isBusy": {
49
+ "id": 1234,
50
+ "command": "mono_isBusy",
51
+ "results":{
52
+ "busy": false
53
+ },
54
+ "errors": []
55
+ },
56
+ "mono_init": {
57
+ "id": 1234,
58
+ "command": "mono_init",
59
+ "errors": []
60
+ },
61
+ "mono_getConfig": {
62
+ "id": 1234,
63
+ "command": "mono_getConfig",
64
+ "results":{
65
+ },
66
+ "errors": []
67
+
68
+ },
69
+ "mono_setConfig": {},
70
+ "mono_getPosition": {
71
+ "id": 1234,
72
+ "command": "mono_getPosition",
73
+ "results":{
74
+ "wavelength": 320.0
75
+ },
76
+ "errors": []
77
+ },
78
+ "mono_setPosition": {
79
+ "id": 1234,
80
+ "command": "mono_setPosition",
81
+ "errors": []
82
+ },
83
+ "mono_moveToPosition": {
84
+ "id": 1234,
85
+ "command": "mono_moveToPosition",
86
+ "errors": []
87
+ },
88
+ "mono_getGratingPosition": {
89
+ "id": 1234,
90
+ "command": "mono_getPosition",
91
+ "results":{
92
+ "position": 1
93
+ },
94
+ "errors": []
95
+ },
96
+ "mono_moveGrating": {
97
+ "id": 1234,
98
+ "command": "mono_getPosition",
99
+ "results":{
100
+ "position": 1
101
+ },
102
+ "errors": []
103
+ },
104
+ "mono_getFilterWheelPosition": {
105
+ "id": 1234,
106
+ "command": "mono_getFilterWheelPosition",
107
+ "results":{
108
+ "position": 0
109
+ },
110
+ "errors": []
111
+ },
112
+ "mono_moveFilterWheel": {
113
+ "id": 1234,
114
+ "command": "mono_moveFilterWheel",
115
+ "results":{
116
+ },
117
+ "errors": []
118
+ },
119
+ "mono_getMirrorPosition": {
120
+ "id": 1234,
121
+ "command": "mono_getMirrorPosition",
122
+ "results": {
123
+ "position": 0
124
+ },
125
+ "errors": []
126
+ },
127
+ "mono_moveMirror": {
128
+ "id": 1234,
129
+ "command": "mono_moveMirror",
130
+ "results": {},
131
+ "errors": []
132
+ },
133
+ "mono_getSlitPositionInMM": {
134
+ "id": 1234,
135
+ "command": "mono_getSlitPositionInMM",
136
+ "results": {
137
+ "position": 0
138
+ },
139
+ "errors": []
140
+ },
141
+ "mono_moveSlitMM": {
142
+ "id": 1234,
143
+ "command": "mono_moveSlitMM",
144
+ "results": {},
145
+ "errors": []
146
+ },
147
+ "mono_shutterOpen": {
148
+ "id": 1234,
149
+ "command": "mono_shutterOpen",
150
+ "results": {},
151
+ "errors": []
152
+ },
153
+ "mono_shutterClose": {
154
+ "id": 1234,
155
+ "command": "mono_shutterClose",
156
+ "results": {},
157
+ "errors": []
158
+ },
159
+ "mono_getShutterStatus": {
160
+ "id": 1234,
161
+ "command": "mono_getShutterStatus",
162
+ "results": {
163
+ "position": 0
164
+ },
165
+ "errors": []
166
+ },
167
+ "mono_getSlitStepPosition": {
168
+ "command": "mono_getSlitStepPosition",
169
+ "id": 1234,
170
+ "results": {
171
+ "position":0
172
+ },
173
+ "errors":[]
174
+ },
175
+ "mono_moveSlit": {
176
+ "id": 1234,
177
+ "command": "mono_moveSlit",
178
+ "results": {},
179
+ "errors": []
180
+ },
181
+ "mono_enableLaser": {},
182
+ "mono_getLaserStatus": {},
183
+ "mono_setLaserPower": {},
184
+ "mono_getLaserPower": {},
185
+ "mono_getLidStatus": {},
186
+ "mono_getSwitchStatus": {}
187
+ }
@@ -0,0 +1,48 @@
1
+ from typing import Any, final
2
+
3
+ from loguru import logger
4
+ from overrides import override
5
+
6
+ from horiba_sdk.communication import AbstractCommunicator, Command, Response
7
+ from horiba_sdk.devices.abstract_device_discovery import AbstractDeviceDiscovery
8
+ from horiba_sdk.devices.single_devices import Monochromator
9
+ from horiba_sdk.icl_error import AbstractErrorDB
10
+
11
+
12
+ @final
13
+ class MonochromatorsDiscovery(AbstractDeviceDiscovery):
14
+ def __init__(self, communicator: AbstractCommunicator, error_db: AbstractErrorDB):
15
+ self._communicator: AbstractCommunicator = communicator
16
+ self._monochromators: list[Monochromator] = []
17
+ self._error_db: AbstractErrorDB = error_db
18
+
19
+ @override
20
+ async def execute(self, error_on_no_device: bool = False) -> None:
21
+ """
22
+ Discovers the connected Monochromators and saves them internally.
23
+ """
24
+ if not self._communicator.opened():
25
+ await self._communicator.open()
26
+
27
+ response: Response = await self._communicator.request_with_response(Command('mono_discover', {}))
28
+ if response.results.get('count', 0) == 0 and error_on_no_device:
29
+ raise Exception('No Monochromators connected')
30
+
31
+ response = await self._communicator.request_with_response(Command('mono_list', {}))
32
+ raw_device_list = response.results['list']
33
+ self._monochromators = self._parse_monos(raw_device_list)
34
+ logger.info(f'Found {len(self._monochromators)} Monochromator devices: {self._monochromators}')
35
+
36
+ def _parse_monos(self, raw_device_list: dict[str, Any]) -> list[Monochromator]:
37
+ detected_monos = []
38
+ for device_string in raw_device_list:
39
+ mono_index: int = int(device_string.split(';')[0])
40
+ mono_type: str = device_string.split(';')[1]
41
+
42
+ logger.info(f'Detected Monochromator: {mono_type}')
43
+ detected_monos.append(Monochromator(mono_index, self._communicator, self._error_db))
44
+
45
+ return detected_monos
46
+
47
+ def monochromators(self) -> list[Monochromator]:
48
+ return self._monochromators
@@ -0,0 +1,5 @@
1
+ from .abstract_device import AbstractDevice
2
+ from .ccd import ChargeCoupledDevice
3
+ from .monochromator import Monochromator
4
+
5
+ __all__ = ['AbstractDevice', 'Monochromator', 'ChargeCoupledDevice']
@@ -0,0 +1,79 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any
3
+
4
+ from horiba_sdk.communication import AbstractCommunicator, Command, Response
5
+ from horiba_sdk.icl_error import AbstractError, AbstractErrorDB
6
+
7
+
8
+ class AbstractDevice(ABC):
9
+ """
10
+ Abstract base class representing a generic device.
11
+
12
+ This class provides an interface for device-specific operations. Concrete implementations should provide specific
13
+ functionalities for each of the abstract methods.
14
+
15
+ Attributes:
16
+ _id (int):
17
+ _communicator (WebsocketCommunicator):
18
+ """
19
+
20
+ def __init__(self, device_id: int, communicator: AbstractCommunicator, error_db: AbstractErrorDB) -> None:
21
+ self._id: int = device_id
22
+ self._error_db: AbstractErrorDB = error_db
23
+ self._communicator: AbstractCommunicator = communicator
24
+
25
+ @abstractmethod
26
+ async def open(self) -> None:
27
+ """
28
+ Open a connection to the device.
29
+
30
+ Returns:
31
+ Result: Result object indicating success or failure.
32
+ """
33
+ if not self._communicator.opened():
34
+ await self._communicator.open()
35
+
36
+ @abstractmethod
37
+ async def close(self) -> None:
38
+ """
39
+ Close the connection to the device.
40
+
41
+ Returns:
42
+ Result: Result object indicating success or failure.
43
+ """
44
+ pass
45
+
46
+ async def _execute_command(self, command_name: str, parameters: dict[Any, Any], timeout: int = 5) -> Response:
47
+ """
48
+ Creates a command from the command name, and it's parameters
49
+ Executes a command and handles the response.
50
+
51
+ Args:
52
+ command_name (str): The name of the command to execute.
53
+ parameters (dict): The parameters for the command.
54
+
55
+ Returns:
56
+ Response: The response from the device.
57
+
58
+ Raises:
59
+ Exception: When an error occurred on the device side.
60
+ """
61
+ response: Response = await self._communicator.request_with_response(
62
+ Command(command_name, parameters), timeout=timeout
63
+ )
64
+ if response.errors:
65
+ self._handle_errors(response.errors)
66
+ return response
67
+
68
+ def _handle_errors(self, errors: list[str]) -> None:
69
+ """
70
+ Handles errors, logs them, and may take corrective actions.
71
+
72
+ Args:
73
+ errors (Exception): The exception or error to handle.
74
+ """
75
+ for error in errors:
76
+ icl_error: AbstractError = self._error_db.error_from(error)
77
+ icl_error.log()
78
+ # TODO: [saga] only throw depending on the log level, tbd
79
+ raise Exception(f'Error from the ICL: {icl_error.message()}')