Skip to content

Commit 469c501

Browse files
authored
Merge pull request #243 from DiamondLightSource/controller-disconnect
Add Controller.disconnect
2 parents 15b1a66 + 1976893 commit 469c501

32 files changed

+239
-196
lines changed

docs/snippets/static05.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,5 @@ class TemperatureController(Controller):
1919
epics_ca = EpicsCATransport(gui=gui_options, ca_ioc=EpicsIOCOptions(pv_prefix="DEMO"))
2020
fastcs = FastCS(TemperatureController(), [epics_ca])
2121

22-
fastcs.create_gui()
23-
2422
if __name__ == "__main__":
2523
fastcs.run()

docs/snippets/static06.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ async def connect(self):
2929
connection_settings = IPConnectionSettings("localhost", 25565)
3030
fastcs = FastCS(TemperatureController(connection_settings), [epics_ca])
3131

32-
fastcs.create_gui()
3332

3433
if __name__ == "__main__":
3534
fastcs.run()

docs/snippets/static07.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,5 @@ async def connect(self):
5353
connection_settings = IPConnectionSettings("localhost", 25565)
5454
fastcs = FastCS(TemperatureController(connection_settings), [epics_ca])
5555

56-
fastcs.create_gui()
57-
5856
if __name__ == "__main__":
5957
fastcs.run()

docs/snippets/static08.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,5 @@ async def connect(self):
5959
connection_settings = IPConnectionSettings("localhost", 25565)
6060
fastcs = FastCS(TemperatureController(connection_settings), [epics_ca])
6161

62-
fastcs.create_gui()
63-
6462
if __name__ == "__main__":
6563
fastcs.run()

docs/snippets/static09.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,5 @@ async def connect(self):
6666
connection_settings = IPConnectionSettings("localhost", 25565)
6767
fastcs = FastCS(TemperatureController(connection_settings), [epics_ca])
6868

69-
fastcs.create_gui()
70-
7169
if __name__ == "__main__":
7270
fastcs.run()

docs/snippets/static10.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,5 @@ async def connect(self):
8484
connection_settings = IPConnectionSettings("localhost", 25565)
8585
fastcs = FastCS(TemperatureController(4, connection_settings), [epics_ca])
8686

87-
fastcs.create_gui()
88-
8987
if __name__ == "__main__":
9088
fastcs.run()

docs/snippets/static11.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,5 @@ async def connect(self):
9191
connection_settings = IPConnectionSettings("localhost", 25565)
9292
fastcs = FastCS(TemperatureController(4, connection_settings), [epics_ca])
9393

94-
fastcs.create_gui()
95-
9694
if __name__ == "__main__":
9795
fastcs.run()

docs/snippets/static12.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,5 @@ async def update_voltages(self):
104104
connection_settings = IPConnectionSettings("localhost", 25565)
105105
fastcs = FastCS(TemperatureController(4, connection_settings), [epics_ca])
106106

107-
fastcs.create_gui()
108-
109107
if __name__ == "__main__":
110108
fastcs.run()

docs/snippets/static13.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,5 @@ async def disable_all(self) -> None:
112112
connection_settings = IPConnectionSettings("localhost", 25565)
113113
fastcs = FastCS(TemperatureController(4, connection_settings), [epics_ca])
114114

115-
fastcs.create_gui()
116-
117115
if __name__ == "__main__":
118116
fastcs.run()

