-- ============================================================= -- R__058_vw_latest_telemetry.sql -- EMS Platform – aktuální stav všech zařízení per lokalita -- Repeatable migration -- -- Výkon (audit 2026-06-11): původní DISTINCT ON přes celé hypertable -- třídilo ~195k (inverter) / ~277k (EV) řádků při každém čtení -- (fn_site_full_status ~1.7 s). LATERAL limit 1 per zařízení čte jen -- špičku PK indexu ((inverter_id|charger_id, …, measured_at)). -- ============================================================= -- security_invoker = false: oprávnění na podkladové hypertably nemusí mít ems_anon (PostgREST). create or replace view ems.vw_latest_inverter with (security_invoker = false) as select inv.site_id, inv.id as inverter_id, inv.code as inverter_code, t.measured_at, t.pv_power_w, t.battery_soc_percent, t.battery_power_w, t.grid_power_w, t.load_power_w, t.inverter_temp_c, t.operating_mode, t.fault_code, now() - t.measured_at as data_age, t.pv1_power_w, t.pv2_power_w, t.gen_port_power_w, t.batt_charge_today_wh, t.batt_discharge_today_wh, t.run_state, t.is_export_limited, t.pv_derating_flags from ems.asset_inverter inv left join lateral ( select ti.measured_at, ti.pv_power_w, ti.battery_soc_percent, ti.battery_power_w, ti.grid_power_w, ti.load_power_w, ti.inverter_temp_c, ti.operating_mode, ti.fault_code, ti.pv1_power_w, ti.pv2_power_w, ti.gen_port_power_w, ti.batt_charge_today_wh, ti.batt_discharge_today_wh, ti.run_state, ti.is_export_limited, ti.pv_derating_flags from ems.telemetry_inverter ti where ti.inverter_id = inv.id order by ti.measured_at desc limit 1 ) t on true where t.measured_at is not null; comment on view ems.vw_latest_inverter is 'Nejnovější telemetrická data pro každý střídač (LATERAL per-inverter, PK index). Slouží pro real-time dashboard a health check.'; -- ------------------------------------------------------------ create or replace view ems.vw_latest_ev_charger with (security_invoker = false) as select ch.site_id, ch.id as charger_id, ch.code as charger_code, conn.connector_id, t.measured_at, t.status, t.power_w, t.energy_kwh, t.current_a, t.session_id, t.error_code, now() - t.measured_at as data_age from ems.asset_ev_charger ch -- konektory za posledních 30 dní (tabulka konektorů neexistuje; konektor bez -- telemetrie 30 dní je pro „latest“ dashboard mrtvý) left join lateral ( select distinct tc.connector_id from ems.telemetry_ev_charger tc where tc.charger_id = ch.id and tc.measured_at >= now() - interval '30 days' ) conn on true left join lateral ( select te.measured_at, te.status, te.power_w, te.energy_kwh, te.current_a, te.session_id, te.error_code from ems.telemetry_ev_charger te where te.charger_id = ch.id and te.connector_id = conn.connector_id order by te.measured_at desc limit 1 ) t on true where t.measured_at is not null; comment on view ems.vw_latest_ev_charger is 'Nejnovější telemetrická data pro každý konektor EV nabíječky (LATERAL per-konektor, PK index). Slouží pro dashboard a řízení nabíjení.'; -- ------------------------------------------------------------ create or replace view ems.vw_latest_heat_pump with (security_invoker = false) as select hp.site_id, hp.id as heat_pump_id, hp.code as heat_pump_code, t.measured_at, t.outdoor_temp_c, t.tuv_tank_temp_c, t.water_outlet_temp_c, t.power_w, t.operating_mode, t.cop_actual, t.defrost_active, t.alarm_code, -- Odhadovaný COP pro aktuální venkovní teplotu ems.fn_cop_estimate(hp.id, t.outdoor_temp_c) as cop_estimated, now() - t.measured_at as data_age from ems.asset_heat_pump hp left join lateral ( select thp.measured_at, thp.outdoor_temp_c, thp.tuv_tank_temp_c, thp.water_outlet_temp_c, thp.power_w, thp.operating_mode, thp.cop_actual, thp.defrost_active, thp.alarm_code from ems.telemetry_heat_pump thp where thp.heat_pump_id = hp.id order by thp.measured_at desc limit 1 ) t on true; comment on view ems.vw_latest_heat_pump is 'Nejnovější telemetrická data pro každé tepelné čerpadlo včetně odhadovaného COP. Slouží pro real-time dashboard a rozhodovací logiku plánování.';