mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-29 17:03:56 +08:00
feat: add optional native mqtt and udp transport
This commit is contained in:
@@ -23,8 +23,20 @@ class GoodbyeProcessor(MessageProcessor):
|
||||
|
||||
if isinstance(msg_json, dict) and msg_json.get("type") == "goodbye":
|
||||
logger.info(f"收到goodbye: session_id={msg_json.get('session_id')}")
|
||||
# 长连接传输仅结束逻辑会话,短连接传输关闭连接。
|
||||
# WebSocket 直接关闭连接;MQTT/UDP 仅结束音频会话,保持连接
|
||||
if transport.keeps_connection_between_sessions:
|
||||
end_call = getattr(
|
||||
getattr(context, "server", None),
|
||||
"end_native_mqtt_call",
|
||||
None,
|
||||
)
|
||||
if callable(end_call):
|
||||
await end_call(
|
||||
context.device_id,
|
||||
"设备结束通话",
|
||||
notify_device=False,
|
||||
expected_session_id=msg_json.get("session_id"),
|
||||
)
|
||||
end_conversation = getattr(context, "end_conversation", None)
|
||||
if callable(end_conversation):
|
||||
await end_conversation(msg_json.get("session_id"))
|
||||
|
||||
@@ -15,6 +15,7 @@ from core.processors.abort_processor import AbortProcessor
|
||||
from core.processors.goodbye_processor import GoodbyeProcessor
|
||||
from core.processors.text_processor import TextProcessor
|
||||
from core.processors.ping_processor import PingProcessor
|
||||
from core.processors.udp_timeout_processor import UdpTimeoutProcessor
|
||||
from config.logger import setup_logging
|
||||
|
||||
logger = setup_logging()
|
||||
@@ -40,6 +41,7 @@ class MessageRouter(MessageProcessor):
|
||||
self.audio_receive_processor = AudioReceiveProcessor()
|
||||
self.text_processor = TextProcessor()
|
||||
self.ping_processor = PingProcessor()
|
||||
self.udp_timeout_processor = UdpTimeoutProcessor()
|
||||
|
||||
# 按优先级排序的processor列表
|
||||
self.processors: List[MessageProcessor] = [
|
||||
@@ -48,6 +50,7 @@ class MessageRouter(MessageProcessor):
|
||||
self.server_processor, # 服务器消息(管理端下发动作)
|
||||
self.abort_processor, # 中断消息
|
||||
self.goodbye_processor, # goodbye消息
|
||||
self.udp_timeout_processor,
|
||||
self.hello_processor, # hello消息
|
||||
self.ping_processor, # 可选JSON ping/pong心跳
|
||||
self.listen_processor, # listen消息
|
||||
|
||||
@@ -19,7 +19,7 @@ class TimeoutProcessor(MessageProcessor):
|
||||
context: SessionContext,
|
||||
transport: TransportInterface,
|
||||
) -> bool:
|
||||
"""End an expired logical conversation without closing a long connection."""
|
||||
"""End an expired logical conversation without conflating it with MQTT."""
|
||||
if not getattr(context, "conversation_active", False):
|
||||
return False
|
||||
|
||||
@@ -29,7 +29,7 @@ class TimeoutProcessor(MessageProcessor):
|
||||
|
||||
try:
|
||||
if transport.keeps_connection_between_sessions:
|
||||
logger.info(f"会话超时,结束长连接逻辑会话: {context.session_id}")
|
||||
logger.info(f"会话超时,结束MQTT逻辑会话: {context.session_id}")
|
||||
from core.processors.audio_receive_processor import (
|
||||
AudioReceiveProcessor,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from core.context.session_context import SessionContext
|
||||
from core.pipeline.message_pipeline import MessageProcessor
|
||||
from core.transport.transport_interface import TransportInterface
|
||||
from config.logger import setup_logging
|
||||
|
||||
logger = setup_logging()
|
||||
|
||||
|
||||
class UdpTimeoutProcessor(MessageProcessor):
|
||||
async def process(
|
||||
self,
|
||||
context: SessionContext,
|
||||
transport: TransportInterface,
|
||||
message: Any,
|
||||
) -> bool:
|
||||
if isinstance(message, str):
|
||||
try:
|
||||
message = json.loads(message)
|
||||
except json.JSONDecodeError:
|
||||
return False
|
||||
if not isinstance(message, dict) or message.get("type") != "udp_timeout":
|
||||
return False
|
||||
if not transport.keeps_connection_between_sessions:
|
||||
return False
|
||||
|
||||
logger.info(
|
||||
"收到udp_timeout: session_id={}", message.get("session_id")
|
||||
)
|
||||
end_call = getattr(
|
||||
getattr(context, "server", None),
|
||||
"end_native_mqtt_call",
|
||||
None,
|
||||
)
|
||||
call_ended = False
|
||||
if callable(end_call):
|
||||
call_ended = await end_call(
|
||||
context.device_id,
|
||||
"设备UDP接收超时",
|
||||
notify_device=True,
|
||||
expected_session_id=message.get("session_id"),
|
||||
)
|
||||
if not call_ended:
|
||||
end_conversation = getattr(context, "end_conversation", None)
|
||||
if callable(end_conversation):
|
||||
await end_conversation(message.get("session_id"))
|
||||
await transport.end_session(
|
||||
message.get("session_id") or context.session_id
|
||||
)
|
||||
return True
|
||||
Reference in New Issue
Block a user