Ohara Lab

Device Server Development Guide

Back to index / Design principles / System architecture

Development articles

  ese774 Frame gRPC Frame
Minimal example Quick Start Quick Start
Implementation Development guide Detailed guide
Examples Router and client examples Streaming examples

For API exposure see Dynamic dispatch; for client registration see DeviceProxy and Factory; for installation see the installation guide.

Scope

This is the entry point for developers implementing a DeviceClass and optionally exposing it through a communication Frame. Package installation, dependencies, and bundled startup scripts are documented separately in the installation manual, and are not duplicated here.

The fundamental unit is an ordinary Python DeviceClass that does not know the transport. It can be used locally without a server. Add a Frame only when remote access is required; do not rewrite device control APIs for a particular transport.

Local:   Application ── DeviceClass ── Hardware
Remote:  Application ── Client / DeviceProxy ── Transport ── Frame / Server ── DeviceClass ── Hardware

First server walkthrough: ese774 Frame

  1. Implement a transport-independent DeviceClass and test it locally.
  2. Start with ese774 Frame’s dynamic-dispatch workflow. Do not create ApiSpec and Pydantic models by default.
  3. Test synchronous or asynchronous clients; register DeviceProxy when useful.
  4. Extend Router or client classes only when a transport-boundary responsibility requires it. Keep hardware control in the DeviceClass.
  5. Use an explicit ApiSpec/Pydantic API only when that is required; it is not mandatory for every device.

See the ese774 Quick Start and dispatch/API guide for details.

gRPC Frame device server

Start with the gRPC Quick Start. For RPC, streaming and event subscriptions, see the gRPC Frame development guide. The DeviceClass remains independent of the communication Frame.

Development sequence and article responsibilities

  1. DeviceClass: implement device operations, state and device-specific error handling as a transport-independent Python API; test it locally.
  2. Select a Frame: choose ese774, gRPC or another supported Frame according to the requirements. Multiple Frames may expose the same DeviceClass.
  3. Server boundary: connect the DeviceClass to the Frame. Put server-side transport adaptations in a Router or stream object only where needed.
  4. Client boundary: extend the Frame client when needed for decoding, local file output, or higher-level compositions that belong on the client.
  5. Public interface and typing: register and expose DeviceProxy where appropriate; maintain .pyi declarations and check correspondence with the direct API.
  6. Distribution: see the separate installation manual for dependencies and bundled scripts.

Follow the detailed ese774 Frame development guide or gRPC Frame development guide. Dispatch and explicit APIs explains exposure mechanisms; DeviceProxy and Factory explains client construction, registration and typing; the ese774 Quick Start is a minimal exercise. These are not device operation manuals.

Package layout

The following is a responsibility-oriented example derived from UR, COBOTTA, MiniPIX and aandd_reader. Neither Frame nor every file is mandatory.

project/
├── pyproject.toml
├── src/
│   └── device_package/
│       ├── __init__.py
│       ├── device_ctrl.py             # DeviceClass (placeholder name)
│       ├── server_fastapi/            # if using ese774 Frame
│       │   ├── __init__.py            # public interface / registration
│       │   ├── spec_ctrl.py           # optional explicit API
│       │   ├── models/                # optional Pydantic models
│       │   ├── routers/               # optional DeviceRouter subclass
│       │   ├── clients/               # sync / async clients
│       │   └── make.py                # optional .pyi generation
│       └── server_grpc/               # if using gRPC Frame
│           ├── __init__.py
│           ├── device_grpc_server.py
│           ├── device_grpc_client.py
│           ├── async_device_grpc_client.py
│           └── make_pyi.py
└── examples/                          # runnable server / client examples

Names such as device_package and device_ctrl.py are placeholders. build/, *.egg-info/ and __pycache__/ are generated artifacts, not authoritative source. The internal layouts of server_fastapi/ and server_grpc/ need not match.

Responsibility boundaries

Operation Where it belongs Rationale
Hardware connection, measurement, motion, state DeviceClass Meaningful even in local use
Device-specific errors and recovery DeviceClass or device support layer Independent of HTTP/gRPC
Request/response conversion and transport error propagation Frame / server adapter Introduced by the transport boundary
Reading a server-side device file and returning its contents DeviceClass, optionally Router Distinguish server actions from transferable data
Saving a file on the client computer Client Server paths are not client paths
Client-facing method adaptations and composite operations Derived client Preserve transport independence of DeviceClass
Proxy registration and typing Transport-specific subpackage .pyi is typing metadata, not runtime behavior

A transparent proxy does not erase the network boundary. Validate execution location, serialization, exceptions, timeouts, concurrency, events and file side effects. Private forwarding method names are not public API contracts.

Frame-specific differences

Aspect ese774 Frame gRPC Frame
Server construction Examples pass a DeviceClass class to FastApiServer Examples pass an instantiated object to create_grpc_server(ctrl_obj=...)
Exposure Automatic dispatch (api_spec=None) or explicit Pydantic / ApiSpec Automatic dispatch using Describe / Call
Server extensions DeviceRouter subclasses as needed Stream objects as needed
Client extensions SyncDeviceClient / AsyncDeviceClient GrpcClient / AsyncGrpcClient
Detailed guide ese774 Frame gRPC Frame

These describe the supplied implementations, not a compatibility guarantee across Frame releases. Some ese774_dummy examples have not been verified against the latest Frame.

Development checks

Implementation references

ese774_dummy, UR, COBOTTA, MiniPIX, aandd_reader. They illustrate Framework usage; they are not separate top-level device manuals.

The legacy guide is retained for historical reference.