mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
feat: 摄像头验证码绑定检查 && 视觉分析URL动态获取
This commit is contained in:
@@ -44,6 +44,8 @@ class App {
|
||||
initMcpTools();
|
||||
// 检查麦克风可用性
|
||||
await this.checkMicrophoneAvailability();
|
||||
// 检查摄像头可用性
|
||||
this.checkCameraAvailability();
|
||||
// 初始化Live2D
|
||||
await this.initLive2D();
|
||||
// 初始化摄像头
|
||||
@@ -115,6 +117,12 @@ class App {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查摄像头可用性
|
||||
checkCameraAvailability() {
|
||||
window.cameraAvailable = true;
|
||||
log('摄像头可用性检查完成: 默认已绑定验证码', 'success');
|
||||
}
|
||||
|
||||
// 初始化摄像头
|
||||
async initCamera() {
|
||||
const cameraContainer = document.getElementById('cameraContainer');
|
||||
@@ -232,7 +240,7 @@ class App {
|
||||
log(`拍照成功,图像数据长度: ${photoData.length}`, 'success');
|
||||
|
||||
try {
|
||||
const visionApiUrl = 'http://localhost:8003/mcp/vision/explain';
|
||||
const visionApiUrl = window.visionApiUrl || 'http://localhost:8003/mcp/vision/explain';
|
||||
log(`正在发送图片到视觉分析接口: ${visionApiUrl}`, 'info');
|
||||
|
||||
const deviceId = document.getElementById('deviceMac')?.value || '';
|
||||
|
||||
@@ -81,6 +81,23 @@ export class WebSocketHandler {
|
||||
log(`收到音频控制消息: ${JSON.stringify(message)}`, 'info');
|
||||
} else if (message.type === 'stt') {
|
||||
log(`识别结果: ${message.text}`, 'info');
|
||||
// 检查是否需要绑定设备
|
||||
if (message.text && (message.text.includes('绑定') || message.text.includes('bind'))) {
|
||||
log('收到设备绑定提示,更新摄像头状态', 'warning');
|
||||
window.cameraAvailable = false;
|
||||
// 关闭摄像头
|
||||
if (typeof window.stopCamera === 'function') {
|
||||
window.stopCamera();
|
||||
}
|
||||
// 更新摄像头按钮状态
|
||||
const cameraBtn = document.getElementById('cameraBtn');
|
||||
if (cameraBtn) {
|
||||
cameraBtn.classList.remove('camera-active');
|
||||
cameraBtn.querySelector('.btn-text').textContent = '摄像头';
|
||||
cameraBtn.disabled = true;
|
||||
cameraBtn.title = '请先绑定验证码';
|
||||
}
|
||||
}
|
||||
// 使用新的聊天消息回调显示STT消息
|
||||
if (this.onChatMessage && message.text) {
|
||||
this.onChatMessage(message.text, true);
|
||||
@@ -288,6 +305,16 @@ export class WebSocketHandler {
|
||||
});
|
||||
} else if (payload.method === 'initialize') {
|
||||
log(`收到工具初始化请求: ${JSON.stringify(payload.params)}`, 'info');
|
||||
// 保存视觉分析接口地址
|
||||
if (payload.params?.capabilities?.vision?.url) {
|
||||
window.visionApiUrl = payload.params.capabilities.vision.url;
|
||||
log(`视觉分析接口地址: ${window.visionApiUrl}`, 'success');
|
||||
// 更新输入框显示
|
||||
const visionUrlInput = document.getElementById('visionUrl');
|
||||
if (visionUrlInput) {
|
||||
visionUrlInput.value = window.visionApiUrl;
|
||||
}
|
||||
}
|
||||
const replyMessage = JSON.stringify({
|
||||
"session_id": message.session_id || "",
|
||||
"type": "mcp",
|
||||
|
||||
@@ -311,10 +311,15 @@ class UIController {
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera button state - enable when connected
|
||||
// Update camera button state - enable when connected and camera is available
|
||||
if (cameraBtn && isConnected) {
|
||||
cameraBtn.disabled = false;
|
||||
cameraBtn.title = '打开/关闭摄像头';
|
||||
if (window.cameraAvailable) {
|
||||
cameraBtn.disabled = false;
|
||||
cameraBtn.title = '打开/关闭摄像头';
|
||||
} else {
|
||||
cameraBtn.disabled = true;
|
||||
cameraBtn.title = '请先绑定验证码';
|
||||
}
|
||||
}
|
||||
|
||||
// Update record button state
|
||||
@@ -487,6 +492,22 @@ class UIController {
|
||||
recordBtn.click();
|
||||
}
|
||||
}
|
||||
// Start camera only if camera is available (bound with verification code)
|
||||
if (window.cameraAvailable && typeof window.startCamera === 'function') {
|
||||
window.startCamera().then(success => {
|
||||
if (success) {
|
||||
const cameraBtn = document.getElementById('cameraBtn');
|
||||
if (cameraBtn) {
|
||||
cameraBtn.classList.add('camera-active');
|
||||
cameraBtn.querySelector('.btn-text').textContent = '关闭';
|
||||
}
|
||||
} else {
|
||||
this.addChatMessage('⚠️ 摄像头启动失败,可能被浏览器拒绝', false);
|
||||
}
|
||||
}).catch(error => {
|
||||
log(`启动摄像头异常: ${error.message}`, 'error');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Handle connect button click
|
||||
@@ -582,23 +603,6 @@ class UIController {
|
||||
}
|
||||
|
||||
this.hideModal('settingsModal');
|
||||
|
||||
// 启动摄像头
|
||||
if (typeof window.startCamera === 'function') {
|
||||
window.startCamera().then(success => {
|
||||
if (success) {
|
||||
const cameraBtn = document.getElementById('cameraBtn');
|
||||
if (cameraBtn) {
|
||||
cameraBtn.classList.add('camera-active');
|
||||
cameraBtn.querySelector('.btn-text').textContent = '关闭';
|
||||
}
|
||||
} else {
|
||||
this.addChatMessage('⚠️ 摄像头启动失败,可能被浏览器拒绝', false);
|
||||
}
|
||||
}).catch(error => {
|
||||
log(`启动摄像头异常: ${error.message}`, 'error');
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new Error('OTA连接失败');
|
||||
}
|
||||
|
||||
@@ -168,6 +168,10 @@
|
||||
<input type="text" id="serverUrl" value="" readonly disabled
|
||||
placeholder="填写OTA地址后,点击拨号按钮自动连接" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="visionUrl">视觉分析地址:</label>
|
||||
<input type="text" id="visionUrl" value="" readonly disabled placeholder="成功建立ws连接后自动获取" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user