function settingsFromSnapshot(sections, houseMode = app.settings?.house_mode || 'cool') { const application = sections?.application || {}; const gree = sections?.gree || {}; const greeCloud = sections?.gree_cloud || {}; const history = sections?.history || {}; const influxdb = sections?.influxdb || {}; const notifications = sections?.notifications || {}; const night = sections?.night || {}; const homeAssistant = sections?.home_assistant || {}; const debug = sections?.debug || {}; return { simulator_enabled: !!application.simulator_enabled, controller_id: gree.controller_id, poll_interval_seconds: Number(gree.poll_interval_seconds), zone_interval_seconds: Number(gree.zone_interval_seconds), discovery_timeout_ms: Number(gree.discovery_timeout_ms), discovery_broadcast: gree.discovery_broadcast, ping_metrics_enabled: gree.ping_metrics_enabled !== false, ping_interval_seconds: Number(gree.ping_interval_seconds || 60), ping_sample_count: Number(gree.ping_sample_count || 3), suppress_device_beep: !!gree.suppress_device_beep, gree_cloud: greeCloud, compressor_protection_enabled: gree.compressor_protection_enabled !== false, compressor_protection_seconds: Number(gree.compressor_protection_seconds), history_retention_days: Number(history.retention_days), history_compaction_enabled: history.compaction_enabled !== false, event_log_retention_days: Number(history.event_retention_days), influxdb, notifications, night_mode: night, home_assistant: homeAssistant, outdoor_assist_enabled: !!homeAssistant.outdoor_assist_enabled, debug, house_mode: houseMode || 'cool', }; } function applyBootstrapSnapshot(data) { app.devices = data.devices || []; app.deviceGroups = data.device_groups || []; app.deviceGroupEnergy = data.device_group_energy || {}; app.zones = data.zones || []; app.groups = data.groups || []; app.schedules = data.schedules || []; app.automations = data.automations || []; app.flows = data.flows || []; app.accessTokens = data.access_tokens || []; app.settings = settingsFromSnapshot(data.settings, data.house?.mode || 'cool'); app.sensorAliases = { ...(app.settings.home_assistant?.sensor_aliases || {}) }; app.flowSharedInputs = JSON.parse(JSON.stringify(app.settings.home_assistant?.flow_inputs || [])); app.system = data.system || {}; app.systemSnapshotAt = Date.now(); const outdoorTemperature = data.outdoor_temperature; app.outdoorTemperature = outdoorTemperature === null || outdoorTemperature === undefined || outdoorTemperature === '' ? null : (Number.isFinite(Number(outdoorTemperature)) ? Number(outdoorTemperature) : null); const hasControlPlan = !!data.control_plan; if (hasControlPlan) app.controlPlan = data.control_plan; if (Number.isFinite(Number(data.control_plan_revision))) app.controlPlanRevision = Number(data.control_plan_revision); return hasControlPlan; } async function loadBootstrap(showMessage = false) { if (app.loading) { app.bootstrapReloadPending = true; return; } app.loading = true; try { const data = await api('/api/bootstrap'); const hasControlPlan = applyBootstrapSnapshot(data); renderAll(); if (!hasControlPlan) scheduleControlPlanLoad(0); if (app.settings?.debug?.overlay_enabled) loadDebugBacklog(); if (showMessage) toast(tr('common.updated')); if ($('#tokenDialog').open) $('#tokenDialog').close(); connectWebSocket(); } catch (error) { if (!String(error.message).toLowerCase().includes('token')) toast(error.message, true); } finally { app.loading = false; if (app.bootstrapReloadPending) { app.bootstrapReloadPending = false; setTimeout(() => loadBootstrap(), 0); } } }