# Overview of the COBOTTA Client Using Device Class and Device Proxy To use COBOTTA within SUSANOO, a Device Class and a Device Proxy are required. The Device Class implements the actual COBOTTA control. `CobottaCtrl()` is provided as a higher-level interface, with either b-CAP or ORiN2 selectable as its backend. To control COBOTTA directly through `CobottaCtrl()` without a communication layer, the code looks approximately like this: ```python from cobotta2 import CobottaCtrl client = CobottaCtrl() client.move("P100") ``` This is a simplified example and will not run as written, but illustrates the concept. With the distributed control framework `ese774_frame`, the client side can instead be written as: ```python import asyncio from ese774_frame import DeviceProxy async def main(): client = DeviceProxy("CobottaCtrl") await client.move("P100") asyncio.run(main()) ``` For synchronous use: ```python import asyncio from ese774_frame import DeviceProxy client = DeviceProxy("CobottaCtrl", async_mode=False) client.move("P100") ``` The architecture uses the Factory design pattern. For example, an electronic balance can be accessed as follows: ```python import asyncio from ese774_frame import DeviceProxy client = DeviceProxy("AanddReader", async_mode=False) client.meas() ``` The key point is that the Device Class is selected by passing a **string** to `DeviceProxy`, rather than by passing the concrete class. For example: ```python import asyncio from ese774_frame import DeviceProxy device_class = "AanddReader" client = DeviceProxy(device_class, async_mode=False) client.meas() ``` This makes it possible to switch the client dynamically. It is a natural design pattern in Python and an important technique for writing flexible programs. ![](fig/cobotta_004.png) Returning to SUSANOO, the key feature of the framework is that the Device Class, although it resides on the device side, appears to exist **transparently** on the client PC through `DeviceProxy`. The implementation actually resides on the server, but the framework exposes it automatically to the client. Users therefore do not need to deal explicitly with most of the communication details. This is the defining feature of the transparent `DeviceProxy` approach. It is also possible to work directly with the concrete device client class: ```python import asyncio from cobotta2.server import AsyncCobottaClient client = AsyncCobottaClient() client.move("P100") ``` However, this approach is somewhat more verbose in Python, because separate asynchronous and synchronous classes exist: ```python import asyncio from cobotta2.server import SyncCobottaClient client = SyncCobottaClient() client.move("P100") ``` On the other hand, direct use of the concrete class can make the actual execution model easier to understand. Both styles are supported. ## Registering a DeviceClass with DeviceProxy Register the DeviceClass (DeviceClient) with `DeviceProxy`: ```python from cobotta2.server import AsyncCobottaClient,SyncCobottaClient from cobotta2.server import cobotta_ctrl_api_spec from ese774_frame.clients import register_device_proxy register_device_proxy( "CobottaCtrl", async_client_cls=AsyncCobottaClient, sync_client_cls=SyncCobottaClient, api_spec=cobotta_ctrl_api_spec, default_async_mode=True, aliases=["cobotta"], ) ``` --- ## Author - Kengo NAKADA