63 lines
6.2 KiB
JavaScript
63 lines
6.2 KiB
JavaScript
async function loadLogs() {
|
|
renderLogRetention();
|
|
try {
|
|
const data = await api('/api/events?limit=150');
|
|
const level=$('#logLevelFilter')?.value||'all', category=$('#logCategoryFilter')?.value||'all';
|
|
const logs = (data.events || []).filter(item => (level==='all'||item.level===level) && (category==='all'||logCategory(item.kind)===category));
|
|
$('#logList').innerHTML = logs.length
|
|
? logs.map(item => `<div class="log-row ${esc(item.level)} category-${esc(logCategory(item.kind))}"><time>${esc(new Date(item.timestamp).toLocaleTimeString(locale()))}</time><span class="log-category">${esc(logCategory(item.kind))}</span><span class="kind">${esc(item.kind)}</span><span class="message">${esc(item.message)}</span></div>`).join('')
|
|
: `<div class="empty"><strong>${esc(tr('logs.emptyTitle'))}</strong>${esc(tr('logs.emptyText'))}</div>`;
|
|
} catch (error) { toast(error.message, true); }
|
|
}
|
|
|
|
function connectWebSocket() {
|
|
if (app.ws && [WebSocket.OPEN, WebSocket.CONNECTING].includes(app.ws.readyState)) return;
|
|
clearTimeout(app.wsTimer);
|
|
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
const query = app.token ? `?token=${encodeURIComponent(app.token)}` : '';
|
|
const ws = new WebSocket(`${protocol}//${location.host}${withBase('/ws')}${query}`); app.ws = ws;
|
|
ws.onopen = () => updateConnectionIndicator('connected');
|
|
ws.onclose = () => { updateConnectionIndicator('disconnected'); app.wsTimer = setTimeout(connectWebSocket, 3000); };
|
|
ws.onerror = () => updateConnectionIndicator('connectionError');
|
|
ws.onmessage = event => {
|
|
try {
|
|
const message = JSON.parse(event.data);
|
|
if (message.event === 'bootstrap') {
|
|
const data=message.data; app.devices=data.devices||[]; app.zones=data.zones||[]; app.groups=data.groups||[]; app.schedules=data.schedules||[]; app.automations=data.automations||[]; app.settings=data.settings||app.settings; app.sensorAliases={...(app.settings?.home_assistant?.sensor_aliases||{})}; app.system=data.system||app.system; app.systemSnapshotAt=Date.now(); app.outdoorTemperature=Number.isFinite(Number(data.outdoor_temperature))?Number(data.outdoor_temperature):app.outdoorTemperature; renderAll(); scheduleControlPlanLoad(); if(app.settings?.debug?.overlay_enabled) loadDebugBacklog(); return;
|
|
}
|
|
const data = message.data || {};
|
|
if (['device.updated','device.created'].includes(message.event)) { updateDevice(data); renderSummary(); renderDevices(); renderGroups(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'device.deleted') { app.devices=app.devices.filter(v=>v.id!==data.id); renderAll(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'devices.discovered') { (data.devices||[]).forEach(updateDevice); renderAll(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'zone.updated') { const i=app.zones.findIndex(v=>v.id===data.id); if(i>=0) app.zones[i]=data; else app.zones.push(data); renderSummary(); renderHouseClimate(); renderZones(); renderDevices(); renderGroups(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'zone.deleted') { app.zones=app.zones.filter(v=>v.id!==data.id); renderAll(); scheduleControlPlanLoad(); }
|
|
else if (['group.updated','group.created'].includes(message.event)) { const i=app.groups.findIndex(v=>v.id===data.id); if(i>=0) app.groups[i]=data; else app.groups.push(data); renderGroups(); fillSelects(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'group.deleted') { app.groups=app.groups.filter(v=>v.id!==data.id); renderGroups(); fillSelects(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'settings.updated') {
|
|
const settingsDirty=isFormDirty($('#settingsForm')), nightDirty=isFormDirty($('#nightModeForm')), haDirty=isFormDirty($('#homeAssistantForm'));
|
|
app.settings=data;
|
|
if (!haDirty) app.sensorAliases={...(app.settings?.home_assistant?.sensor_aliases||{})};
|
|
if (!settingsDirty) renderSettings();
|
|
if (!nightDirty) renderNightSettings();
|
|
if (!haDirty) renderHomeAssistantSettings();
|
|
renderHouseClimate(); renderSimulationModeBanner(); renderSystemInfo(); renderDebugOverlay(); if(app.settings?.debug?.overlay_enabled) loadDebugBacklog(); scheduleControlPlanLoad();
|
|
}
|
|
else if (message.event === 'house.power_changed') { app.settings=app.settings||{}; app.settings.house_power_enabled=data.house_power_enabled !== false; renderHouseClimate(); renderGroups(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'debug.settings') { app.settings = app.settings || {}; app.settings.debug = data; if (!isFormDirty($('#settingsForm'))) renderSettings(); renderDebugOverlay(); if(data.overlay_enabled) loadDebugBacklog(); }
|
|
else if (message.event === 'outdoor.updated') { app.outdoorTemperature=Number.isFinite(Number(data.temperature))?Number(data.temperature):null; renderHouseClimate(); scheduleControlPlanLoad(); }
|
|
else if (message.event === 'gree.frame_received') {
|
|
app.system = app.system || {};
|
|
app.system.gree_received_frames = Number(data.total || 0);
|
|
app.system.gree_received_frames_by_device = {...(app.system.gree_received_frames_by_device || {})};
|
|
if (data.device_id) app.system.gree_received_frames_by_device[data.device_id] = Number(data.device_count || 0);
|
|
renderGreeFrameStats();
|
|
renderSystemInfo();
|
|
}
|
|
else if (message.event === 'gree.frame') { if(app.settings?.debug?.overlay_enabled) debugLine('GREE', `${data.direction || '?'} ${data.protocol_version || ''}`, data.device_name || data.device_id || data.target || '', message.timestamp, data.payload); }
|
|
else if (message.event === 'api.request') { if(app.settings?.debug?.overlay_enabled) debugLine('HTTP', `${data.method || '?'} ${data.status || ''}`, `${data.path || ''} · ${data.duration_ms ?? '?'} ms`, message.timestamp); }
|
|
else if (message.event === 'log.created') { if(app.settings?.debug?.overlay_enabled) debugLine('API', data.kind || data.level || 'log', data.message || '', message.timestamp, data.metadata); if(app.currentView === 'logs') loadLogs(); }
|
|
else if (message.event.startsWith('schedule.') || message.event.startsWith('automation.')) scheduleControlPlanLoad();
|
|
} catch (_) {}
|
|
};
|
|
}
|