xiaozhi-sdk 0.0.3__tar.gz → 0.0.5__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.
- {xiaozhi_sdk-0.0.3/xiaozhi_sdk.egg-info → xiaozhi_sdk-0.0.5}/PKG-INFO +6 -15
- xiaozhi_sdk-0.0.5/pyproject.toml +64 -0
- xiaozhi_sdk-0.0.5/setup.cfg +4 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/tests/test_iot.py +4 -2
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/__init__.py +10 -3
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/__main__.py +11 -0
- xiaozhi_sdk-0.0.5/xiaozhi_sdk/config.py +3 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/iot.py +4 -1
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5/xiaozhi_sdk.egg-info}/PKG-INFO +6 -15
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk.egg-info/SOURCES.txt +1 -2
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk.egg-info/requires.txt +1 -1
- xiaozhi_sdk-0.0.3/setup.cfg +0 -17
- xiaozhi_sdk-0.0.3/setup.py +0 -60
- xiaozhi_sdk-0.0.3/xiaozhi_sdk/config.py +0 -3
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/LICENSE +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/MANIFEST.in +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/README.md +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/audio/greet.wav +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/audio/say_hello.wav +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/audio/take_photo.wav +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/image/leijun.jpg +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/opus/linux-arm64-libopus.so +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/opus/linux-x64-libopus.so +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/opus/macos-arm64-libopus.dylib +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/opus/macos-x64-libopus.dylib +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/file/opus/windows-x86_64-opus.dll +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/tests/test_opus.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/tests/test_pic.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/tests/test_xiaozhi.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/data.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/mcp.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/opus.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk/utils.py +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk.egg-info/dependency_links.txt +0 -0
- {xiaozhi_sdk-0.0.3 → xiaozhi_sdk-0.0.5}/xiaozhi_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,34 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xiaozhi-sdk
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: 一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: dairoot <623815825@qq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dairoot/xiaozhi-sdk
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.8
|
|
11
|
+
Requires-Python: >=3.8.1
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: numpy
|
|
15
|
-
Requires-Dist: websockets
|
|
15
|
+
Requires-Dist: websockets>=15.0.1
|
|
16
16
|
Requires-Dist: aiohttp
|
|
17
17
|
Requires-Dist: av
|
|
18
18
|
Requires-Dist: opuslib
|
|
19
19
|
Requires-Dist: requests
|
|
20
20
|
Requires-Dist: sounddevice
|
|
21
21
|
Requires-Dist: python-socks
|
|
22
|
-
Dynamic: author
|
|
23
|
-
Dynamic: author-email
|
|
24
|
-
Dynamic: classifier
|
|
25
|
-
Dynamic: description
|
|
26
|
-
Dynamic: description-content-type
|
|
27
|
-
Dynamic: home-page
|
|
28
22
|
Dynamic: license-file
|
|
29
|
-
Dynamic: requires-dist
|
|
30
|
-
Dynamic: requires-python
|
|
31
|
-
Dynamic: summary
|
|
32
23
|
|
|
33
24
|
# 小智SDK (XiaoZhi SDK)
|
|
34
25
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "xiaozhi-sdk"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{name = "dairoot", email = "623815825@qq.com"}]
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
requires-python = ">=3.8.1"
|
|
13
|
+
dependencies = [
|
|
14
|
+
"numpy",
|
|
15
|
+
"websockets>=15.0.1",
|
|
16
|
+
"aiohttp",
|
|
17
|
+
"av",
|
|
18
|
+
"opuslib",
|
|
19
|
+
"requests",
|
|
20
|
+
"sounddevice",
|
|
21
|
+
"python-socks",
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/dairoot/xiaozhi-sdk"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.dynamic]
|
|
35
|
+
version = {attr = "xiaozhi_sdk.__version__"}
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.packages.find]
|
|
38
|
+
include = ["xiaozhi_sdk*"]
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.package-data]
|
|
41
|
+
xiaozhi_sdk = ["../file/**/*"]
|
|
42
|
+
|
|
43
|
+
# 保留现有的工具配置
|
|
44
|
+
[tool.coverage.run]
|
|
45
|
+
omit = [
|
|
46
|
+
"xiaozhi_sdk/__main__.py",
|
|
47
|
+
"tests/*",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[dependency-groups]
|
|
51
|
+
dev = [
|
|
52
|
+
"black>=24.8.0",
|
|
53
|
+
"flake8>=5.0.4",
|
|
54
|
+
"flake8-bugbear",
|
|
55
|
+
"flake8-comprehensions",
|
|
56
|
+
"isort>=5.13.2",
|
|
57
|
+
"mypy>=1.14.1",
|
|
58
|
+
"types-requests",
|
|
59
|
+
"pre-commit>=3.5.0",
|
|
60
|
+
"pytest>=8.3.5",
|
|
61
|
+
"pytest-asyncio",
|
|
62
|
+
"pytest-cov",
|
|
63
|
+
"build>=0.10",
|
|
64
|
+
]
|
|
@@ -13,8 +13,10 @@ from xiaozhi_sdk.iot import OtaDevice
|
|
|
13
13
|
async def test_main():
|
|
14
14
|
serial_number = ""
|
|
15
15
|
license_key = ""
|
|
16
|
-
mac_address = "
|
|
17
|
-
|
|
16
|
+
mac_address = ""
|
|
17
|
+
ota_url = "http://localhost:3080/api/ota"
|
|
18
|
+
ota_url = None
|
|
19
|
+
ota = OtaDevice(mac_addr=mac_address, client_id=str(uuid.uuid4()), serial_number=serial_number, ota_url=ota_url)
|
|
18
20
|
res = await ota.activate_device()
|
|
19
21
|
if not res.get("activation"):
|
|
20
22
|
return
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.5"
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import json
|
|
@@ -147,6 +147,7 @@ class XiaoZhiWebsocket(McpTool):
|
|
|
147
147
|
await self.message_handler_callback(
|
|
148
148
|
{"type": "websocket", "state": "close", "source": "sdk.message_handler"}
|
|
149
149
|
)
|
|
150
|
+
logger.info("[websocket] close")
|
|
150
151
|
|
|
151
152
|
async def set_mcp_tool_callback(self, tool_func: Dict[str, Callable[..., Any]]) -> None:
|
|
152
153
|
"""设置MCP工具回调函数"""
|
|
@@ -165,11 +166,15 @@ class XiaoZhiWebsocket(McpTool):
|
|
|
165
166
|
|
|
166
167
|
self.ota = OtaDevice(self.mac_addr, self.client_id, self.ota_url, serial_number)
|
|
167
168
|
ota_info = await self.ota.activate_device()
|
|
168
|
-
ws_url = ota_info
|
|
169
|
+
ws_url = ota_info.get("websocket", {}).get("url")
|
|
169
170
|
self.url = self.url or ws_url
|
|
170
171
|
|
|
172
|
+
if not self.url:
|
|
173
|
+
logger.warning("[websocket] 未找到websocket链接地址")
|
|
174
|
+
return
|
|
175
|
+
|
|
171
176
|
if "tenclass.net" not in self.url and "xiaozhi.me" not in self.url:
|
|
172
|
-
logger.warning("[websocket]
|
|
177
|
+
logger.warning("[websocket] 检测到非官方服务器,当前链接地址: %s", self.url)
|
|
173
178
|
|
|
174
179
|
headers = {
|
|
175
180
|
"Authorization": "Bearer {}".format(ota_info["websocket"]["token"]),
|
|
@@ -202,6 +207,8 @@ class XiaoZhiWebsocket(McpTool):
|
|
|
202
207
|
if self.message_handler_callback:
|
|
203
208
|
await self.message_handler_callback({"type": "websocket", "state": "close", "source": "sdk.send_audio"})
|
|
204
209
|
self.websocket = None
|
|
210
|
+
logger.info("[websocket] close")
|
|
211
|
+
|
|
205
212
|
await asyncio.sleep(0.5)
|
|
206
213
|
else:
|
|
207
214
|
await asyncio.sleep(0.1)
|
|
@@ -20,11 +20,15 @@ logger = logging.getLogger("xiaozhi_sdk")
|
|
|
20
20
|
# 全局状态
|
|
21
21
|
input_audio_buffer: deque[bytes] = deque()
|
|
22
22
|
is_playing_audio = False
|
|
23
|
+
is_end = False
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
async def handle_message(message):
|
|
26
27
|
"""处理接收到的消息"""
|
|
28
|
+
global is_end
|
|
27
29
|
logger.info("message received: %s", message)
|
|
30
|
+
if message["type"] == "websocket" and message["state"] == "close":
|
|
31
|
+
is_end = True
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
async def play_assistant_audio(audio_queue: deque[bytes]):
|
|
@@ -36,6 +40,9 @@ async def play_assistant_audio(audio_queue: deque[bytes]):
|
|
|
36
40
|
last_audio_time = None
|
|
37
41
|
|
|
38
42
|
while True:
|
|
43
|
+
if is_end:
|
|
44
|
+
return
|
|
45
|
+
|
|
39
46
|
if not audio_queue:
|
|
40
47
|
await asyncio.sleep(0.01)
|
|
41
48
|
if last_audio_time and time.time() - last_audio_time > 1:
|
|
@@ -77,6 +84,10 @@ class XiaoZhiClient:
|
|
|
77
84
|
async def process_audio_input(self):
|
|
78
85
|
"""处理音频输入"""
|
|
79
86
|
while True:
|
|
87
|
+
|
|
88
|
+
if is_end:
|
|
89
|
+
return
|
|
90
|
+
|
|
80
91
|
if not input_audio_buffer:
|
|
81
92
|
await asyncio.sleep(0.02)
|
|
82
93
|
continue
|
|
@@ -29,6 +29,8 @@ class OtaDevice:
|
|
|
29
29
|
|
|
30
30
|
def __init__(self, mac_addr: str, client_id: str, ota_url: Optional[str] = None, serial_number: str = "") -> None:
|
|
31
31
|
self.ota_url = ota_url or OTA_URL
|
|
32
|
+
self.ota_url = self.ota_url.rstrip("/")
|
|
33
|
+
|
|
32
34
|
self.mac_addr = mac_addr
|
|
33
35
|
self.client_id = client_id
|
|
34
36
|
self.serial_number = serial_number
|
|
@@ -54,12 +56,13 @@ class OtaDevice:
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
async with aiohttp.ClientSession() as session:
|
|
57
|
-
async with session.post(self.ota_url, headers=headers, data=json.dumps(payload)) as response:
|
|
59
|
+
async with session.post(self.ota_url + "/", headers=headers, data=json.dumps(payload)) as response:
|
|
58
60
|
response.raise_for_status()
|
|
59
61
|
return await response.json()
|
|
60
62
|
|
|
61
63
|
async def check_activate(self, challenge: str, license_key: str = "") -> bool:
|
|
62
64
|
url = f"{self.ota_url}/activate"
|
|
65
|
+
|
|
63
66
|
headers = self._get_base_headers()
|
|
64
67
|
|
|
65
68
|
hmac_instance = hmac.new(license_key.encode(), challenge.encode(), hashlib.sha256)
|
|
@@ -1,34 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xiaozhi-sdk
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: 一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: dairoot <623815825@qq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dairoot/xiaozhi-sdk
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.8
|
|
11
|
+
Requires-Python: >=3.8.1
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: numpy
|
|
15
|
-
Requires-Dist: websockets
|
|
15
|
+
Requires-Dist: websockets>=15.0.1
|
|
16
16
|
Requires-Dist: aiohttp
|
|
17
17
|
Requires-Dist: av
|
|
18
18
|
Requires-Dist: opuslib
|
|
19
19
|
Requires-Dist: requests
|
|
20
20
|
Requires-Dist: sounddevice
|
|
21
21
|
Requires-Dist: python-socks
|
|
22
|
-
Dynamic: author
|
|
23
|
-
Dynamic: author-email
|
|
24
|
-
Dynamic: classifier
|
|
25
|
-
Dynamic: description
|
|
26
|
-
Dynamic: description-content-type
|
|
27
|
-
Dynamic: home-page
|
|
28
22
|
Dynamic: license-file
|
|
29
|
-
Dynamic: requires-dist
|
|
30
|
-
Dynamic: requires-python
|
|
31
|
-
Dynamic: summary
|
|
32
23
|
|
|
33
24
|
# 小智SDK (XiaoZhi SDK)
|
|
34
25
|
|
xiaozhi_sdk-0.0.3/setup.cfg
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
[flake8]
|
|
2
|
-
ignore = E203, E266, E501, W503, F403, F401, E731, E711, C901, F841, D103, B008, D400, E402, E712
|
|
3
|
-
max-line-length = 120
|
|
4
|
-
max-complexity = 20
|
|
5
|
-
exclude =
|
|
6
|
-
tests/*
|
|
7
|
-
|
|
8
|
-
[coverage:run]
|
|
9
|
-
omit =
|
|
10
|
-
xiaozhi_sdk/__main__.py
|
|
11
|
-
tests/*
|
|
12
|
-
setup.py
|
|
13
|
-
|
|
14
|
-
[egg_info]
|
|
15
|
-
tag_build =
|
|
16
|
-
tag_date = 0
|
|
17
|
-
|
xiaozhi_sdk-0.0.3/setup.py
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
from setuptools import find_packages, setup
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# 读取版本号
|
|
8
|
-
def get_version():
|
|
9
|
-
with open(os.path.join("xiaozhi_sdk", "__init__.py"), "r", encoding="utf-8") as f:
|
|
10
|
-
content = f.read()
|
|
11
|
-
match = re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', content, re.M)
|
|
12
|
-
if match:
|
|
13
|
-
return match.group(1)
|
|
14
|
-
raise RuntimeError("Unable to find version string.")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# 收集指定目录下的所有文件
|
|
18
|
-
def get_data_files(*directories):
|
|
19
|
-
data_files = []
|
|
20
|
-
for directory in directories:
|
|
21
|
-
if os.path.exists(directory):
|
|
22
|
-
for root, _, files in os.walk(directory):
|
|
23
|
-
for file in files:
|
|
24
|
-
# 将相对于项目根目录的路径转换为相对于包的路径
|
|
25
|
-
rel_path = os.path.relpath(os.path.join(root, file), ".")
|
|
26
|
-
data_files.append(rel_path)
|
|
27
|
-
return data_files
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
setup(
|
|
31
|
-
name="xiaozhi-sdk", # 包名
|
|
32
|
-
version=get_version(), # 版本号
|
|
33
|
-
packages=find_packages(), # 自动发现包
|
|
34
|
-
package_data={
|
|
35
|
-
"xiaozhi_sdk": ["../" + f for f in get_data_files("file")], # 包含file目录下的所有文件
|
|
36
|
-
},
|
|
37
|
-
include_package_data=True, # 使用MANIFEST.in文件包含额外文件
|
|
38
|
-
install_requires=[ # 依赖
|
|
39
|
-
"numpy",
|
|
40
|
-
"websockets",
|
|
41
|
-
"aiohttp",
|
|
42
|
-
"av",
|
|
43
|
-
"opuslib",
|
|
44
|
-
"requests",
|
|
45
|
-
"sounddevice",
|
|
46
|
-
"python-socks",
|
|
47
|
-
],
|
|
48
|
-
author="dairoot",
|
|
49
|
-
author_email="623815825@qq.com", # 作者邮箱
|
|
50
|
-
description="一个用于连接和控制小智智能设备的Python SDK,支持实时音频通信、MCP工具集成和设备管理功能。", # 简短描述
|
|
51
|
-
long_description=open("README.md").read(), # 详细描述(通常从 README 读取)
|
|
52
|
-
long_description_content_type="text/markdown", # README 文件格式
|
|
53
|
-
url="https://github.com/dairoot/xiaozhi-sdk", # 项目主页
|
|
54
|
-
classifiers=[ # 分类元数据
|
|
55
|
-
"Programming Language :: Python :: 3",
|
|
56
|
-
"License :: OSI Approved :: MIT License",
|
|
57
|
-
"Operating System :: OS Independent",
|
|
58
|
-
],
|
|
59
|
-
python_requires=">=3.8", # 支持的 Python 版本
|
|
60
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|