second option, different attributes
It will be possible for what is currently backends, will be drivers to implement multiple “capability backends”, but they can also be separate objects that then point to the driver.
See this post for more info: Updating PLR API for machine interfaces discussion - #62 by rickwierenga
whether something exists in standard.py is just a question of whether we want backends to support it. In this case you and @vcjdeboer have made convincing arguments that time series are an atomic command, not just a loop on the client side.
why is frontend/client read time important? assuming backend here means machine reported time for each measurement.
I was thinking two separate methods for stream/read. Backend only does streaming so
class AbsorbanceReaderBackend:
async def stream_absorbance(self) -> AsyncGenerator[dict, None]: ...
and on the front end:
class AbsorbanceReader:
async def stream_absorbance(self) -> AsyncGenerator[dict, None]: ...
async def read_absorbance(self) -> List[dict]:
all_data = []
async for data in pr.stream():
all_data.append(data)
return data
Changing the return type based on a parameter is ugly.
Mostly a topic for the main architecture thread, but will answer briefly here. The idea is the Device (object user creates) will orchestrate different capabilities, so
class TecanInfinite:
def __init__(self, ...):
self.driver = TecanInfiniteDriver(...)
self.absorbance_reader = AbsorbanceReader(backend=InfiniteAbsorbance(driver=self.driver))
self.temperature_controller = TemperatureController(backend=InfiniteTemperatureController(driver=self.driver))
self.shaker = Shaker(backend=InfiniteShaker(driver=self.driver))
The capabilities are universal, and mimic the existing front/backend pattern. In this specific example I assume we have different InfiniteAbsorbance, InfiniteTemperatureController, InfiniteShaker objects (I assume we want this for big backends), but we can also have TecanInfiniteDriver implement AbsorbanceReaderBackend etc. directly.