上传后台修改
This commit is contained in:
@@ -5,15 +5,53 @@ from utils.logger import session_logger
|
||||
message_audio_storage_service = MessageAudioStorageService()
|
||||
|
||||
|
||||
# async def save_audio_file(audio_data: bytes, device_id: str) -> str:
|
||||
# """Upload device audio to COS and return its object key."""
|
||||
# try:
|
||||
# stored = await message_audio_storage_service.upload_audio(
|
||||
# device_id=device_id,
|
||||
# content=audio_data,
|
||||
# )
|
||||
# session_logger.info(device_id, "audio", f"audio uploaded to COS: {stored.file_key}")
|
||||
# return stored.file_key
|
||||
# except Exception as e:
|
||||
# session_logger.error(device_id, "audio", f"failed to store audio: {e}", exc_info=True)
|
||||
# raise
|
||||
|
||||
|
||||
import os
|
||||
import uuid
|
||||
from config import settings
|
||||
from utils.logger import session_logger
|
||||
# from utils.audio_denoiser import reduce_background_noise
|
||||
|
||||
|
||||
async def save_audio_file(audio_data: bytes, device_id: str) -> str:
|
||||
"""Upload device audio to COS and return its object key."""
|
||||
"""
|
||||
保存音频数据到 assets/audio 目录
|
||||
|
||||
Args:
|
||||
audio_data: 音频二进制数据
|
||||
device_id: 设备ID
|
||||
|
||||
Returns:
|
||||
音频文件的相对路径
|
||||
"""
|
||||
try:
|
||||
stored = await message_audio_storage_service.upload_audio(
|
||||
device_id=device_id,
|
||||
content=audio_data,
|
||||
)
|
||||
session_logger.info(device_id, "audio", f"audio uploaded to COS: {stored.file_key}")
|
||||
return stored.file_key
|
||||
audio_dir = os.path.join(settings.assets_dir, "audio")
|
||||
os.makedirs(audio_dir, exist_ok=True)
|
||||
|
||||
filename = f"{device_id}_{uuid.uuid4().hex[:8]}.mp3"
|
||||
filepath = os.path.join(audio_dir, filename)
|
||||
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(audio_data)
|
||||
|
||||
# relative_path = f"assets/audio/{filename}"
|
||||
session_logger.info(device_id, "audio", f"音频文件已保存: {filepath}")
|
||||
|
||||
# reduce_background_noise(filepath, relative_path,noise_path='assets/audio/noise_sample.wav',normalize_volume=True)
|
||||
return filepath
|
||||
except Exception as e:
|
||||
session_logger.error(device_id, "audio", f"failed to store audio: {e}", exc_info=True)
|
||||
raise
|
||||
session_logger.error(device_id, "audio", f"保存音频文件时出错: {e}", exc_info=True)
|
||||
raise
|
||||
@@ -43,6 +43,10 @@ class TalkingQMQTTService:
|
||||
"005": self._handle_nfc_listen_report,
|
||||
"006": self._handle_bind_response,
|
||||
"007": self._handle_open_response,
|
||||
"008": self._handle_sleep_schedule_response,
|
||||
"009": self._handle_remote_sleep_wake_response,
|
||||
"010": self._handle_alarm_report,
|
||||
"011": self._handle_short_press_message,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -161,11 +165,11 @@ class TalkingQMQTTService:
|
||||
await self._send_nfc_listen_response(device_id, nfc_uuid)
|
||||
|
||||
async def _handle_bind_response(self, device_id: str, payload: dict):
|
||||
params = payload.get("params", {})
|
||||
params = payload
|
||||
status = params.get("status")
|
||||
logger.info(device_id, "", f"[NFC绑定] 设备 {device_id} 请求绑定卡片返回状态: {status}")
|
||||
|
||||
nfc_uuid = params.get("uuid")
|
||||
data = params.get("data", {})
|
||||
nfc_uuid = data.get("uuid")
|
||||
# 卡片与设备绑定
|
||||
# await card_service.activate_card(device_id=device_id, card_uuid=nfc_uuid)
|
||||
service = BindingService()
|
||||
@@ -176,13 +180,44 @@ class TalkingQMQTTService:
|
||||
logger.info(device_id, "", f"[NFC绑定] 设备 {device_id} 请求绑定卡片, UUID={nfc_uuid}, result={result}")
|
||||
|
||||
async def _handle_open_response(self, device_id: str, payload: dict):
|
||||
params = payload.get("params", {})
|
||||
params = payload
|
||||
status = params.get("status")
|
||||
logger.info(device_id, "", f"[设备状态] 设备 {device_id} 请求返回设备状态: {status}")
|
||||
data = params.get("data", {})
|
||||
device_status = data.get("status")
|
||||
logger.info(device_id, "", f"[设备状态] 设备 {device_id} 请求设备状态: {device_status}")
|
||||
|
||||
async def _handle_sleep_schedule_response(self, device_id: str, payload: dict):
|
||||
status = payload.get("status")
|
||||
if status == "success":
|
||||
logger.info(device_id, "", f"[定时休眠] 设备 {device_id} 休眠时间设置成功")
|
||||
else:
|
||||
logger.warning(device_id, "", f"[定时休眠] 设备 {device_id} 休眠时间设置失败: {payload}")
|
||||
|
||||
async def _handle_remote_sleep_wake_response(self, device_id: str, payload: dict):
|
||||
status = payload.get("status")
|
||||
if status == "success":
|
||||
logger.info(device_id, "", f"[远程休眠唤醒] 设备 {device_id} 操作成功")
|
||||
else:
|
||||
logger.warning(device_id, "", f"[远程休眠唤醒] 设备 {device_id} 操作失败: {payload}")
|
||||
|
||||
async def _handle_alarm_report(self, device_id: str, payload: dict):
|
||||
logger.info(device_id, "", f"[告警] 设备 {device_id} 发送紧急报警")
|
||||
await self._publish(f"device/{device_id}/event_resp", {"msg_id": "010", "status": "success"})
|
||||
|
||||
async def _handle_short_press_message(self, device_id: str, payload: dict):
|
||||
params = payload.get("params", {})
|
||||
nfc_uuid = params.get("uuid")
|
||||
logger.info(device_id, "", f"[短按留言] 设备 {device_id} 短按发送留言, UUID={nfc_uuid}")
|
||||
payload = {
|
||||
"msg_id": "011",
|
||||
"type": 0,
|
||||
"params": {
|
||||
"url": f"http://{settings.server_host}:{settings.server_port}/assets/audio/message_ok.mp3"
|
||||
}
|
||||
}
|
||||
await self._publish(f"device/{device_id}/event_resp", payload)
|
||||
|
||||
async def _send_nfc_listen_response(self, device_id: str, nfc_uuid: str):
|
||||
topic = f"device/{device_id}/event_resp"
|
||||
card = await card_service.get_card_by_uuid(nfc_uuid)
|
||||
@@ -201,7 +236,7 @@ class TalkingQMQTTService:
|
||||
is_owner = await card_service.check_card_ownership(nfc_uuid, device_id)
|
||||
if is_owner:
|
||||
has_pending = await offline_audio_cache.has_pending_audio(device_id)
|
||||
if nfc_uuid == "53D92B6DA20001":
|
||||
if nfc_uuid == "53C22B6DA20001":
|
||||
payload = {
|
||||
"msg_id": "005",
|
||||
"type": 0,
|
||||
@@ -214,12 +249,12 @@ class TalkingQMQTTService:
|
||||
if has_pending:
|
||||
audio_urls = await offline_audio_cache.get_audio_urls(device_id)
|
||||
# 53D92B6DA20001 测试卡片
|
||||
if nfc_uuid == "53D92B6DA20001":
|
||||
if nfc_uuid == "53C22B6DA20001":
|
||||
payload = {
|
||||
"msg_id": "005",
|
||||
"type": 0,
|
||||
"params": {
|
||||
"url_1": f"http://{settings.server_host}:{settings.server_port}/assets/audio/test_zh.mp3"
|
||||
"url_1": f"http://{settings.server_host}:{settings.server_port}/assets/audio/TalkingQ_XQSN00001005_2f654480.mp3"
|
||||
}
|
||||
}
|
||||
await self._publish(topic, payload)
|
||||
@@ -366,7 +401,7 @@ class TalkingQMQTTService:
|
||||
topic = f"device/{device_id}/command"
|
||||
payload = {
|
||||
"msg_id": "004",
|
||||
"params": {"url_1": url}
|
||||
"params": {"url": url}
|
||||
}
|
||||
await self._publish(topic, payload)
|
||||
return "004"
|
||||
@@ -375,15 +410,18 @@ class TalkingQMQTTService:
|
||||
async def send_bind_nfc_command(self, device_id: str, uuid: str) -> str:
|
||||
topic = f"device/{device_id}/command"
|
||||
payload = {
|
||||
"msg_id": "006"
|
||||
"msg_id": "006",
|
||||
"params": {
|
||||
"url": f"http://{settings.server_host}:{settings.server_port}/assets/audio/bind_nfc_ready_zh.mp3"
|
||||
}
|
||||
}
|
||||
await self._publish(topic, payload)
|
||||
return "006"
|
||||
|
||||
async def send_open_command(self, device_id: str, open_type: int, is_open: int) -> str:
|
||||
topic = f"device/{device_id}/command"
|
||||
if open_type not in [0, 1]:
|
||||
raise ValueError("open_type must be 0 or 1")
|
||||
if open_type not in [0, 1, 2]:
|
||||
raise ValueError("open_type must be 0, 1 or 2")
|
||||
if open_type == 0:
|
||||
payload = {
|
||||
"msg_id": "007",
|
||||
@@ -392,8 +430,37 @@ class TalkingQMQTTService:
|
||||
elif open_type == 1:
|
||||
payload = {
|
||||
"msg_id": "007",
|
||||
"type": open_type,
|
||||
"status": is_open
|
||||
"type": open_type
|
||||
}
|
||||
elif open_type == 2:
|
||||
payload = {
|
||||
"msg_id": "007",
|
||||
"type": open_type
|
||||
}
|
||||
await self._publish(topic, payload)
|
||||
return "007"
|
||||
|
||||
async def send_sleep_schedule_command(self, device_id: str, start: str, end: str) -> str:
|
||||
topic = f"device/{device_id}/command"
|
||||
payload = {
|
||||
"msg_id": "008",
|
||||
"params": {
|
||||
"start": start,
|
||||
"end": end
|
||||
}
|
||||
}
|
||||
await self._publish(topic, payload)
|
||||
return "008"
|
||||
|
||||
async def send_remote_sleep_wake_command(self, device_id: str, switch: str) -> str:
|
||||
if switch not in ["on", "off"]:
|
||||
raise ValueError("switch must be 'on' or 'off'")
|
||||
topic = f"device/{device_id}/command"
|
||||
payload = {
|
||||
"msg_id": "009",
|
||||
"params": {
|
||||
"switch": switch
|
||||
}
|
||||
}
|
||||
await self._publish(topic, payload)
|
||||
return "009"
|
||||
|
||||
@@ -18,6 +18,8 @@ from handlers.prompt_sound_handler import handle_prompt_sound_request
|
||||
from handlers.session_cleanup_handler import handle_old_session_cleanup
|
||||
from config import settings
|
||||
from banban.service.im import im_service as im_conversation_service
|
||||
from handlers.audio_file_handler import message_audio_storage_service, save_audio_file
|
||||
from fastapi import HTTPException
|
||||
|
||||
async def handle_websocket_messages(websocket: WebSocket, device_id: str, serial_number: str):
|
||||
"""
|
||||
@@ -265,11 +267,14 @@ async def process_cached_audio(device_id: str, target_device_id: str, serial_num
|
||||
return
|
||||
|
||||
# 保存音频文件
|
||||
audio_path = await save_audio_file(cached_audio, device_id)
|
||||
audio_url = f"http://{settings.server_host}:{settings.server_port}/{audio_path}"
|
||||
audio_file_key = await save_audio_file(cached_audio, device_id)
|
||||
audio_url = f"http://{settings.server_host}:{settings.server_port}/{audio_file_key}"
|
||||
# 将音频URL保存到数据库 im_conversation和im_message
|
||||
await im_conversation_service.create_device_message(device_id=device_id, serial_number=serial_number, target_device_id=target_device_id, audio_url=audio_url)
|
||||
|
||||
# await im_conversation_service.create_device_message(device_id=device_id, serial_number=serial_number, target_device_id=target_device_id, audio_url=audio_file_key)
|
||||
# try:
|
||||
# audio_url = await message_audio_storage_service.get_audio_url(audio_file_key)
|
||||
# except Exception:
|
||||
# audio_url = audio_file_key
|
||||
# 发送URL给目标设备
|
||||
# target_websocket = await connection_manager.get_connection(target_device_id)
|
||||
# if target_websocket and target_websocket.client_state.name == "CONNECTED":
|
||||
@@ -290,7 +295,7 @@ async def process_cached_audio(device_id: str, target_device_id: str, serial_num
|
||||
await websocket.send_text(f"PROMPT_SOUND_URL:{success_audio_url}")
|
||||
session_logger.info(device_id, "device", f"留言已收到音频URL给设备 {device_id}")
|
||||
else:
|
||||
session_logger.warning(device_id, "device", f"设备 {device_id} 不在线,发送留言已收到音频URL失败")
|
||||
session_logger.warning(device_id, "device", f"设备 {device_id} 不在线,暂不发送留言已收到音频URL")
|
||||
# # # 目标设备不在线,保存到离线缓存
|
||||
# await offline_audio_cache.add_audio_url(target_device_id, audio_url)
|
||||
# session_logger.warning(device_id, "target", f"目标设备 {target_device_id} 不在线,保存音频URL到离线缓存")
|
||||
@@ -302,7 +307,19 @@ async def process_cached_audio(device_id: str, target_device_id: str, serial_num
|
||||
# else:
|
||||
# session_logger.warning(device_id, "device", f"设备 {device_id} 不在线,发送留言成功音频失败")
|
||||
except Exception as e:
|
||||
session_logger.error(device_id, "target", f"处理缓存音频时出错: {e}", exc_info=True)
|
||||
# 处理HTTPException异常
|
||||
if isinstance(e, HTTPException):
|
||||
session_logger.error(device_id, "target", f"保存音频文件时出错,返回HTTPException: {e}")
|
||||
websocket = await connection_manager.get_connection(device_id)
|
||||
if e.status_code == 404 or e.status_code == 400:
|
||||
if websocket and websocket.client_state.name == "CONNECTED":
|
||||
success_audio_url = f"http://{settings.server_host}:{settings.server_port}/assets/audio/save_audio_fail.mp3"
|
||||
await websocket.send_text(f"PROMPT_SOUND_URL:{success_audio_url}")
|
||||
session_logger.info(device_id, "device", f"留言已收到音频URL给设备 {device_id}")
|
||||
else:
|
||||
session_logger.warning(device_id, "device", f"设备 {device_id} 不在线,暂不发送留言已收到音频URL")
|
||||
else:
|
||||
session_logger.error(device_id, "target", f"处理缓存音频时出错: {e}", exc_info=True)
|
||||
finally:
|
||||
# 清除缓存
|
||||
await target_audio_cache.clear_audio_data(target_device_id)
|
||||
|
||||
Reference in New Issue
Block a user