Metadata-Version: 2.4
Name: gclight
Version: 0.1.0
Summary: Typed, synchronous Python SDK for GC Light devices
Author: Pidbid
Author-email: Pidbid <wicos@wicos.cn>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Dist: pyserial>=3.5
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/Pidbid/gclight-python
Project-URL: Repository, https://github.com/Pidbid/gclight-python
Project-URL: Issues, https://github.com/Pidbid/gclight-python/issues
Description-Content-Type: text/markdown

# gclight Python 开发工具包

[英文文档](README_EN.md)

`gclight` 是 GC Light 设备的类型化 Python SDK。当前版本 `0.1.0` 实现设备线协议 v1 的 Mini 串口控制；`gclight.v1` 是线协议命名空间，不是包版本别名。

## 要求与安装

- Python 3.10 或更高版本
- Windows 或 Ubuntu 上可用的串口

使用 `uv` 添加 SDK 依赖：

```bash
uv add gclight
```

## 最小连接与安全开光

构造 `Mini` 不执行 I/O；`connect()` 或上下文管理器才打开指定串口。SDK 不会隐式扫描系统串口。
无线功能仅公开 `query_bluetooth_enabled()` 状态查询和 `set_bluetooth_enabled()` 开关控制。

```python
from gclight.v1.mini import Mini

# 使用实际端口。
with Mini("COM3") as device:
    print(device.info.serial_number)
    print(device.state.actual_current_ma)

    # 同帧先设电流。
    device.laser_on(current_ma=120.00)
    device.laser_off()
```

## 消费主动上报与处理异常

后台读取线程在没有消费者或待处理命令时仍持续接收设备主动上报。`next_event()` 只等待本地有界事件通道，不会轮询设备。

```python
from gclight.v1.mini import (
    EventTimeoutError,
    ExceptionReport,
    Mini,
    TelemetryReport,
)

with Mini("COM3") as device:
    device.laser_on(current_ma=120.00)
    try:
        event = device.next_event(timeout=1.0)
    except EventTimeoutError:
        print("1 秒内没有主动上报")
    else:
        if isinstance(event, TelemetryReport):
            print(event.current_ma, event.pd_data)
        elif isinstance(event, ExceptionReport):
            print(f"设备异常位：0x{event.error_bits:04X}")
    finally:
        device.laser_off()
```

命令失败通过具体异常表达。命令超时或发送失败、无法确认设备是否已收到命令时，会话进入失步状态；首次发送失败抛出 `TransportError`，后续命令抛出 `SessionDesynchronizedError`。此时仍可消费设备主动上报，但必须先 `close()`，再 `connect()` 才能恢复命令发送；SDK 不自动重发或重放控制命令。

流解码器按声明长度等待完整帧，不会把未完成帧载荷中的魔数或完整帧字节当作新消息。长度合法但不完整的候选帧不会被后续候选帧抢占；无法继续收全时，由命令超时及关闭重连恢复。

## 开发与验证

```bash
uv sync
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv build
```
