// ========== IoT 设备控制面板 ========== function startIoTRefresh() { stopIoTRefresh(); STATE.iotInterval = setInterval(function() { if (STATE.activePanel === 'iot') renderIoTPanel(); }, 3000); } function stopIoTRefresh() { if (STATE.iotInterval) { clearInterval(STATE.iotInterval); STATE.iotInterval = null; } } async function fetchIoTDevices() { var data = await api('/api/iot/devices'); if (data.error) return { error: data }; var devices = []; if (Array.isArray(data)) devices = data; else if (data.devices) devices = data.devices; return { devices: devices }; } var IOT_DEVICE_TYPES = { 'ac': '❄️', 'light': '💡', 'curtain': '🪟', 'door_lock': '🔒', 'camera': '📷', 'sensor': '📡', 'speaker': '🔊', 'thermostat': '🌡️', }; var IOT_MODE_OPTIONS = ['cool', 'heat', 'auto', 'fan', 'dry']; var IOT_COLOR_OPTIONS = [ { name: '暖白', value: 'warm_white', bg: '#f5d0a9' }, { name: '冷白', value: 'cool_white', bg: '#d4e6fc' }, { name: '暖黄', value: 'warm_yellow', bg: '#fce4a6' }, { name: '蓝色', value: 'blue', bg: '#3b82f6' }, { name: '紫色', value: 'purple', bg: '#a855f7' }, { name: '绿色', value: 'green', bg: '#22c55e' }, ]; async function renderIoTPanel() { document.getElementById('panel-actions').innerHTML = '' + '⏱ 每3秒自动刷新 · 最后更新: ' + new Date().toLocaleTimeString('zh-CN', {hour12: false}) + ''; var result = await fetchIoTDevices(); var panel = document.getElementById('panel-iot'); if (result.error) { var hint = ''; if (result.error.errorType === 'iot_not_running') { hint = '
💡 提示: 请先在「服务管理」面板中启动 IoT Debug 服务'; } panel.innerHTML = '
⚠️
' + escHtml(result.error.error) + hint + '
'; return; } var devices = result.devices; var badge = document.getElementById('iot-badge'); if (badge) { badge.textContent = devices.length; badge.style.display = devices.length > 0 ? 'inline-block' : 'none'; } var html = '
' + '📡 模拟 IoT 设备 (' + devices.length + ')' + '通过 IoT 调试服务 (端口 8083) 管理' + '
' + devices.map(function(d) { return renderIoTDeviceCard(d); }).join('') + '
'; panel.innerHTML = html; } function renderIoTDeviceCard(device) { var isOn = device.status === 'on'; var icon = IOT_DEVICE_TYPES[device.type] || '📦'; var propsHtml = ''; if (device.type === 'ac') { propsHtml = '
' + '🌡️ 温度' + '
' + '' + '' + (device.temperature || 26) + '°C' + '
' + '
' + '
' + '🔄 模式' + '
' + IOT_MODE_OPTIONS.map(function(m) { var active = (device.mode || 'cool') === m ? ' active' : ''; return ''; }).join('') + '
' + '
'; } else if (device.type === 'light') { propsHtml = '
' + '💡 亮度' + '
' + '' + '' + (device.brightness || 80) + '%' + '
' + '
' + '
' + '🎨 颜色' + '
' + IOT_COLOR_OPTIONS.map(function(c) { var active = (device.color || 'warm_white') === c.value ? ' active' : ''; return ''; }).join('') + '
' + '
'; } else if (device.type === 'curtain') { propsHtml = '
' + '🪟 位置' + '
' + '' + '' + (device.position != null ? device.position : 100) + '%' + '
' + '
'; } else if (device.temperature != null) { propsHtml = '
' + '🌡️ 温度' + '' + device.temperature + (device.unit || '°C') + '' + '
'; } if (device.battery != null) { propsHtml += '
' + '🔋 电量' + '' + device.battery + '%' + '
'; } var actionsHtml = '
' + ''; if (device.type === 'ac') { var currentTemp = device.temperature || 26; actionsHtml += '' + ''; } actionsHtml += '' + '
' + ''; return '
' + '
' + '
' + '' + icon + '' + '
' + '
' + escHtml(device.name) + '
' + '
' + escHtml(device.type) + ' · ' + escHtml(device.id) + '
' + '
' + '
' + '
' + '' + '' + (isOn ? '开启' : '关闭') + '' + '
' + '
' + (propsHtml ? '
' + propsHtml + '
' : '') + actionsHtml + '
'; } async function iotToggle(deviceId) { console.log('[IoT] 切换设备开关: ' + deviceId); var data = await api('/api/iot/devices/' + deviceId + '/toggle', { method: 'POST' }); if (data.error) { showToast('切换失败: ' + data.error, 'error'); } else { var device = data.device || {}; showToast((device.name || deviceId) + ': ' + (device.status === 'on' ? '已开启' : '已关闭'), 'success'); renderIoTPanel(); } } async function iotSetProperty(deviceId, field, value) { console.log('[IoT] 设置设备属性: ' + deviceId + ' -> ' + field + ' = ' + value); var data = await api('/api/iot/devices/' + deviceId + '/set', { method: 'POST', body: JSON.stringify({ field: field, value: value }), }); if (data.error) { showToast('设置失败: ' + data.error, 'error'); } else { var device = data.device || {}; showToast((device.name || deviceId) + ': ' + field + ' = ' + value, 'success'); } } async function refreshIoTDeviceCard(deviceId) { var data = await api('/api/iot/devices/' + deviceId); if (data.error) return; var device = data.device; if (!device) return; var card = document.getElementById('iot-card-' + deviceId); if (!card) return; card.outerHTML = renderIoTDeviceCard(device); } async function iotShowHistory(deviceId) { var panel = document.getElementById('iot-history-' + deviceId); if (!panel) return; if (panel.style.display !== 'none') { panel.style.display = 'none'; return; } console.log('[IoT] 获取设备历史: ' + deviceId); var data = await api('/api/iot/devices/' + deviceId + '/history'); panel.style.display = ''; if (data.error) { panel.innerHTML = '
' + escHtml(data.error) + '
'; return; } var history = data.history || []; if (history.length === 0) { panel.innerHTML = '
暂无操作历史
'; return; } panel.innerHTML = history.slice(-20).reverse().map(function(h) { var timeStr = h.timestamp ? new Date(h.timestamp).toLocaleTimeString('zh-CN', {hour12: false}) : '—'; return '
' + '' + timeStr + '' + '' + escHtml(h.action || '操作') + '' + '' + escHtml(h.detail || h.value || '') + '' + '
'; }).join(''); }