feat: http简单上报异常以及对话

This commit is contained in:
DongShengWu 2026-01-02 05:13:03 +08:00
parent 3b49a8d776
commit 91efe70da0

246
k230/agent_client_http.py Normal file
View File

@ -0,0 +1,246 @@
import socket
import json
import time
import os
import network
import struct
import gc
from audio_module import AudioPlayer
# Try importing wave, handle different environments
try:
import media.wave as wave
except ImportError:
try:
import wave
except ImportError:
wave = None
class AgentClientHTTP:
"""
K230 Agent Client (HTTP)
"""
def __init__(self, server_host, server_port=8000):
self._server_host = server_host
self._server_port = server_port
self._sta = None
self._is_connected = False
def connect_wifi(self, ssid, password=None, timeout=15):
"""
Connect to WiFi
"""
self._sta = network.WLAN(network.STA_IF)
self._sta.active(True)
if password:
self._sta.connect(ssid, password)
else:
self._sta.connect(ssid)
print("正在连接WiFi: " + ssid + "...")
start_time = time.time()
while not self._sta.isconnected():
if time.time() - start_time > timeout:
raise RuntimeError("WiFi连接超时: " + ssid)
time.sleep(1)
try:
os.exitpoint()
except BaseException:
pass
ip = self._sta.ifconfig()[0]
print("WiFi连接成功! IP: " + ip)
self._is_connected = True
return ip
def disconnect(self):
"""断开网络连接"""
if self._sta:
if self._sta.isconnected():
self._sta.disconnect()
self._sta.active(False)
print("WiFi已断开网卡已关闭。")
self._is_connected = False
def trigger_abnormal_state(self, reason, context_data=None):
"""
Trigger abnormal state and save response as WAV.
"""
url_path = "/abnormal_trigger"
payload = {
"type": "abnormal_trigger",
"trigger_reason": reason,
"enable_streaming": True,
"context_data": context_data or {}
}
body_json = json.dumps(payload)
print(f"[AgentHTTP] 请求服务器: {self._server_host}:{self._server_port}...")
try:
# Send Request
response_data = self._send_http_request(url_path, body_json)
# Parse Header/Body
header_end = response_data.find(b"\r\n\r\n")
if header_end == -1:
print("[AgentHTTP] 响应格式错误")
return None
body_bytes = response_data[header_end + 4:]
if len(body_bytes) == 0:
print("[AgentHTTP] 响应正文为空")
return None
print(f"[AgentHTTP] 成功接收音频数据: {len(body_bytes)} 字节")
# Save as WAV file
# TTS server returns 24000Hz, 1 channel, 16bit (2 bytes) PCM
wav_file = "/sdcard/agent_response.wav"
self._save_wav(wav_file, body_bytes, rate=24000, channels=1, sampwidth=2)
return wav_file
except Exception as e:
print(f"[AgentHTTP] 请求失败: {e}")
return None
def _save_wav(self, filename, pcm_data, rate=24000, channels=1, sampwidth=2):
"""
Save PCM data with WAV header
"""
print(f"[AgentHTTP] 保存 WAV 文件: {filename} (Rate: {rate}, Ch: {channels})")
try:
if wave:
# Use wave module if available
wf = wave.open(filename, 'wb')
wf.set_channels(channels)
wf.set_sampwidth(sampwidth)
wf.set_framerate(rate)
wf.write_frames(pcm_data)
wf.close()
else:
# Manual WAV header creation
total_len = len(pcm_data) + 36
header = struct.pack(
'<4sI4s4sIHHIIHH4sI',
b'RIFF',
total_len,
b'WAVE',
b'fmt ',
16,
1,
channels,
rate,
rate * channels * sampwidth,
channels * sampwidth,
sampwidth * 8,
b'data',
len(pcm_data))
with open(filename, 'wb') as f:
f.write(header)
f.write(pcm_data)
except Exception as e:
print(f"[AgentHTTP] 保存 WAV 失败: {e}")
def play_audio_file(self, file_path):
"""
Play audio file using AudioPlayer.play_file (handles WAV)
"""
if not file_path:
return
print(f"[AgentHTTP] 正在播放: {file_path}...")
player = None
try:
player = AudioPlayer()
# play_file will init and start stream, write frames, and then deinit in
# finally block
player.play_file(file_path)
print("[AgentHTTP] 播放完成。")
except Exception as e:
print(f"[AgentHTTP] 播放出错: {e}")
finally:
# Double check deinit to prevent noise/resource leak
if player:
try:
if player.is_running: # Check if flag exists
player.deinit()
except BaseException:
pass
def _send_http_request(self, path, body_json):
"""
Send HTTP POST
"""
addr_info = socket.getaddrinfo(self._server_host, self._server_port)
addr = addr_info[0][-1]
s = socket.socket()
s.settimeout(10)
try:
s.connect(addr)
body_bytes = body_json.encode('utf-8')
req = f"POST {path} HTTP/1.1\r\n"
req += f"Host: {self._server_host}:{self._server_port}\r\n"
req += "Content-Type: application/json\r\n"
req += f"Content-Length: {len(body_bytes)}\r\n"
req += "Connection: close\r\n\r\n"
s.send(req.encode('utf-8'))
s.send(body_bytes)
response = bytearray()
while True:
chunk = s.recv(4096)
if not chunk:
break
response.extend(chunk)
return response
finally:
s.close()
if __name__ == "__main__":
# ========== CONFIG ==========
WIFI_SSID = "dongshengwu"
WIFI_PASSWORD = "wds666666"
SERVER_HOST = "172.20.10.2"
SERVER_PORT = 8000
# ============================
client = AgentClientHTTP(server_host=SERVER_HOST, server_port=SERVER_PORT)
try:
# 1. Connect
client.connect_wifi(WIFI_SSID, WIFI_PASSWORD)
# 2. Trigger & Save
print("\n[测试] 触发皮肤状态异常提示...")
wav_file = client.trigger_abnormal_state("poor_skin")
# 3. Play
if wav_file:
client.play_audio_file(wav_file)
except Exception as e:
print("程序异常: " + str(e))
finally:
# 4. Clean up resources
print("\n[资源清理] 断开 WiFi 并回收资源...")
gc.collect()
print("测试结束,已安全退出。")