Skip to content

Commit aef8b33

Browse files
committed
Add OdinAdapterController to parse commands at root of attribute
1 parent b848544 commit aef8b33

File tree

4 files changed

+75
-31
lines changed

4 files changed

+75
-31
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from fastcs.logging import bind_logger
2+
3+
from fastcs_odin.controllers.odin_subcontroller import OdinSubController
4+
5+
logger = bind_logger(logger_name=__name__)
6+
7+
8+
class OdinAdapterController(OdinSubController):
9+
"""Sub controller for an adapter in an odin control server"""
10+
11+
async def initialise(self):
12+
await self._create_attributes()
13+
await self._create_commands()

src/fastcs_odin/controllers/odin_controller.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from fastcs.connections.ip_connection import IPConnectionSettings
33
from fastcs.controllers import BaseController, Controller
44

5+
from fastcs_odin.controllers.odin_adapter_controller import OdinAdapterController
56
from fastcs_odin.controllers.odin_data.frame_processor import (
67
FrameProcessorAdapterController,
78
)
@@ -98,6 +99,6 @@ def _create_adapter_controller(
9899
connection, parameters, f"{self.API_PREFIX}/{adapter}", self._ios
99100
)
100101
case _:
101-
return OdinSubController(
102+
return OdinAdapterController(
102103
connection, parameters, f"{self.API_PREFIX}/{adapter}", self._ios
103104
)

src/fastcs_odin/controllers/odin_data/frame_processor.py

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
from fastcs.attributes import AttrR, AttrRW
77
from fastcs.datatypes import Bool, Int
88
from fastcs.logging import bind_logger
9-
from fastcs.methods import Command, command
10-
from pydantic import ValidationError
9+
from fastcs.methods import command
1110

1211
from fastcs_odin.controllers.odin_data.odin_data_adapter import (
1312
OdinDataAdapterController,
@@ -17,12 +16,7 @@
1716
StatusSummaryAttributeIORef,
1817
_filter_sub_controllers,
1918
)
20-
from fastcs_odin.util import (
21-
AllowedCommandsResponse,
22-
OdinParameter,
23-
create_attribute,
24-
partition,
25-
)
19+
from fastcs_odin.util import OdinParameter, create_attribute, partition
2620

2721
logger = bind_logger(logger_name=__name__)
2822

@@ -155,8 +149,6 @@ class FrameProcessorPluginController(OdinSubController):
155149
"""Controller for a plugin in a frameProcessor application."""
156150

157151
async def initialise(self):
158-
await self._create_commands()
159-
await self._create_dataset_controllers()
160152
for parameter in self.parameters:
161153
# Remove plugin name included in controller base path
162154
parameter.set_path(parameter.path[1:])
@@ -172,18 +164,10 @@ async def initialise(self):
172164
create_attribute(parameter=parameter, api_prefix=self._api_prefix),
173165
)
174166

175-
async def _create_commands(self):
176167
plugin_name = self.path[-1].lower()
177-
command_response = await self.connection.get(
178-
f"{self._api_prefix}/command/{plugin_name}/allowed"
179-
)
168+
await self._create_commands([plugin_name])
180169

181-
try:
182-
commands = AllowedCommandsResponse.model_validate(command_response)
183-
for command in commands.allowed:
184-
self._construct_command(command, plugin_name)
185-
except ValidationError:
186-
pass
170+
await self._create_dataset_controllers()
187171

188172
async def _create_dataset_controllers(self):
189173
if any("dataset" in p.path for p in self.parameters):
@@ -204,15 +188,6 @@ def __dataset_parameter(param: OdinParameter):
204188
self.add_sub_controller("DS", dataset_controller)
205189
await dataset_controller.initialise()
206190

207-
def _construct_command(self, command_name, plugin_name):
208-
async def submit_command() -> None:
209-
logger.info("Executing command", plugin=plugin_name, command=command_name)
210-
await self.connection.put(
211-
f"{self._api_prefix}/command/{plugin_name}/execute", command_name
212-
)
213-
214-
setattr(self, command_name, Command(submit_command))
215-
216191

217192
class FrameProcessorDatasetController(OdinSubController):
218193
"""Controller for datasets in the HDF plugin of a frameProcessor application"""

src/fastcs_odin/controllers/odin_subcontroller.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
from fastcs.attributes import AttributeIO, AttributeIORefT
44
from fastcs.controllers import Controller
55
from fastcs.datatypes import DType_T
6+
from fastcs.logging import bind_logger
7+
from fastcs.methods import Command
8+
from pydantic import ValidationError
69

710
from fastcs_odin.http_connection import HTTPConnection
8-
from fastcs_odin.util import OdinParameter, create_attribute
11+
from fastcs_odin.util import AllowedCommandsResponse, OdinParameter, create_attribute
12+
13+
logger = bind_logger(logger_name=__name__)
914

1015

1116
class OdinSubController(Controller):
@@ -33,8 +38,58 @@ def __init__(
3338
self._ios = ios
3439

3540
async def initialise(self):
41+
await self._create_attributes()
42+
43+
async def _create_attributes(self):
44+
"""Create an `Attribute` for each parameter"""
45+
3646
for parameter in self.parameters:
3747
self.add_attribute(
3848
parameter.name,
3949
create_attribute(parameter=parameter, api_prefix=self._api_prefix),
4050
)
51+
52+
async def _create_commands(self, path: Sequence[str] = ()):
53+
"""Create a `Command` for each allowed command in the odin server
54+
55+
Args:
56+
path: The sub path to the command under ``self._api_prefix``
57+
58+
"""
59+
response = await self.connection.get(
60+
f"{self._api_prefix}/command{'/' + '/'.join(path) if path else ''}/allowed"
61+
)
62+
63+
try:
64+
commands = AllowedCommandsResponse.model_validate(response)
65+
except ValidationError:
66+
logger.warning(
67+
"Failed to parse command response",
68+
path=self.path,
69+
response=response,
70+
)
71+
return
72+
73+
for command in commands.allowed:
74+
self._create_command(command, path)
75+
76+
def _create_command(self, name: str, path: Sequence[str] = ()):
77+
"""Create a `Command` that sends a command to the odin server
78+
79+
Args:
80+
name: The name of the command
81+
path: The sub path to the command under ``self._api_prefix``
82+
83+
"""
84+
uri = (
85+
f"{self._api_prefix}/command{'/' + '/'.join(path) if path else ''}/execute"
86+
)
87+
88+
async def submit_command() -> None:
89+
logger.info(
90+
"Executing command", controller=self.path, command=name, path=path
91+
)
92+
93+
await self.connection.put(uri, name)
94+
95+
setattr(self, name, Command(submit_command))

0 commit comments

Comments
 (0)