Metadata-Version: 2.4
Name: py-tjbrhk-toolkit
Version: 3.0.3
Summary: 天津博瑞皓科 Python 客户端库，提供与天津博瑞皓科 API 交互的完整功能支持
Author-email: 郭磊 <174000902@qq.com>
License: MIT
Project-URL: Homepage, https://gitee.com/guolei19850528/py_tjbrhk_toolkit
Project-URL: Repository, https://gitee.com/guolei19850528/py_tjbrhk_toolkit.git
Project-URL: PyPI Homepage, https://pypi.org/project/py-tjbrhk-toolkit/
Keywords: 天津博瑞皓科,tjbrhk,python,client,智能云音箱,api
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
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: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24.0
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
Dynamic: license-file

# py-tjbrhk-toolkit

天津博瑞皓科博瑞云音箱 Python 客户端库，实现官方《博瑞云音箱 API 对接文档》中定义的全部接口。

[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![官方文档](https://img.shields.io/badge/官方文档-语雀-blue.svg)](https://www.yuque.com/lingdutuandui/ugcpag/umbzsd)

## 项目简介

`py-tjbrhk-toolkit` 是天津博瑞皓科博瑞云音箱 API 的 Python 客户端库。它严格基于 [官方文档（语雀）](https://www.yuque.com/lingdutuandui/ugcpag/umbzsd) 实现，覆盖以下全部接口：

| 接口 | 版本 | 类型 | 官方说明 |
|------|------|------|----------|
| notify.php | 3.1 | 流量版专用 | 将通知消息提交到云音箱服务器，云音箱接收后通过 TTS 播报。仅适用于流量版（2G/4G）音箱。 |
| bind.php | 2.1 | 基础接口 | 云音箱绑定或解绑，支持绑定（m=1）、解绑（m=0）和强制解绑（m=4）。 |
| add.php | 2.2 | 基础接口 | 将支付结果提交到云音箱服务器，云音箱播报收款提示语音。price 单位为分。 |
| modify_bootvoicewav.php | 3.2 | 灰度测试 | 更改开机语音、自定义播报前缀。仅适用于 402、404、502、504 型号。 |

**接口约定（来自官方文档）：**
- 所有接口均为 `POST` 请求，以 `application/x-www-form-urlencoded` 提交表单数据。
- 返回 JSON 格式 `{"errcode", "errmsg", "detail"}`，`errcode` 为 0 即视为业务成功。
- 本库不涉及登录与 Token 缓存，Token 由调用方自行管理并传入。

## 安装

推荐使用 `uv` 安装：

```bash
uv add py-tjbrhk-toolkit
```

或使用 `pip` 安装：

```bash
pip install py-tjbrhk-toolkit
```

从本地源码安装（开发模式）：

```bash
uv venv .venv
source .venv/bin/activate
uv pip install -e .
uv pip install -e ".[dev]"
```

## 快速开始

### 同步模式

```python
from py_tjbrhk_toolkit.speaker.client import SpeakerClient

client = SpeakerClient(
    base_url="https://speaker.17laimai.cn/",
    token="your_token",
    id="your_speaker_id",
    version="1",
)

# 通知语音播报（流量版专用）
response = client.notify(message="[123]收款66元", vol=80)
print(response.json())

# 云音箱绑定（m=1 绑定，0 解绑，4 强制解绑）
response = client.bind(m=1, uid="user_123")

# 支付语音播报（price 单位为分）
response = client.add(price="3879", pt=1, vol=80)

# 更改语音信息（灰度测试，仅 402/404/502/504）
response = client.modify_boot_voice_wav(sound="欢迎光临", type=0, off_text="谢谢使用")

client.close()
```

### 异步模式

```python
import asyncio
from py_tjbrhk_toolkit.speaker.client import AsyncSpeakerClient

async def main():
    client = AsyncSpeakerClient(
        base_url="https://speaker.17laimai.cn/",
        token="your_token",
        id="your_speaker_id",
        version="1",
    )
    response = await client.async_notify(message="Hello World")
    print(response.json())
    await client.close()

asyncio.run(main())
```

所有客户端均支持 `with` / `async with` 上下文管理器，退出时自动关闭底层 httpx 客户端。

## API 参考

### SpeakerClient / AsyncSpeakerClient

初始化参数：

| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| base_url | str | 否 | `https://speaker.17laimai.cn/` | API 基础地址 |
| token | str | 否 | `""` | Token，代理商分配的接口凭证 |
| id | str | 否 | `""` | SPEAKERID，云音箱标签上的 SN 码 |
| version | str | 否 | `"1"` | 接口版本 |
| timeout | float | 否 | `30.0` | 请求超时时间（秒） |

#### notify.php — 通知语音播报

同步：`client.notify(message, *, id, token, version, seq, vol, speed, trace_no, **kwargs)`  
异步：`await client.async_notify(...)`

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| message | str | 是 | 通知消息内容，长度最长 128 字节 |
| id | str | 否 | SPEAKERID，未提供则使用客户端配置 |
| token | str | 否 | TOKEN，未提供则使用客户端配置 |
| version | str | 否 | 接口版本，未提供则使用客户端配置 |
| seq | int \| str | 否 | 通讯去重顺序号，范围 [0, 4294967295] |
| vol | int \| str | 否 | 音量设置值，范围 0 到 100 |
| speed | int \| str | 否 | 语速，范围 0-100，默认 50（仅限 404、504） |
| trace_no | str | 否 | 追踪字符串，最大 63 字节 |

#### bind.php — 云音箱绑定/解绑

同步：`client.bind(m, uid, *, id, token, version, seq, descs, **kwargs)`  
异步：`await client.async_bind(...)`

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| m | int \| str | 是 | METHOD，0 解绑 / 1 绑定 / 4 强制解绑 |
| uid | str | 是 | USERID，开发者自定义，在自身系统内唯一即可 |
| id | str | 否 | SPEAKERID，未提供则使用客户端配置 |
| token | str | 否 | TOKEN，未提供则使用客户端配置 |
| version | str | 否 | 接口版本，未提供则使用客户端配置 |
| seq | int \| str | 否 | 通讯去重顺序号，范围 [0, 4294967295] |
| descs | str | 否 | 绑定描述，最大 255 字节 |

#### add.php — 支付语音播报

同步：`client.add(price, *, id, token, version, uid, pt, vol, seq, trace_no, descs, suffix, **kwargs)`  
异步：`await client.async_add(...)`

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| price | int \| str | 是 | 支付金额值，单位为分，范围 1 至 2147483647 |
| id | str | 否 | SPEAKERID，未提供则使用客户端配置 |
| token | str | 否 | TOKEN，未提供则使用客户端配置 |
| version | str | 否 | 接口版本，未提供则使用客户端配置 |
| uid | str | 否 | USERID，开发者自定义 |
| pt | int \| str | 否 | 支付类型，决定播报不同提示语音 |
| vol | int \| str | 否 | 音量设置值，范围 0 到 100 |
| seq | int \| str | 否 | 通讯去重顺序号，范围 [0, 4294967295] |
| trace_no | str | 否 | 追踪字符串，最大 63 字节 |
| descs | str | 否 | 支付消息描述，最大 255 字节 |
| suffix | int \| str | 否 | 是否开启自定义收款消息后缀，1 表示开启 |

#### modify_bootvoicewav.php — 更改语音信息

同步：`client.modify_boot_voice_wav(sound, type, *, id, token, version, off_text, seq, descs, **kwargs)`  
异步：`await client.async_modify_boot_voice_wav(...)`

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sound | str | 是 | 开机铃声，中文最长 15 字，其他字节 30 字节 |
| type | int \| str | 是 | TYPE，0 表示开机欢迎声音；传 off_text 时填写 1 |
| id | str | 否 | SPEAKERID，未提供则使用客户端配置 |
| token | str | 否 | TOKEN，未提供则使用客户端配置 |
| version | str | 否 | 接口版本，未提供则使用客户端配置 |
| off_text | str | 否 | 关机铃声，中文，可选 |
| seq | int \| str | 否 | 通讯去重顺序号，范围 [0, 4294967295] |
| descs | str | 否 | 描述字符串，最大 255 字节 |

### 返回码（errcode）

| 码 | 说明 |
|---|------|
| 0 | 成功 |
| 1 | 未知错误 |
| 2 | SPEAKERID 不存在 |
| 3 | SPEAKERID 已经被其它用户 ID 绑定 |
| 4 | SPEAKERID 已经被同一用户 ID 绑定 |
| 5 | SPEAKERID 未被任何用户 ID 绑定 |
| 6 | 未提供 SPEAKERID |
| 8 | 此 token 无此 SPEAKERID 权限 |
| 9 | 无效的 token |
| 17 | 重复的请求 |

## 目录结构

```text
py_tjbrhk_toolkit/
├── pyproject.toml
├── README.md
├── LICENSE
├── src/
│   └── py_tjbrhk_toolkit/
│       ├── __init__.py
│       ├── py.typed
│       └── speaker/
│           ├── __init__.py
│           ├── client.py     # SpeakerClient（同步）与 AsyncSpeakerClient（异步）
│           └── models.py     # Pydantic 响应模型
├── tests/
│   └── speaker/
│       ├── __init__.py
│       ├── conftest.py
│       ├── test_speaker_sync.py
│       └── test_speaker_async.py
└── examples/
    └── speaker/
        ├── __init__.py
        ├── .env.example
        ├── example_common.py
        ├── example_notify.py
        ├── example_bind.py
        ├── example_add.py
        ├── example_modify_boot_voice_wav.py
        ├── example_async_notify.py
        ├── example_async_bind.py
        ├── example_async_add.py
        └── example_async_modify_boot_voice_wav.py
```

## 证书

MIT License
