Device-server development / gRPC Quick Start / Home
This guide covers gRPC server and client development. Device control remains in the independent DeviceClass. Installation and packaging are documented separately in the installation guide.
create_grpc_server(ctrl_obj=...) receives a DeviceClass instance. GrpcClient obtains public methods using Describe, dynamically binds them, and invokes them through Call. Per-device RPC methods do not have to be added individually to .proto files. Serialization, exposed methods, and exception propagation still require testing.
from grpc_frame.grpc_server import create_grpc_server
server = create_grpc_server(ctrl_obj=ctrl, max_workers=10)
from grpc_frame.grpc_client import GrpcClient
class InstrumentGrpcClient(GrpcClient):
def __init__(self, server_ip: str, server_port: int):
super().__init__(server_ip=server_ip, server_port=server_port)
def read_and_report(self):
return self.read_value() # Public DeviceClass method
The added method is a client-side convenience method, not a framework RPC. See aandd_reader_grpc_client.py for a real implementation. Close the client with close().
The aandd_reader package provides AsyncAanddReaderGrpcClient, used as await client.meas(). Its configuration must already contain the server address and port. Check the actual client implementation for its asynchronous execution model.
import asyncio
from aandd_reader import Config
from aandd_reader.server_grpc import AsyncAanddReaderGrpcClient
async def main():
client = AsyncAanddReaderGrpcClient(config=Config)
try:
print(await client.meas())
finally:
client.close()
asyncio.run(main())
StreamCall handles streamed responses rather than a single Call result. In MiniPIX, _MiniPixStream bridges acquisition callbacks into a queue and yields frames as they arrive. The server can use a separate stream_obj alongside ctrl_obj:
server = create_grpc_server(ctrl_obj=ctrl, stream_obj=stream_obj)
Review pixet_grpc_server.py and async_pixet_grpc_client.py for the exact stream methods and client usage. Validate cancellation, queue growth, exceptions, and disconnect handling.
The framework provides an EventBus-based event channel, with GrpcClient.subscribe(topic=..., once=...). Streaming measurement frames and subscribing to event notifications are different operations. In aandd_reader, the device-specific client groups setup into prepare_event_measurement():
client.prepare_event_measurement(
topic="weight_threshold",
threshold_g=10.0,
above=True,
once=True,
trigger_mode="raw",
)
event = client.wait_event()
print(event)
client.stream_stop()
These are aandd_reader-specific convenience methods, not universal GrpcClient methods. Internally, the client invokes stream_start(), event_set_config(), set_trigger_mode(), and event_arm(); wait_event() subscribes to the selected topic. Distinguish the once parameter for arming from the subscription’s own once behavior.
Generated .pyi files should reflect both remotely exposed methods and client-side additions/overrides. The MiniPIX and aandd_reader packages contain server_grpc/make_pyi.py examples. Direct client use does not require DeviceProxy. See DeviceProxy and Factory.
Check the return value of add_insecure_port, start the server, and test connectivity. The aandd_reader server uses channel_ready_future, calls server.stop(...), and closes the device. insecure_channel does not provide encryption; consider network exposure. Review gRPC message size options for large payloads.
aandd_reader: regular RPC, synchronous/async clients, event subscription.mini_pix: streamed acquisition via StreamCall.cobotta2: additional gRPC implementation.See gRPC implementation examples for source excerpts.