# Quick Start

This guide shows how to build and use a PlestyLib device API with the Thorlabs PM100D power meter as an example.

## Install

```bash
pip install plestylib
```

## Before You Implement a Device API

Collect the following information first:

1. Which physical interface is used (USB, Ethernet, Serial, and so on)?
2. Which communication protocol is provided (SCPI, vendor SDK, custom binary protocol)?
3. Where is the protocol reference (manual, command table, SDK docs)?

For PM100D, the typical setup is USB + SCPI, with commands described in the vendor manual.

## Implement a PM100D Device Class

When the device uses VISA + SCPI, inherit from `BaseVisaScpiDevice` and register parameters through the [Parameter system](device/param_system.md).

```python
from plestylib.device.base_visa_scpi_device import BaseVisaScpiDevice


class PowermeterDevice(BaseVisaScpiDevice):
    SENSOR_WAVELENGTH_RANGES = {
        "S155C": (800, 1700),
        "S120C": (400, 1100),
        "S130C": (400, 1100),
    }

    def __init__(self, address: str, sensor_type: str):
        super().__init__(address)

        if sensor_type not in self.SENSOR_WAVELENGTH_RANGES:
            raise ValueError(f"Unsupported sensor type: {sensor_type}")

        min_wl, max_wl = self.SENSOR_WAVELENGTH_RANGES[sensor_type]

        self.register_config("SENSOR", read_only=True, command="SYST:SENS:IDN")
        self.register_config(
            "WAVELENGTH",
            dtype=int,
            unit="nm",
            min_value=min_wl,
            max_value=max_wl,
            command="SENS:CORR:WAV",
        )
        self.register_config("DIAMETER", dtype=float, command="SENS:CORR:BEAM")
        self.register_config("POWER_RANGE", dtype=float, command="SENS:POW:RANG")
        self.register_config("POWER_RANGE_AUTO", dtype=bool, default=True, command="SENS:POW:RANG:AUTO")
        self.register_config("AVERAGES", dtype=int, command="SENS:AVER:COUN")
        self.register_config("POWER", read_only=True, dtype=float, unit="watt", command="MEAS:SCAL:POW")
```

## Use the Device Locally

### Context Manager (Recommended)

```python
from powermeter_device import PowermeterDevice

address = "USB0::0x1313::0x8078::P0000001::INSTR"
sensor_type = "S155C"

with PowermeterDevice(address, sensor_type=sensor_type) as powermeter:
    print(powermeter.identity())
    for name in powermeter.get_config_list():
        value = powermeter.query(name)
        print(f"{name}: {value}")

        cfg = powermeter.get_config(name)
        if not cfg.read_only:
            powermeter.write(name, value)
```

### Manual Connect/Disconnect

```python
from powermeter_device import PowermeterDevice

address = "USB0::0x1313::0x8078::P0000001::INSTR"
sensor_type = "S155C"

powermeter = PowermeterDevice(address, sensor_type=sensor_type)
powermeter.connect()

try:
    print(powermeter.identity())
    for name in powermeter.get_config_list():
        value = powermeter.query(name)
        print(f"{name}: {value}")
finally:
    powermeter.disconnect()
```

## Use the Device Asynchronously

```python
import asyncio

from powermeter_device import PowermeterDevice
from plestylib.device.async_wrapper import AsyncWrapperSafe

address = "USB0::0x1313::0x8078::P0000001::INSTR"
sensor_type = "S155C"


async def main() -> None:
    async with AsyncWrapperSafe(PowermeterDevice(address, sensor_type=sensor_type)) as powermeter:
        print(await powermeter.identity())

        for name in await powermeter.get_config_list():
            value = await powermeter.query(name)
            print(f"{name}: {value}")


asyncio.run(main())
```

## Access the Device Remotely

### Host Machine (Run Server)

```python
import asyncio

from powermeter_device import PowermeterDevice
from plestylib.service import build_server

address = "USB0::0x1313::0x8078::P0000001::INSTR"
sensor_type = "S155C"


async def main() -> None:
    device = PowermeterDevice(address, sensor_type=sensor_type)
    server = build_server(device, fixed_threading=False, address="tcp://*:5555")
    await server.run()


asyncio.run(main())
```

### Remote Machine (Run Client)

```python
from plestylib.service import build_client

client = build_client(address="tcp://<host-ip>:5555", timeout=5000)

for name in client.get_config_list():
    value = client.query(name)
    print(f"{name}: {value}")
```

## Next Reading

1. [Parameter system](device/param_system.md)
2. [Traffic manager](device/traffic_manager.md)
3. [Command solver](device/cmd_solver.md)