client: 增加ACK支持
This commit is contained in:
@@ -5,6 +5,7 @@ import os
|
||||
from datetime import datetime
|
||||
from typing import Dict, Callable, Any, Optional
|
||||
from functools import partial
|
||||
from threading import Event
|
||||
|
||||
class ASEngineClient:
|
||||
def __init__(self, server_url: str, namespace: str, id:str):
|
||||
@@ -29,8 +30,9 @@ class ASEngineClient:
|
||||
self._on_connect_callback_entry=None
|
||||
self._on_connect_callback_initData=None
|
||||
|
||||
|
||||
|
||||
# ACK相关
|
||||
self.ack_events: Dict[str, Event] = {} # 存储ack_id和对应的Event对象
|
||||
|
||||
# 注册基础事件处理函数
|
||||
self._register_base_events()
|
||||
|
||||
@@ -62,6 +64,15 @@ class ASEngineClient:
|
||||
@self.sio.on('response', namespace=self.namespace)
|
||||
def on_response(data):
|
||||
print(f"Received response: {data}")
|
||||
|
||||
# ACK事件处理
|
||||
@self.sio.on('ack', namespace=self.namespace)
|
||||
def on_ack(data):
|
||||
ack_id = data.get('ack_id')
|
||||
if ack_id and ack_id in self.ack_events:
|
||||
print(f"Received ACK for message: {ack_id}")
|
||||
event = self.ack_events[ack_id]
|
||||
event.set() # 触发事件,通知等待的线程
|
||||
|
||||
def register_on_connect_entry(self, callback: Callable, entry: Any, init_data: Any)->bool:
|
||||
if not callable(callback):
|
||||
@@ -169,12 +180,15 @@ class ASEngineClient:
|
||||
self.sid = None
|
||||
print("Disconnected from server")
|
||||
|
||||
def send_text(self, route: str, text: str, id:str="") -> bool:
|
||||
def send_text(self, route: str, text: str, id:str="", wait_for_ack: bool = False, timeout: int = 5) -> bool:
|
||||
"""
|
||||
发送文本消息
|
||||
:param route: 目标路由
|
||||
:param text: 要发送的文本
|
||||
:return: 是否发送成功
|
||||
:param id: 发送者ID
|
||||
:param wait_for_ack: 是否等待服务器ACK确认
|
||||
:param timeout: 等待ACK的超时时间(秒)
|
||||
:return: 是否发送成功(若wait_for_ack为True,则返回是否收到ACK)
|
||||
"""
|
||||
if not self.connected:
|
||||
print("Not connected to server")
|
||||
@@ -183,19 +197,53 @@ class ASEngineClient:
|
||||
id = self.id
|
||||
|
||||
try:
|
||||
self.sio.emit(route, {'type': 'text', 'data': text, 'id': id}, namespace=self.namespace)
|
||||
# 生成唯一ack_id
|
||||
ack_id = f"{id}_{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
|
||||
|
||||
# 准备发送数据
|
||||
data = {
|
||||
'type': 'text',
|
||||
'data': text,
|
||||
'id': id,
|
||||
'ack_id': ack_id
|
||||
}
|
||||
|
||||
# 发送数据
|
||||
self.sio.emit(route, data, namespace=self.namespace)
|
||||
print(f"Sent text to route '{route}': {text}")
|
||||
return True
|
||||
|
||||
# 如果不需要等待ACK,直接返回True
|
||||
if not wait_for_ack:
|
||||
return True
|
||||
|
||||
# 初始化ACK事件
|
||||
event = Event()
|
||||
self.ack_events[ack_id] = event
|
||||
|
||||
# 等待ACK或超时
|
||||
received_ack = event.wait(timeout=timeout)
|
||||
|
||||
# 清理ACK事件
|
||||
del self.ack_events[ack_id]
|
||||
|
||||
if received_ack:
|
||||
return True
|
||||
else:
|
||||
print(f"ACK timeout for message: {ack_id}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Failed to send text to route '{route}': {e}")
|
||||
return False
|
||||
|
||||
def send_voice(self, route: str, voice_data: bytes, id:str=None) -> bool:
|
||||
def send_voice(self, route: str, voice_data: bytes, id:str=None, wait_for_ack: bool = False, timeout: int = 5) -> bool:
|
||||
"""
|
||||
发送语音数据
|
||||
:param route: 目标路由
|
||||
:param voice_data: 语音数据字节流
|
||||
:return: 是否发送成功
|
||||
:param id: 发送者ID
|
||||
:param wait_for_ack: 是否等待服务器ACK确认
|
||||
:param timeout: 等待ACK的超时时间(秒)
|
||||
:return: 是否发送成功(若wait_for_ack为True,则返回是否收到ACK)
|
||||
"""
|
||||
if id is None:
|
||||
id = self.id
|
||||
@@ -204,8 +252,9 @@ class ASEngineClient:
|
||||
return False
|
||||
|
||||
try:
|
||||
# 编码语音数据为base64
|
||||
# voice_data = 'data:image/jpeg;base64,' +base64.b64encode(voice_data).decode('utf-8')
|
||||
# 生成唯一ack_id
|
||||
ack_id = f"{id}_{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
|
||||
|
||||
# 发送数据
|
||||
self.sio.emit(
|
||||
route,
|
||||
@@ -214,24 +263,46 @@ class ASEngineClient:
|
||||
'data': voice_data,
|
||||
'timestamp': int(time.time() * 1000),
|
||||
'sampleRate': 16000,
|
||||
'id': id
|
||||
'id': id,
|
||||
'ack_id': ack_id
|
||||
},
|
||||
namespace=self.namespace
|
||||
)
|
||||
|
||||
|
||||
print(f"Sent voice file to route '{route}'")
|
||||
return True
|
||||
|
||||
# 如果不需要等待ACK,直接返回True
|
||||
if not wait_for_ack:
|
||||
return True
|
||||
|
||||
# 初始化ACK事件
|
||||
event = Event()
|
||||
self.ack_events[ack_id] = event
|
||||
|
||||
# 等待ACK或超时
|
||||
received_ack = event.wait(timeout=timeout)
|
||||
|
||||
# 清理ACK事件
|
||||
del self.ack_events[ack_id]
|
||||
|
||||
if received_ack:
|
||||
return True
|
||||
else:
|
||||
print(f"ACK timeout for message: {ack_id}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Failed to send voice to route '{route}': {e}")
|
||||
return False
|
||||
|
||||
def send_image(self, route: str, file_path: str, id:str) -> bool:
|
||||
def send_image(self, route: str, file_path: str, id:str, wait_for_ack: bool = False, timeout: int = 5) -> bool:
|
||||
"""
|
||||
发送图片文件
|
||||
:param route: 目标路由
|
||||
:param file_path: 图片文件路径
|
||||
:return: 是否发送成功
|
||||
:param id: 发送者ID
|
||||
:param wait_for_ack: 是否等待服务器ACK确认
|
||||
:param timeout: 等待ACK的超时时间(秒)
|
||||
:return: 是否发送成功(若wait_for_ack为True,则返回是否收到ACK)
|
||||
"""
|
||||
if not self.connected:
|
||||
print("Not connected to server")
|
||||
@@ -251,18 +322,41 @@ class ASEngineClient:
|
||||
# 获取文件名
|
||||
filename = os.path.basename(file_path)
|
||||
|
||||
# 生成唯一ack_id
|
||||
ack_id = f"{id}_{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
|
||||
|
||||
# 发送数据
|
||||
self.sio.emit(
|
||||
route,
|
||||
{
|
||||
'type': 'image',
|
||||
'data': image_data,
|
||||
'id': id
|
||||
'id': id,
|
||||
'ack_id': ack_id
|
||||
},
|
||||
namespace=self.namespace
|
||||
)
|
||||
print(f"Sent image file to route '{route}': {filename}")
|
||||
return True
|
||||
|
||||
# 如果不需要等待ACK,直接返回True
|
||||
if not wait_for_ack:
|
||||
return True
|
||||
|
||||
# 初始化ACK事件
|
||||
event = Event()
|
||||
self.ack_events[ack_id] = event
|
||||
|
||||
# 等待ACK或超时
|
||||
received_ack = event.wait(timeout=timeout)
|
||||
|
||||
# 清理ACK事件
|
||||
del self.ack_events[ack_id]
|
||||
|
||||
if received_ack:
|
||||
return True
|
||||
else:
|
||||
print(f"ACK timeout for message: {ack_id}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Failed to send image to route '{route}': {e}")
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user