Server and client implementation

This chapter describes the project-defined common robot-control interface implemented for the MG400 using the provided src/dobot/server_fastapi/ sources. ese774_frame transports calls; it does not define the robot-specific control contract.

Control paths

  • Local: application → DobotCtrl → DobotTcp → MG400.

  • Remote: application → SyncDobotClient / AsyncDobotClient / DeviceProxy → ese774_frame → server-side DobotCtrl → DobotTcp → MG400.

The server configures FastApiServer with device_cls=DobotCtrl, router_cls=None, api_spec=None, and object_name="dobot". This uses the framework’s automatic dispatch without requiring a custom router or API specification.

Starting the server

The packaged dobot.server_fastapi.server module constructs its server from the Config class attributes. Defaults include SERVER_IP="127.0.0.1", SERVER_PORT=8000, and DOBOT_IP="192.168.1.6".

python -m dobot.server_fastapi.server

Important: The module constructs its FastApiServer object at import time. Calling Config.load_yaml() in a different Python process does not configure this server process. To customize settings, load the configuration in the same process, before creating the server. The provided server entry point does not automatically load a YAML file.

The following is a separate launcher script that explicitly loads YAML before constructing the server. An absolute path is used because Config.load_yaml() resolves relative paths against the calling source file.

from pathlib import Path

from dobot.config import Config
from dobot.dobot_ctrl import DobotCtrl
from ese774_frame import FastApiServer
from x_logger import XLogger

Config.load_yaml(Path(__file__).resolve().parent / "config_dobot_server.yaml")
logger = XLogger(log_level=Config.LOGGER_LEVEL, logger_name=Config.SERVER_LOGGER_NAME)
server = FastApiServer(
    device_cls=DobotCtrl,
    router_cls=None,
    config=Config,
    api_spec=None,
    object_name="dobot",
    device_kwargs={"dobot_ip": Config.DOBOT_IP, "instance_name": Config.INSTANCE_NAME},
    logger=logger,
    logger_name=Config.SERVER_LOGGER_NAME,
    lifespan_msg_prefix="DOBOT",
)
server.run(host=Config.SERVER_IP, port=Config.SERVER_PORT)
SERVER_IP: "127.0.0.1"
SERVER_PORT: 8000
DOBOT_IP: "192.168.1.6"
INSTANCE_NAME: "Ctrl"
LOGGER_LEVEL: "INFO"

SERVER_IP is the HTTP server bind address; DOBOT_IP is the robot controller address. They are not interchangeable. Exposing a motion-capable HTTP service requires separate network and access-control measures.

Synchronous and asynchronous clients

SyncDobotClient extends SyncDeviceClient; AsyncDobotClient extends AsyncDeviceClient. Both pass object_name="dobot" and api_spec=None to their base class.

from dobot.server_fastapi.client_sync import SyncDobotClient

client = SyncDobotClient(server_ip="127.0.0.1", server_port=8000)
from dobot.server_fastapi.client_async import AsyncDobotClient

client = AsyncDobotClient(server_ip="127.0.0.1", server_port=8000)

Important: Both constructors default server_ip and server_port to None. Without a config argument, the current implementation assembles http://None:None. Pass explicit connection parameters or a Config instance. When config is provided, its SERVER_IP and SERVER_PORT take precedence over the individual parameters.

server_fastapi/__init__.py registers DeviceProxy under DobotCtrl and the alias dobot, with default_async_mode=True. This does not mean that a robot motion has completed: asynchronous HTTP calls and robot motion completion are separate concerns.

Scope of verification

These examples reproduce initialization patterns from the supplied Python sources. The actual MG400, deployment environment, installed ese774_frame version, and physical motion require separate verification. Do not use an HTTP response as the sole safety-stop mechanism.