mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-27 09:33:55 +08:00
feat: 摄像头验证码绑定检查 && 视觉分析URL动态获取
This commit is contained in:
@@ -44,6 +44,8 @@ class App {
|
|||||||
initMcpTools();
|
initMcpTools();
|
||||||
// 检查麦克风可用性
|
// 检查麦克风可用性
|
||||||
await this.checkMicrophoneAvailability();
|
await this.checkMicrophoneAvailability();
|
||||||
|
// 检查摄像头可用性
|
||||||
|
this.checkCameraAvailability();
|
||||||
// 初始化Live2D
|
// 初始化Live2D
|
||||||
await this.initLive2D();
|
await this.initLive2D();
|
||||||
// 初始化摄像头
|
// 初始化摄像头
|
||||||
@@ -115,6 +117,12 @@ class App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查摄像头可用性
|
||||||
|
checkCameraAvailability() {
|
||||||
|
window.cameraAvailable = true;
|
||||||
|
log('摄像头可用性检查完成: 默认已绑定验证码', 'success');
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化摄像头
|
// 初始化摄像头
|
||||||
async initCamera() {
|
async initCamera() {
|
||||||
const cameraContainer = document.getElementById('cameraContainer');
|
const cameraContainer = document.getElementById('cameraContainer');
|
||||||
@@ -232,7 +240,7 @@ class App {
|
|||||||
log(`拍照成功,图像数据长度: ${photoData.length}`, 'success');
|
log(`拍照成功,图像数据长度: ${photoData.length}`, 'success');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const visionApiUrl = 'http://localhost:8003/mcp/vision/explain';
|
const visionApiUrl = window.visionApiUrl || 'http://localhost:8003/mcp/vision/explain';
|
||||||
log(`正在发送图片到视觉分析接口: ${visionApiUrl}`, 'info');
|
log(`正在发送图片到视觉分析接口: ${visionApiUrl}`, 'info');
|
||||||
|
|
||||||
const deviceId = document.getElementById('deviceMac')?.value || '';
|
const deviceId = document.getElementById('deviceMac')?.value || '';
|
||||||
|
|||||||
@@ -81,6 +81,23 @@ export class WebSocketHandler {
|
|||||||
log(`收到音频控制消息: ${JSON.stringify(message)}`, 'info');
|
log(`收到音频控制消息: ${JSON.stringify(message)}`, 'info');
|
||||||
} else if (message.type === 'stt') {
|
} else if (message.type === 'stt') {
|
||||||
log(`识别结果: ${message.text}`, 'info');
|
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消息
|
// 使用新的聊天消息回调显示STT消息
|
||||||
if (this.onChatMessage && message.text) {
|
if (this.onChatMessage && message.text) {
|
||||||
this.onChatMessage(message.text, true);
|
this.onChatMessage(message.text, true);
|
||||||
@@ -288,6 +305,16 @@ export class WebSocketHandler {
|
|||||||
});
|
});
|
||||||
} else if (payload.method === 'initialize') {
|
} else if (payload.method === 'initialize') {
|
||||||
log(`收到工具初始化请求: ${JSON.stringify(payload.params)}`, 'info');
|
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({
|
const replyMessage = JSON.stringify({
|
||||||
"session_id": message.session_id || "",
|
"session_id": message.session_id || "",
|
||||||
"type": "mcp",
|
"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) {
|
if (cameraBtn && isConnected) {
|
||||||
cameraBtn.disabled = false;
|
if (window.cameraAvailable) {
|
||||||
cameraBtn.title = '打开/关闭摄像头';
|
cameraBtn.disabled = false;
|
||||||
|
cameraBtn.title = '打开/关闭摄像头';
|
||||||
|
} else {
|
||||||
|
cameraBtn.disabled = true;
|
||||||
|
cameraBtn.title = '请先绑定验证码';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update record button state
|
// Update record button state
|
||||||
@@ -487,6 +492,22 @@ class UIController {
|
|||||||
recordBtn.click();
|
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
|
// Handle connect button click
|
||||||
@@ -582,23 +603,6 @@ class UIController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.hideModal('settingsModal');
|
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 {
|
} else {
|
||||||
throw new Error('OTA连接失败');
|
throw new Error('OTA连接失败');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,6 +168,10 @@
|
|||||||
<input type="text" id="serverUrl" value="" readonly disabled
|
<input type="text" id="serverUrl" value="" readonly disabled
|
||||||
placeholder="填写OTA地址后,点击拨号按钮自动连接" />
|
placeholder="填写OTA地址后,点击拨号按钮自动连接" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="visionUrl">视觉分析地址:</label>
|
||||||
|
<input type="text" id="visionUrl" value="" readonly disabled placeholder="成功建立ws连接后自动获取" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user