py-tjbrhk-toolkit 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py_tjbrhk_toolkit-1.0.0/LICENSE +21 -0
- py_tjbrhk_toolkit-1.0.0/PKG-INFO +308 -0
- py_tjbrhk_toolkit-1.0.0/README.md +254 -0
- py_tjbrhk_toolkit-1.0.0/pyproject.toml +46 -0
- py_tjbrhk_toolkit-1.0.0/setup.cfg +4 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit/__init__.py +9 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit/speaker/__init__.py +135 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit/speaker/responses.py +36 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit/speaker/utils.py +100 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit.egg-info/PKG-INFO +308 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit.egg-info/SOURCES.txt +12 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit.egg-info/dependency_links.txt +1 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit.egg-info/requires.txt +11 -0
- py_tjbrhk_toolkit-1.0.0/src/py_tjbrhk_toolkit.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 郭磊
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py-tjbrhk-toolkit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: 一个用于与天津博瑞皓科 API 交互的 Python 客户端库
|
|
5
|
+
Author-email: Guolei <174000902@qq.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 郭磊
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://gitee.com/guolei19850528/py_tjbrhk_toolkit
|
|
29
|
+
Project-URL: Repository, https://gitee.com/guolei19850528/py_tjbrhk_toolkit.git
|
|
30
|
+
Keywords: 天津博瑞皓科,tjbrhk,python,client,智能云音箱,api
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: httpx>=0.27.0
|
|
44
|
+
Requires-Dist: pydantic>=2.0
|
|
45
|
+
Requires-Dist: jsonpath-ng>=1.5.3
|
|
46
|
+
Requires-Dist: jsonschema>=4.21.0
|
|
47
|
+
Requires-Dist: py-httpx-toolkit>=1.0.1
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
50
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
51
|
+
Requires-Dist: setuptools>=61.0; extra == "dev"
|
|
52
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# py-tjbrhk-toolkit
|
|
56
|
+
|
|
57
|
+
天津博瑞皓科 Python 客户端库,提供与天津博瑞皓科 API 交互的完整功能支持。
|
|
58
|
+
|
|
59
|
+
## 特性
|
|
60
|
+
|
|
61
|
+
- 支持同步和异步两种请求模式
|
|
62
|
+
- 提供通知发送功能
|
|
63
|
+
- 基于 Pydantic 的数据验证
|
|
64
|
+
- JSONPath 数据查询支持
|
|
65
|
+
- JSON Schema 校验功能
|
|
66
|
+
|
|
67
|
+
## 安装
|
|
68
|
+
|
|
69
|
+
### 使用 uv(推荐)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv add py-tjbrhk-toolkit
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 使用 pip
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install py-tjbrhk-toolkit
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## 依赖包
|
|
83
|
+
|
|
84
|
+
| 依赖 | 版本要求 | 说明 |
|
|
85
|
+
|------|----------|------|
|
|
86
|
+
| httpx | >=0.27.0 | HTTP 客户端库 |
|
|
87
|
+
| pydantic | >=2.0 | 数据验证库 |
|
|
88
|
+
| jsonpath-ng | >=1.5.3 | JSONPath 查询库 |
|
|
89
|
+
| jsonschema | >=4.21.0 | JSON Schema 校验库 |
|
|
90
|
+
| py-httpx-toolkit | >=1.0.1 | HTTP 工具库 |
|
|
91
|
+
|
|
92
|
+
## 快速开始
|
|
93
|
+
|
|
94
|
+
### 同步模式
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
98
|
+
|
|
99
|
+
# 初始化客户端
|
|
100
|
+
client = Speaker(
|
|
101
|
+
base_url="https://speaker.17laimai.cn",
|
|
102
|
+
token="your_token",
|
|
103
|
+
id="your_id",
|
|
104
|
+
version="1"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# 发送通知
|
|
108
|
+
response = client.notify(message="Hello World")
|
|
109
|
+
print(response.json())
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 异步模式
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import asyncio
|
|
116
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
117
|
+
|
|
118
|
+
async def main():
|
|
119
|
+
# 初始化客户端
|
|
120
|
+
client = Speaker(
|
|
121
|
+
base_url="https://speaker.17laimai.cn",
|
|
122
|
+
token="your_token",
|
|
123
|
+
id="your_id",
|
|
124
|
+
version="1"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# 异步发送通知
|
|
128
|
+
response = await client.async_notify(message="Hello World")
|
|
129
|
+
print(response.json())
|
|
130
|
+
|
|
131
|
+
asyncio.run(main())
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## API 文档
|
|
135
|
+
|
|
136
|
+
### Speaker 客户端
|
|
137
|
+
|
|
138
|
+
#### 初始化参数
|
|
139
|
+
|
|
140
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
141
|
+
|------|------|--------|------|
|
|
142
|
+
| base_url | str | https://speaker.17laimai.cn | Speaker 服务器地址 |
|
|
143
|
+
| token | str | "" | API 认证 Token |
|
|
144
|
+
| id | str | "" | API 认证 ID |
|
|
145
|
+
| version | str | "1" | API 版本号 |
|
|
146
|
+
| client_kwargs | dict | None | httpx.Client 额外配置 |
|
|
147
|
+
|
|
148
|
+
#### notify(message, client=None, client_kwargs=None, **kwargs)
|
|
149
|
+
|
|
150
|
+
发送同步通知请求
|
|
151
|
+
|
|
152
|
+
**参数**:
|
|
153
|
+
- `message`: 要发送的内容
|
|
154
|
+
- `client`: 自定义 httpx.Client 实例
|
|
155
|
+
- `client_kwargs`: 客户端配置参数
|
|
156
|
+
- `**kwargs`: 传递给 httpx 请求的额外参数
|
|
157
|
+
|
|
158
|
+
**返回**: `httpx.Response` - HTTP 响应对象
|
|
159
|
+
|
|
160
|
+
#### async_notify(message, client=None, client_kwargs=None, **kwargs)
|
|
161
|
+
|
|
162
|
+
发送异步通知请求
|
|
163
|
+
|
|
164
|
+
**参数**:
|
|
165
|
+
- `message`: 要发送的内容
|
|
166
|
+
- `client`: 自定义 httpx.AsyncClient 实例
|
|
167
|
+
- `client_kwargs`: 客户端配置参数
|
|
168
|
+
- `**kwargs`: 传递给 httpx 请求的额外参数
|
|
169
|
+
|
|
170
|
+
**返回**: `httpx.Response` - HTTP 响应对象
|
|
171
|
+
|
|
172
|
+
### 工具函数
|
|
173
|
+
|
|
174
|
+
#### json_find_first(expression, data)
|
|
175
|
+
|
|
176
|
+
使用 JSONPath 表达式从数据中查找第一个匹配项
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from py_tjbrhk_toolkit.speaker.utils import json_find_first
|
|
180
|
+
|
|
181
|
+
data = {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
|
|
182
|
+
result = json_find_first("$.users[0].name", data)
|
|
183
|
+
print(result) # Alice
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### json_is_valid(schema, data)
|
|
187
|
+
|
|
188
|
+
校验 JSON 数据是否符合指定的 JSON Schema
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from py_tjbrhk_toolkit.speaker.utils import json_is_valid
|
|
192
|
+
|
|
193
|
+
schema = {"type": "object", "properties": {"name": {"type": "string"}}}
|
|
194
|
+
data = {"name": "test"}
|
|
195
|
+
valid = json_is_valid(schema, data)
|
|
196
|
+
print(valid) # True
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### build_success_instance(response)
|
|
200
|
+
|
|
201
|
+
将 HTTP 响应或字典转换为 Success 模型对象
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance
|
|
205
|
+
|
|
206
|
+
response = {"errcode": 0, "errmsg": "success"}
|
|
207
|
+
result = build_success_instance(response)
|
|
208
|
+
print(result.errcode) # 0
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### success_is_valid(response, schema=None)
|
|
212
|
+
|
|
213
|
+
校验 HTTP 响应或字典是否符合成功响应的 JSON Schema
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
from py_tjbrhk_toolkit.speaker.utils import success_is_valid
|
|
217
|
+
|
|
218
|
+
response = {"errcode": 0, "errmsg": "success"}
|
|
219
|
+
valid = success_is_valid(response)
|
|
220
|
+
print(valid) # True
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 响应模型
|
|
224
|
+
|
|
225
|
+
#### Base
|
|
226
|
+
|
|
227
|
+
响应基类,包含错误码和错误信息字段
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from py_tjbrhk_toolkit.speaker.responses import Base
|
|
231
|
+
|
|
232
|
+
response = Base(errcode=0, errmsg="success")
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### Success
|
|
236
|
+
|
|
237
|
+
成功响应模型,继承自 Base
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from py_tjbrhk_toolkit.speaker.responses import Success
|
|
241
|
+
|
|
242
|
+
response = Success(errcode=0, errmsg="success")
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 示例代码
|
|
246
|
+
|
|
247
|
+
### 完整示例
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
251
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance, success_is_valid
|
|
252
|
+
|
|
253
|
+
# 初始化客户端
|
|
254
|
+
client = Speaker(
|
|
255
|
+
token="your_token",
|
|
256
|
+
id="your_id"
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# 发送通知
|
|
260
|
+
response = client.notify(message="测试通知")
|
|
261
|
+
|
|
262
|
+
# 验证响应
|
|
263
|
+
if success_is_valid(response):
|
|
264
|
+
result = build_success_instance(response)
|
|
265
|
+
print(f"发送成功: {result.errmsg}")
|
|
266
|
+
else:
|
|
267
|
+
print("发送失败")
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### 异步完整示例
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
import asyncio
|
|
274
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
275
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance, success_is_valid
|
|
276
|
+
|
|
277
|
+
async def send_notification():
|
|
278
|
+
client = Speaker(
|
|
279
|
+
token="your_token",
|
|
280
|
+
id="your_id"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
response = await client.async_notify(message="异步测试通知")
|
|
284
|
+
|
|
285
|
+
if success_is_valid(response):
|
|
286
|
+
result = build_success_instance(response)
|
|
287
|
+
print(f"发送成功: {result.errmsg}")
|
|
288
|
+
else:
|
|
289
|
+
print("发送失败")
|
|
290
|
+
|
|
291
|
+
asyncio.run(send_notification())
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## 作者
|
|
295
|
+
|
|
296
|
+
Guolei <174000902@qq.com>
|
|
297
|
+
|
|
298
|
+
## 项目主页
|
|
299
|
+
|
|
300
|
+
[https://gitee.com/guolei19850528/py_tjbrhk_toolkit](https://gitee.com/guolei19850528/py_tjbrhk_toolkit)
|
|
301
|
+
|
|
302
|
+
## 官方文档
|
|
303
|
+
|
|
304
|
+
[https://www.yuque.com/lingdutuandui/ugcpag/umbzsd](https://www.yuque.com/lingdutuandui/ugcpag/umbzsd)
|
|
305
|
+
|
|
306
|
+
## 许可证
|
|
307
|
+
|
|
308
|
+
MIT License
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# py-tjbrhk-toolkit
|
|
2
|
+
|
|
3
|
+
天津博瑞皓科 Python 客户端库,提供与天津博瑞皓科 API 交互的完整功能支持。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 支持同步和异步两种请求模式
|
|
8
|
+
- 提供通知发送功能
|
|
9
|
+
- 基于 Pydantic 的数据验证
|
|
10
|
+
- JSONPath 数据查询支持
|
|
11
|
+
- JSON Schema 校验功能
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
### 使用 uv(推荐)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv add py-tjbrhk-toolkit
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 使用 pip
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install py-tjbrhk-toolkit
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## 依赖包
|
|
29
|
+
|
|
30
|
+
| 依赖 | 版本要求 | 说明 |
|
|
31
|
+
|------|----------|------|
|
|
32
|
+
| httpx | >=0.27.0 | HTTP 客户端库 |
|
|
33
|
+
| pydantic | >=2.0 | 数据验证库 |
|
|
34
|
+
| jsonpath-ng | >=1.5.3 | JSONPath 查询库 |
|
|
35
|
+
| jsonschema | >=4.21.0 | JSON Schema 校验库 |
|
|
36
|
+
| py-httpx-toolkit | >=1.0.1 | HTTP 工具库 |
|
|
37
|
+
|
|
38
|
+
## 快速开始
|
|
39
|
+
|
|
40
|
+
### 同步模式
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
44
|
+
|
|
45
|
+
# 初始化客户端
|
|
46
|
+
client = Speaker(
|
|
47
|
+
base_url="https://speaker.17laimai.cn",
|
|
48
|
+
token="your_token",
|
|
49
|
+
id="your_id",
|
|
50
|
+
version="1"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# 发送通知
|
|
54
|
+
response = client.notify(message="Hello World")
|
|
55
|
+
print(response.json())
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 异步模式
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
import asyncio
|
|
62
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
63
|
+
|
|
64
|
+
async def main():
|
|
65
|
+
# 初始化客户端
|
|
66
|
+
client = Speaker(
|
|
67
|
+
base_url="https://speaker.17laimai.cn",
|
|
68
|
+
token="your_token",
|
|
69
|
+
id="your_id",
|
|
70
|
+
version="1"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# 异步发送通知
|
|
74
|
+
response = await client.async_notify(message="Hello World")
|
|
75
|
+
print(response.json())
|
|
76
|
+
|
|
77
|
+
asyncio.run(main())
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API 文档
|
|
81
|
+
|
|
82
|
+
### Speaker 客户端
|
|
83
|
+
|
|
84
|
+
#### 初始化参数
|
|
85
|
+
|
|
86
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
87
|
+
|------|------|--------|------|
|
|
88
|
+
| base_url | str | https://speaker.17laimai.cn | Speaker 服务器地址 |
|
|
89
|
+
| token | str | "" | API 认证 Token |
|
|
90
|
+
| id | str | "" | API 认证 ID |
|
|
91
|
+
| version | str | "1" | API 版本号 |
|
|
92
|
+
| client_kwargs | dict | None | httpx.Client 额外配置 |
|
|
93
|
+
|
|
94
|
+
#### notify(message, client=None, client_kwargs=None, **kwargs)
|
|
95
|
+
|
|
96
|
+
发送同步通知请求
|
|
97
|
+
|
|
98
|
+
**参数**:
|
|
99
|
+
- `message`: 要发送的内容
|
|
100
|
+
- `client`: 自定义 httpx.Client 实例
|
|
101
|
+
- `client_kwargs`: 客户端配置参数
|
|
102
|
+
- `**kwargs`: 传递给 httpx 请求的额外参数
|
|
103
|
+
|
|
104
|
+
**返回**: `httpx.Response` - HTTP 响应对象
|
|
105
|
+
|
|
106
|
+
#### async_notify(message, client=None, client_kwargs=None, **kwargs)
|
|
107
|
+
|
|
108
|
+
发送异步通知请求
|
|
109
|
+
|
|
110
|
+
**参数**:
|
|
111
|
+
- `message`: 要发送的内容
|
|
112
|
+
- `client`: 自定义 httpx.AsyncClient 实例
|
|
113
|
+
- `client_kwargs`: 客户端配置参数
|
|
114
|
+
- `**kwargs`: 传递给 httpx 请求的额外参数
|
|
115
|
+
|
|
116
|
+
**返回**: `httpx.Response` - HTTP 响应对象
|
|
117
|
+
|
|
118
|
+
### 工具函数
|
|
119
|
+
|
|
120
|
+
#### json_find_first(expression, data)
|
|
121
|
+
|
|
122
|
+
使用 JSONPath 表达式从数据中查找第一个匹配项
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from py_tjbrhk_toolkit.speaker.utils import json_find_first
|
|
126
|
+
|
|
127
|
+
data = {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
|
|
128
|
+
result = json_find_first("$.users[0].name", data)
|
|
129
|
+
print(result) # Alice
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### json_is_valid(schema, data)
|
|
133
|
+
|
|
134
|
+
校验 JSON 数据是否符合指定的 JSON Schema
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from py_tjbrhk_toolkit.speaker.utils import json_is_valid
|
|
138
|
+
|
|
139
|
+
schema = {"type": "object", "properties": {"name": {"type": "string"}}}
|
|
140
|
+
data = {"name": "test"}
|
|
141
|
+
valid = json_is_valid(schema, data)
|
|
142
|
+
print(valid) # True
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### build_success_instance(response)
|
|
146
|
+
|
|
147
|
+
将 HTTP 响应或字典转换为 Success 模型对象
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance
|
|
151
|
+
|
|
152
|
+
response = {"errcode": 0, "errmsg": "success"}
|
|
153
|
+
result = build_success_instance(response)
|
|
154
|
+
print(result.errcode) # 0
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### success_is_valid(response, schema=None)
|
|
158
|
+
|
|
159
|
+
校验 HTTP 响应或字典是否符合成功响应的 JSON Schema
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from py_tjbrhk_toolkit.speaker.utils import success_is_valid
|
|
163
|
+
|
|
164
|
+
response = {"errcode": 0, "errmsg": "success"}
|
|
165
|
+
valid = success_is_valid(response)
|
|
166
|
+
print(valid) # True
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 响应模型
|
|
170
|
+
|
|
171
|
+
#### Base
|
|
172
|
+
|
|
173
|
+
响应基类,包含错误码和错误信息字段
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from py_tjbrhk_toolkit.speaker.responses import Base
|
|
177
|
+
|
|
178
|
+
response = Base(errcode=0, errmsg="success")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Success
|
|
182
|
+
|
|
183
|
+
成功响应模型,继承自 Base
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from py_tjbrhk_toolkit.speaker.responses import Success
|
|
187
|
+
|
|
188
|
+
response = Success(errcode=0, errmsg="success")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 示例代码
|
|
192
|
+
|
|
193
|
+
### 完整示例
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
197
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance, success_is_valid
|
|
198
|
+
|
|
199
|
+
# 初始化客户端
|
|
200
|
+
client = Speaker(
|
|
201
|
+
token="your_token",
|
|
202
|
+
id="your_id"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# 发送通知
|
|
206
|
+
response = client.notify(message="测试通知")
|
|
207
|
+
|
|
208
|
+
# 验证响应
|
|
209
|
+
if success_is_valid(response):
|
|
210
|
+
result = build_success_instance(response)
|
|
211
|
+
print(f"发送成功: {result.errmsg}")
|
|
212
|
+
else:
|
|
213
|
+
print("发送失败")
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 异步完整示例
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
import asyncio
|
|
220
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
221
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance, success_is_valid
|
|
222
|
+
|
|
223
|
+
async def send_notification():
|
|
224
|
+
client = Speaker(
|
|
225
|
+
token="your_token",
|
|
226
|
+
id="your_id"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
response = await client.async_notify(message="异步测试通知")
|
|
230
|
+
|
|
231
|
+
if success_is_valid(response):
|
|
232
|
+
result = build_success_instance(response)
|
|
233
|
+
print(f"发送成功: {result.errmsg}")
|
|
234
|
+
else:
|
|
235
|
+
print("发送失败")
|
|
236
|
+
|
|
237
|
+
asyncio.run(send_notification())
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## 作者
|
|
241
|
+
|
|
242
|
+
Guolei <174000902@qq.com>
|
|
243
|
+
|
|
244
|
+
## 项目主页
|
|
245
|
+
|
|
246
|
+
[https://gitee.com/guolei19850528/py_tjbrhk_toolkit](https://gitee.com/guolei19850528/py_tjbrhk_toolkit)
|
|
247
|
+
|
|
248
|
+
## 官方文档
|
|
249
|
+
|
|
250
|
+
[https://www.yuque.com/lingdutuandui/ugcpag/umbzsd](https://www.yuque.com/lingdutuandui/ugcpag/umbzsd)
|
|
251
|
+
|
|
252
|
+
## 许可证
|
|
253
|
+
|
|
254
|
+
MIT License
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
[project]
|
|
5
|
+
name = "py-tjbrhk-toolkit"
|
|
6
|
+
version = "1.0.0"
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Guolei", email = "174000902@qq.com" }
|
|
10
|
+
]
|
|
11
|
+
description = "一个用于与天津博瑞皓科 API 交互的 Python 客户端库"
|
|
12
|
+
keywords = ["天津博瑞皓科", "tjbrhk", "python", "client","智能云音箱", "api"]
|
|
13
|
+
license = { file = "LICENSE" }
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"httpx>=0.27.0",
|
|
28
|
+
"pydantic>=2.0",
|
|
29
|
+
"jsonpath-ng>=1.5.3",
|
|
30
|
+
"jsonschema>=4.21.0",
|
|
31
|
+
"py-httpx-toolkit>=1.0.1",
|
|
32
|
+
]
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
dev = [
|
|
35
|
+
"pytest>=7.0",
|
|
36
|
+
"pytest-cov>=4.0",
|
|
37
|
+
"setuptools>=61.0",
|
|
38
|
+
"twine>=4.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
"Homepage" = "https://gitee.com/guolei19850528/py_tjbrhk_toolkit"
|
|
43
|
+
"Repository" = "https://gitee.com/guolei19850528/py_tjbrhk_toolkit.git"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["src"]
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: UTF-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
天津博瑞皓科 Speaker 客户端库
|
|
5
|
+
|
|
6
|
+
提供与天津博瑞皓科 Speaker API 交互的 Python 客户端实现。
|
|
7
|
+
支持同步和异步两种请求模式,提供通知发送功能。
|
|
8
|
+
|
|
9
|
+
官方文档: https://www.yuque.com/lingdutuandui/ugcpag/umbzsd
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
from pydantic import HttpUrl
|
|
16
|
+
|
|
17
|
+
from py_httpx_toolkit import Httpx
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Speaker(Httpx):
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
base_url: Optional[str] = "https://speaker.17laimai.cn",
|
|
24
|
+
token: Optional[str] = "",
|
|
25
|
+
id: Optional[str] = "",
|
|
26
|
+
version: Optional[str] = "1",
|
|
27
|
+
client_kwargs: Optional[dict] = None,
|
|
28
|
+
):
|
|
29
|
+
"""
|
|
30
|
+
初始化 Speaker 客户端
|
|
31
|
+
|
|
32
|
+
创建与 Speaker 交互的客户端实例,配置连接参数和认证密钥。
|
|
33
|
+
|
|
34
|
+
参数:
|
|
35
|
+
base_url (Optional[HttpUrl]): Speaker 服务器地址,如 "https://speaker.17laimai.cn"
|
|
36
|
+
token (Optional[str]): Token,用于 API 认证
|
|
37
|
+
id (Optional[str]): ID,用于 API 认证
|
|
38
|
+
version (Optional[str]): 版本号,用于 API 认证
|
|
39
|
+
client_kwargs (Optional[dict]): 传递给 httpx.Client 的额外配置参数
|
|
40
|
+
|
|
41
|
+
配置说明:
|
|
42
|
+
- base_url 会自动去除末尾的斜杠
|
|
43
|
+
- 默认配置: base_url=base_url, verify=False, timeout=60
|
|
44
|
+
- client_kwargs 中的参数会覆盖默认配置
|
|
45
|
+
"""
|
|
46
|
+
self.base_url = base_url or ""
|
|
47
|
+
self.base_url = self.base_url[:-1] if self.base_url.endswith("/") else self.base_url
|
|
48
|
+
self.token = token or ""
|
|
49
|
+
self.id = id or ""
|
|
50
|
+
self.version = version or "1"
|
|
51
|
+
self.client_kwargs = client_kwargs or {}
|
|
52
|
+
self.client_kwargs = {
|
|
53
|
+
**{
|
|
54
|
+
"base_url": self.base_url,
|
|
55
|
+
"verify": False,
|
|
56
|
+
"timeout": 60,
|
|
57
|
+
},
|
|
58
|
+
**self.client_kwargs,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
def notify(
|
|
62
|
+
self,
|
|
63
|
+
message: str = "",
|
|
64
|
+
client: Optional[httpx.Client] = None,
|
|
65
|
+
client_kwargs: Optional[dict] = None,
|
|
66
|
+
**kwargs
|
|
67
|
+
) -> httpx.Response:
|
|
68
|
+
"""
|
|
69
|
+
发送同步 HTTP 请求
|
|
70
|
+
|
|
71
|
+
支持传入自定义客户端或使用内置客户端。
|
|
72
|
+
|
|
73
|
+
参数:
|
|
74
|
+
client (Optional[httpx.Client]): 自定义的 httpx.Client 实例,若为 None 则自动创建
|
|
75
|
+
message (str): 要发送的内容,将作为 POST 请求体的 message 字段发送
|
|
76
|
+
**kwargs: 传递给 httpx.Client.request 的参数,包括 method、url、headers、data、json 等
|
|
77
|
+
|
|
78
|
+
返回:
|
|
79
|
+
httpx.Response: HTTP 响应对象
|
|
80
|
+
"""
|
|
81
|
+
client = client or None
|
|
82
|
+
client_kwargs = client_kwargs or {}
|
|
83
|
+
kwargs = kwargs or {}
|
|
84
|
+
kwargs = {
|
|
85
|
+
**{
|
|
86
|
+
"method": "POST",
|
|
87
|
+
"url": "/notify.php",
|
|
88
|
+
"data": {
|
|
89
|
+
"token": self.token,
|
|
90
|
+
"id": self.id,
|
|
91
|
+
"version": self.version,
|
|
92
|
+
"message": message,
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
**kwargs
|
|
96
|
+
}
|
|
97
|
+
return self.request(client=client, client_kwargs=client_kwargs, **kwargs)
|
|
98
|
+
|
|
99
|
+
async def async_notify(
|
|
100
|
+
self,
|
|
101
|
+
message: str = "",
|
|
102
|
+
client: Optional[httpx.AsyncClient] = None,
|
|
103
|
+
client_kwargs: Optional[dict] = None,
|
|
104
|
+
**kwargs
|
|
105
|
+
) -> httpx.Response:
|
|
106
|
+
"""
|
|
107
|
+
发送异步 HTTP 请求
|
|
108
|
+
|
|
109
|
+
支持传入自定义客户端或使用内置客户端。
|
|
110
|
+
|
|
111
|
+
参数:
|
|
112
|
+
client (Optional[httpx.AsyncClient]): 自定义的 httpx.AsyncClient 实例,若为 None 则自动创建
|
|
113
|
+
message (str): 要发送的内容,将作为 POST 请求体的 message 字段发送
|
|
114
|
+
**kwargs: 传递给 httpx.Client.request 的参数,包括 method、url、headers、data、json 等
|
|
115
|
+
|
|
116
|
+
返回:
|
|
117
|
+
httpx.Response: HTTP 响应对象
|
|
118
|
+
"""
|
|
119
|
+
client = client or None
|
|
120
|
+
client_kwargs = client_kwargs or {}
|
|
121
|
+
kwargs = kwargs or {}
|
|
122
|
+
kwargs = {
|
|
123
|
+
**{
|
|
124
|
+
"method": "POST",
|
|
125
|
+
"url": "/notify.php",
|
|
126
|
+
"data": {
|
|
127
|
+
"token": self.token,
|
|
128
|
+
"id": self.id,
|
|
129
|
+
"version": self.version,
|
|
130
|
+
"message": message,
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
**kwargs
|
|
134
|
+
}
|
|
135
|
+
return await self.async_request(client=client, client_kwargs=client_kwargs, **kwargs)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: UTF-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
响应模型模块
|
|
5
|
+
|
|
6
|
+
定义 API 响应的数据模型,基于 Pydantic 实现数据验证和类型提示。
|
|
7
|
+
|
|
8
|
+
官方文档: https://www.yuque.com/lingdutuandui/ugcpag/umbzsd
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
from pydantic import Field
|
|
13
|
+
from typing import Literal, Union, Any, Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Base(BaseModel):
|
|
17
|
+
"""
|
|
18
|
+
iSecure Center响应基类
|
|
19
|
+
|
|
20
|
+
所有API响应都包含错误码和错误信息字段
|
|
21
|
+
"""
|
|
22
|
+
errcode: Union[int, str] = Field(..., title="错误码", description="错误码,0表示成功,非0表示失败")
|
|
23
|
+
errmsg: Optional[str] = Field(default=None, title="错误信息", description="错误信息描述")
|
|
24
|
+
|
|
25
|
+
model_config = {
|
|
26
|
+
"extra": "allow" # 允许额外动态字段
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Success(Base):
|
|
31
|
+
"""
|
|
32
|
+
成功响应模型
|
|
33
|
+
|
|
34
|
+
继承自Base,用于成功接口的响应
|
|
35
|
+
"""
|
|
36
|
+
errcode: Literal[0, "0"] = Field(..., title="错误码", description="成功,值为0")
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: UTF-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
工具函数模块
|
|
5
|
+
|
|
6
|
+
提供 JSON 数据处理、数据校验等通用工具函数。
|
|
7
|
+
|
|
8
|
+
官方文档: https://www.yuque.com/lingdutuandui/ugcpag/umbzsd
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import base64
|
|
12
|
+
import hashlib
|
|
13
|
+
import uuid
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
from typing import Any, Optional, Tuple, Union
|
|
16
|
+
|
|
17
|
+
import httpx
|
|
18
|
+
from jsonpath_ng import parse
|
|
19
|
+
from jsonschema.validators import Draft202012Validator
|
|
20
|
+
|
|
21
|
+
from .responses import Success
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def json_find_first(expression: str, data: Any) -> Any:
|
|
25
|
+
"""
|
|
26
|
+
使用 JSONPath 表达式从数据中查找第一个匹配项
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
expression: JSONPath 表达式,用于指定要查找的数据路径
|
|
30
|
+
data: 待查询的 JSON 数据
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Any: 第一个匹配的值,如果没有匹配项则返回 None
|
|
34
|
+
"""
|
|
35
|
+
results = [i.value for i in parse(expression).find(data)]
|
|
36
|
+
if isinstance(results, list) and len(results) > 0:
|
|
37
|
+
return results[0]
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def json_is_valid(schema: Optional[dict], data: Any) -> bool:
|
|
42
|
+
"""
|
|
43
|
+
校验 JSON 数据是否符合指定的 JSON Schema
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
schema: JSON Schema 字典
|
|
47
|
+
data: 待校验的 JSON 数据
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
bool: 校验是否成功
|
|
51
|
+
"""
|
|
52
|
+
return Draft202012Validator(schema).is_valid(data)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def build_success_instance(response: Union[httpx.Response, dict]) -> Success:
|
|
56
|
+
"""
|
|
57
|
+
将 HTTP 响应或字典转换为 Success 模型对象
|
|
58
|
+
|
|
59
|
+
统一处理 httpx.Response 对象和字典,将其转换为标准化的 Success 模型对象。
|
|
60
|
+
|
|
61
|
+
参数:
|
|
62
|
+
response (Union[httpx.Response, dict]): HTTP 响应对象或字典数据
|
|
63
|
+
|
|
64
|
+
返回:
|
|
65
|
+
Success: 标准化的响应模型对象,包含 errcode 和 errmsg 字段
|
|
66
|
+
|
|
67
|
+
处理逻辑:
|
|
68
|
+
- 如果输入是 httpx.Response 对象,先调用 json() 方法解析响应体
|
|
69
|
+
- 如果输入是字典,直接传入 Success 构造函数
|
|
70
|
+
"""
|
|
71
|
+
if isinstance(response, httpx.Response):
|
|
72
|
+
return Success(**response.json())
|
|
73
|
+
return Success(**response)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def success_is_valid(
|
|
77
|
+
response: Union[httpx.Response, dict] = None,
|
|
78
|
+
schema: dict = {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"properties": {
|
|
81
|
+
"errcode": {
|
|
82
|
+
"oneOf": [
|
|
83
|
+
{"type": "integer", "const": 0},
|
|
84
|
+
{"type": "string", "const": "0"}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"required": ["errcode"]
|
|
89
|
+
}
|
|
90
|
+
):
|
|
91
|
+
"""
|
|
92
|
+
校验 HTTP 响应或字典是否符合指定的 JSON Schema
|
|
93
|
+
|
|
94
|
+
:param response: HTTP 响应对象或字典数据
|
|
95
|
+
:param schema: JSON Schema 字典
|
|
96
|
+
:return: 校验是否成功
|
|
97
|
+
"""
|
|
98
|
+
if isinstance(response, httpx.Response):
|
|
99
|
+
return json_is_valid(schema, response.json())
|
|
100
|
+
return json_is_valid(schema, response)
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py-tjbrhk-toolkit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: 一个用于与天津博瑞皓科 API 交互的 Python 客户端库
|
|
5
|
+
Author-email: Guolei <174000902@qq.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 郭磊
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://gitee.com/guolei19850528/py_tjbrhk_toolkit
|
|
29
|
+
Project-URL: Repository, https://gitee.com/guolei19850528/py_tjbrhk_toolkit.git
|
|
30
|
+
Keywords: 天津博瑞皓科,tjbrhk,python,client,智能云音箱,api
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: httpx>=0.27.0
|
|
44
|
+
Requires-Dist: pydantic>=2.0
|
|
45
|
+
Requires-Dist: jsonpath-ng>=1.5.3
|
|
46
|
+
Requires-Dist: jsonschema>=4.21.0
|
|
47
|
+
Requires-Dist: py-httpx-toolkit>=1.0.1
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
50
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
51
|
+
Requires-Dist: setuptools>=61.0; extra == "dev"
|
|
52
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# py-tjbrhk-toolkit
|
|
56
|
+
|
|
57
|
+
天津博瑞皓科 Python 客户端库,提供与天津博瑞皓科 API 交互的完整功能支持。
|
|
58
|
+
|
|
59
|
+
## 特性
|
|
60
|
+
|
|
61
|
+
- 支持同步和异步两种请求模式
|
|
62
|
+
- 提供通知发送功能
|
|
63
|
+
- 基于 Pydantic 的数据验证
|
|
64
|
+
- JSONPath 数据查询支持
|
|
65
|
+
- JSON Schema 校验功能
|
|
66
|
+
|
|
67
|
+
## 安装
|
|
68
|
+
|
|
69
|
+
### 使用 uv(推荐)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv add py-tjbrhk-toolkit
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 使用 pip
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install py-tjbrhk-toolkit
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## 依赖包
|
|
83
|
+
|
|
84
|
+
| 依赖 | 版本要求 | 说明 |
|
|
85
|
+
|------|----------|------|
|
|
86
|
+
| httpx | >=0.27.0 | HTTP 客户端库 |
|
|
87
|
+
| pydantic | >=2.0 | 数据验证库 |
|
|
88
|
+
| jsonpath-ng | >=1.5.3 | JSONPath 查询库 |
|
|
89
|
+
| jsonschema | >=4.21.0 | JSON Schema 校验库 |
|
|
90
|
+
| py-httpx-toolkit | >=1.0.1 | HTTP 工具库 |
|
|
91
|
+
|
|
92
|
+
## 快速开始
|
|
93
|
+
|
|
94
|
+
### 同步模式
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
98
|
+
|
|
99
|
+
# 初始化客户端
|
|
100
|
+
client = Speaker(
|
|
101
|
+
base_url="https://speaker.17laimai.cn",
|
|
102
|
+
token="your_token",
|
|
103
|
+
id="your_id",
|
|
104
|
+
version="1"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# 发送通知
|
|
108
|
+
response = client.notify(message="Hello World")
|
|
109
|
+
print(response.json())
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 异步模式
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import asyncio
|
|
116
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
117
|
+
|
|
118
|
+
async def main():
|
|
119
|
+
# 初始化客户端
|
|
120
|
+
client = Speaker(
|
|
121
|
+
base_url="https://speaker.17laimai.cn",
|
|
122
|
+
token="your_token",
|
|
123
|
+
id="your_id",
|
|
124
|
+
version="1"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# 异步发送通知
|
|
128
|
+
response = await client.async_notify(message="Hello World")
|
|
129
|
+
print(response.json())
|
|
130
|
+
|
|
131
|
+
asyncio.run(main())
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## API 文档
|
|
135
|
+
|
|
136
|
+
### Speaker 客户端
|
|
137
|
+
|
|
138
|
+
#### 初始化参数
|
|
139
|
+
|
|
140
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
141
|
+
|------|------|--------|------|
|
|
142
|
+
| base_url | str | https://speaker.17laimai.cn | Speaker 服务器地址 |
|
|
143
|
+
| token | str | "" | API 认证 Token |
|
|
144
|
+
| id | str | "" | API 认证 ID |
|
|
145
|
+
| version | str | "1" | API 版本号 |
|
|
146
|
+
| client_kwargs | dict | None | httpx.Client 额外配置 |
|
|
147
|
+
|
|
148
|
+
#### notify(message, client=None, client_kwargs=None, **kwargs)
|
|
149
|
+
|
|
150
|
+
发送同步通知请求
|
|
151
|
+
|
|
152
|
+
**参数**:
|
|
153
|
+
- `message`: 要发送的内容
|
|
154
|
+
- `client`: 自定义 httpx.Client 实例
|
|
155
|
+
- `client_kwargs`: 客户端配置参数
|
|
156
|
+
- `**kwargs`: 传递给 httpx 请求的额外参数
|
|
157
|
+
|
|
158
|
+
**返回**: `httpx.Response` - HTTP 响应对象
|
|
159
|
+
|
|
160
|
+
#### async_notify(message, client=None, client_kwargs=None, **kwargs)
|
|
161
|
+
|
|
162
|
+
发送异步通知请求
|
|
163
|
+
|
|
164
|
+
**参数**:
|
|
165
|
+
- `message`: 要发送的内容
|
|
166
|
+
- `client`: 自定义 httpx.AsyncClient 实例
|
|
167
|
+
- `client_kwargs`: 客户端配置参数
|
|
168
|
+
- `**kwargs`: 传递给 httpx 请求的额外参数
|
|
169
|
+
|
|
170
|
+
**返回**: `httpx.Response` - HTTP 响应对象
|
|
171
|
+
|
|
172
|
+
### 工具函数
|
|
173
|
+
|
|
174
|
+
#### json_find_first(expression, data)
|
|
175
|
+
|
|
176
|
+
使用 JSONPath 表达式从数据中查找第一个匹配项
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from py_tjbrhk_toolkit.speaker.utils import json_find_first
|
|
180
|
+
|
|
181
|
+
data = {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
|
|
182
|
+
result = json_find_first("$.users[0].name", data)
|
|
183
|
+
print(result) # Alice
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### json_is_valid(schema, data)
|
|
187
|
+
|
|
188
|
+
校验 JSON 数据是否符合指定的 JSON Schema
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from py_tjbrhk_toolkit.speaker.utils import json_is_valid
|
|
192
|
+
|
|
193
|
+
schema = {"type": "object", "properties": {"name": {"type": "string"}}}
|
|
194
|
+
data = {"name": "test"}
|
|
195
|
+
valid = json_is_valid(schema, data)
|
|
196
|
+
print(valid) # True
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### build_success_instance(response)
|
|
200
|
+
|
|
201
|
+
将 HTTP 响应或字典转换为 Success 模型对象
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance
|
|
205
|
+
|
|
206
|
+
response = {"errcode": 0, "errmsg": "success"}
|
|
207
|
+
result = build_success_instance(response)
|
|
208
|
+
print(result.errcode) # 0
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### success_is_valid(response, schema=None)
|
|
212
|
+
|
|
213
|
+
校验 HTTP 响应或字典是否符合成功响应的 JSON Schema
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
from py_tjbrhk_toolkit.speaker.utils import success_is_valid
|
|
217
|
+
|
|
218
|
+
response = {"errcode": 0, "errmsg": "success"}
|
|
219
|
+
valid = success_is_valid(response)
|
|
220
|
+
print(valid) # True
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 响应模型
|
|
224
|
+
|
|
225
|
+
#### Base
|
|
226
|
+
|
|
227
|
+
响应基类,包含错误码和错误信息字段
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from py_tjbrhk_toolkit.speaker.responses import Base
|
|
231
|
+
|
|
232
|
+
response = Base(errcode=0, errmsg="success")
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### Success
|
|
236
|
+
|
|
237
|
+
成功响应模型,继承自 Base
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from py_tjbrhk_toolkit.speaker.responses import Success
|
|
241
|
+
|
|
242
|
+
response = Success(errcode=0, errmsg="success")
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 示例代码
|
|
246
|
+
|
|
247
|
+
### 完整示例
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
251
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance, success_is_valid
|
|
252
|
+
|
|
253
|
+
# 初始化客户端
|
|
254
|
+
client = Speaker(
|
|
255
|
+
token="your_token",
|
|
256
|
+
id="your_id"
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# 发送通知
|
|
260
|
+
response = client.notify(message="测试通知")
|
|
261
|
+
|
|
262
|
+
# 验证响应
|
|
263
|
+
if success_is_valid(response):
|
|
264
|
+
result = build_success_instance(response)
|
|
265
|
+
print(f"发送成功: {result.errmsg}")
|
|
266
|
+
else:
|
|
267
|
+
print("发送失败")
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### 异步完整示例
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
import asyncio
|
|
274
|
+
from py_tjbrhk_toolkit.speaker import Speaker
|
|
275
|
+
from py_tjbrhk_toolkit.speaker.utils import build_success_instance, success_is_valid
|
|
276
|
+
|
|
277
|
+
async def send_notification():
|
|
278
|
+
client = Speaker(
|
|
279
|
+
token="your_token",
|
|
280
|
+
id="your_id"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
response = await client.async_notify(message="异步测试通知")
|
|
284
|
+
|
|
285
|
+
if success_is_valid(response):
|
|
286
|
+
result = build_success_instance(response)
|
|
287
|
+
print(f"发送成功: {result.errmsg}")
|
|
288
|
+
else:
|
|
289
|
+
print("发送失败")
|
|
290
|
+
|
|
291
|
+
asyncio.run(send_notification())
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## 作者
|
|
295
|
+
|
|
296
|
+
Guolei <174000902@qq.com>
|
|
297
|
+
|
|
298
|
+
## 项目主页
|
|
299
|
+
|
|
300
|
+
[https://gitee.com/guolei19850528/py_tjbrhk_toolkit](https://gitee.com/guolei19850528/py_tjbrhk_toolkit)
|
|
301
|
+
|
|
302
|
+
## 官方文档
|
|
303
|
+
|
|
304
|
+
[https://www.yuque.com/lingdutuandui/ugcpag/umbzsd](https://www.yuque.com/lingdutuandui/ugcpag/umbzsd)
|
|
305
|
+
|
|
306
|
+
## 许可证
|
|
307
|
+
|
|
308
|
+
MIT License
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/py_tjbrhk_toolkit/__init__.py
|
|
5
|
+
src/py_tjbrhk_toolkit.egg-info/PKG-INFO
|
|
6
|
+
src/py_tjbrhk_toolkit.egg-info/SOURCES.txt
|
|
7
|
+
src/py_tjbrhk_toolkit.egg-info/dependency_links.txt
|
|
8
|
+
src/py_tjbrhk_toolkit.egg-info/requires.txt
|
|
9
|
+
src/py_tjbrhk_toolkit.egg-info/top_level.txt
|
|
10
|
+
src/py_tjbrhk_toolkit/speaker/__init__.py
|
|
11
|
+
src/py_tjbrhk_toolkit/speaker/responses.py
|
|
12
|
+
src/py_tjbrhk_toolkit/speaker/utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
py_tjbrhk_toolkit
|