src/fastcs/control_system.py

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from fastcs.controller import BaseController, Controller
1010
from fastcs.controller_api import ControllerAPI
11-
from fastcs.cs_methods import Command, Scan
11+
from fastcs.cs_methods import Command, Scan, ScanCallback
1212
from fastcs.exceptions import FastCSError
1313
from fastcs.logging import logger as _fastcs_logger
1414
from fastcs.tracer import Tracer
@@ -36,36 +36,17 @@ def __init__(
3636
transports: Sequence[Transport],
3737
loop: asyncio.AbstractEventLoop | None = None,
3838
):
39-
self._loop = loop or asyncio.get_event_loop()
4039
self._controller = controller
41-
42-
self._scan_tasks: set[asyncio.Task] = set()
43-
44-
# these initialise the controller & build its APIs
45-
self._loop.run_until_complete(controller.initialise())
46-
self._loop.run_until_complete(controller.attribute_initialise())
47-
validate_hinted_attributes(controller)
48-
self.controller_api = build_controller_api(controller)
49-
50-
self._scan_coros, self._initial_coros = (
51-
self.controller_api.get_scan_and_initial_coros()
52-
)
53-
self._initial_coros.append(controller.connect)
54-
5540
self._transports = transports
56-
for transport in self._transports:
57-
transport.initialise(controller_api=self.controller_api, loop=self._loop)
41+
self._loop = loop or asyncio.get_event_loop()
5842

59-
def create_docs(self) -> None:
60-
for transport in self._transports:
61-
transport.create_docs()
43+
self._scan_coros: list[ScanCallback] = []
44+
self._initial_coros: list[ScanCallback] = []
6245

63-
def create_gui(self) -> None:
64-
for transport in self._transports:
65-
transport.create_gui()
46+
self._scan_tasks: set[asyncio.Task] = set()
6647

67-
def run(self):
68-
serve = asyncio.ensure_future(self.serve())
48+
def run(self, interactive: bool = True):
49+
serve = asyncio.ensure_future(self.serve(interactive=interactive))
6950

7051
self._loop.add_signal_handler(signal.SIGINT, serve.cancel)
7152
self._loop.add_signal_handler(signal.SIGTERM, serve.cancel)
@@ -100,7 +81,18 @@ def _stop_scan_tasks(self):
10081
except Exception as e:
10182
raise RuntimeError("Unhandled exception in stop scan tasks") from e
10283

103-
async def serve(self) -> None:
84+
self._scan_tasks.clear()
85+
86+
async def serve(self, interactive: bool = True) -> None:
87+
await self._controller.initialise()
88+
validate_hinted_attributes(self._controller)
89+
self._controller.connect_attribute_ios()
90+
91+
self.controller_api = build_controller_api(self._controller)
92+
self._scan_coros, self._initial_coros = (
93+
self.controller_api.get_scan_and_initial_coros()
94+
)
95+
10496
context = {
10597
"controller": self._controller,
10698
"controller_api": self.controller_api,
@@ -109,8 +101,9 @@ async def serve(self) -> None:
109101
],
110102
}
111103

112-
coros = []
104+
coros: list[Coroutine] = []
113105
for transport in self._transports:
106+
transport.connect(controller_api=self.controller_api, loop=self._loop)
114107
coros.append(transport.serve())
115108
common_context = context.keys() & transport.context.keys()
116109
if common_context:
@@ -122,14 +115,23 @@ async def serve(self) -> None:
122115
)
123116
context.update(transport.context)
124117

125-
coros.append(self._interactive_shell(context))
118+
if interactive:
119+
coros.append(self._interactive_shell(context))
120+
else:
121+
122+
async def block_forever():
123+
while True:
124+
await asyncio.sleep(1)
125+
126+
coros.append(block_forever())
126127

127128
logger.info(
128129
"Starting FastCS",
129130
controller=self._controller,
130131
transports=f"[{', '.join(str(t) for t in self._transports)}]",
131132
)
132133

134+
await self._controller.connect()
133135
await self._run_initial_coros()
134136
await self._start_scan_tasks()
135137

@@ -139,6 +141,10 @@ async def serve(self) -> None:
139141
pass
140142
except Exception as e:
141143
raise RuntimeError("Unhandled exception in serve") from e
144+
finally:
145+
logger.info("Shutting down FastCS")
146+
self._stop_scan_tasks()
147+
await self._controller.disconnect()
142148

143149
async def _interactive_shell(self, context: dict[str, Any]):
144150
"""Spawn interactive shell in another thread and wait for it to complete."""

0 commit comments

Comments
 (0)