Quick Start#
This guide shows how to build and use a PlestyLib device API with the Thorlabs PM100D power meter as an example.
Install#
pip install plestylib
Before You Implement a Device API#
Collect the following information first:
Which physical interface is used (USB, Ethernet, Serial, and so on)?
Which communication protocol is provided (SCPI, vendor SDK, custom binary protocol)?
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.
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)#
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#
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#
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)#
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)#
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}")