159 lines
4.8 KiB
SQL
159 lines
4.8 KiB
SQL
create or replace function ems.fn_site_full_status(p_site_id int)
|
|
returns jsonb
|
|
language sql
|
|
stable
|
|
as $fn$
|
|
select
|
|
case
|
|
when not exists (select 1 from ems.site s0 where s0.id = p_site_id) then
|
|
jsonb_build_object('error', 'not_found')
|
|
else jsonb_build_object(
|
|
'site',
|
|
(
|
|
select jsonb_build_object(
|
|
'id', s.id,
|
|
'code', s.code,
|
|
'name', s.name,
|
|
'timezone', s.timezone
|
|
)
|
|
from ems.site s
|
|
where s.id = p_site_id
|
|
),
|
|
'operating_mode',
|
|
(
|
|
select jsonb_build_object(
|
|
'mode_code', m.mode_code,
|
|
'mode_name', d.name,
|
|
'activated_at', m.activated_at,
|
|
'activated_by', m.activated_by
|
|
)
|
|
from ems.site_operating_mode m
|
|
join ems.operating_mode_def d on d.code = m.mode_code
|
|
where m.site_id = p_site_id
|
|
),
|
|
'heartbeat',
|
|
(
|
|
select jsonb_build_object(
|
|
'last_seen', hb.last_seen,
|
|
'status', hb.status
|
|
)
|
|
from ems.site_heartbeat hb
|
|
where hb.site_id = p_site_id
|
|
),
|
|
'inverter_latest',
|
|
(
|
|
select to_jsonb(li.*)
|
|
from ems.vw_latest_inverter li
|
|
where li.site_id = p_site_id
|
|
order by li.measured_at desc nulls last
|
|
limit 1
|
|
),
|
|
'ev_chargers',
|
|
coalesce(
|
|
(
|
|
select jsonb_agg(
|
|
jsonb_build_object(
|
|
'code', v.code,
|
|
'status', v.status,
|
|
'power_w', v.power_w,
|
|
'measured_at', v.measured_at
|
|
)
|
|
order by v.measured_at desc nulls last
|
|
)
|
|
from (
|
|
select distinct on (evc.charger_id)
|
|
evc.charger_code as code,
|
|
evc.status,
|
|
evc.power_w,
|
|
evc.measured_at
|
|
from ems.vw_latest_ev_charger evc
|
|
where evc.site_id = p_site_id
|
|
order by evc.charger_id, evc.measured_at desc nulls last
|
|
) v
|
|
),
|
|
'[]'::jsonb
|
|
),
|
|
'heat_pump_latest',
|
|
(
|
|
select jsonb_build_object(
|
|
'power_w', hp.power_w,
|
|
'tuv_tank_temp_c', hp.tuv_tank_temp_c,
|
|
'measured_at', hp.measured_at
|
|
)
|
|
from ems.vw_latest_heat_pump hp
|
|
where hp.site_id = p_site_id
|
|
order by hp.measured_at desc nulls last
|
|
limit 1
|
|
),
|
|
'battery_limits',
|
|
(
|
|
select jsonb_build_object(
|
|
'reserve_soc', min(ab.reserve_soc_percent)::float,
|
|
'min_soc', min(ab.min_soc_percent)::float
|
|
)
|
|
from ems.asset_battery ab
|
|
where ab.site_id = p_site_id
|
|
),
|
|
'active_plan',
|
|
(
|
|
select jsonb_build_object(
|
|
'id', pr.id,
|
|
'created_at', pr.created_at
|
|
)
|
|
from ems.planning_run pr
|
|
where pr.site_id = p_site_id
|
|
and pr.status = 'active'
|
|
order by pr.created_at desc
|
|
limit 1
|
|
),
|
|
'planning_intervals',
|
|
coalesce(
|
|
(
|
|
select jsonb_agg(
|
|
jsonb_build_object(
|
|
'interval_start', pi.interval_start,
|
|
'battery_setpoint_w', pi.battery_setpoint_w,
|
|
'load_baseline_w', pi.load_baseline_w,
|
|
'pv_a_forecast_raw_w', pi.pv_a_forecast_raw_w,
|
|
'pv_b_forecast_raw_w', pi.pv_b_forecast_raw_w,
|
|
'pv_a_forecast_solver_w', pi.pv_a_forecast_solver_w,
|
|
'pv_b_forecast_solver_w', pi.pv_b_forecast_solver_w
|
|
)
|
|
order by pi.interval_start
|
|
)
|
|
from ems.planning_interval pi
|
|
where pi.run_id = (
|
|
select pr2.id
|
|
from ems.planning_run pr2
|
|
where pr2.site_id = p_site_id
|
|
and pr2.status = 'active'
|
|
order by pr2.created_at desc
|
|
limit 1
|
|
)
|
|
),
|
|
'[]'::jsonb
|
|
),
|
|
'tomorrow_price_slot_count',
|
|
(
|
|
select count(*)::int
|
|
from ems.vw_site_effective_price vep
|
|
where vep.site_id = p_site_id
|
|
and (vep.interval_start at time zone coalesce(
|
|
nullif(trim((select s2.timezone from ems.site s2 where s2.id = p_site_id)), ''),
|
|
'Europe/Prague'
|
|
))::date = (
|
|
(
|
|
current_timestamp at time zone coalesce(
|
|
nullif(trim((select s3.timezone from ems.site s3 where s3.id = p_site_id)), ''),
|
|
'Europe/Prague'
|
|
)
|
|
)::date + 1
|
|
)
|
|
)
|
|
)
|
|
end;
|
|
$fn$;
|
|
|
|
comment on function ems.fn_site_full_status(int) is
|
|
'Raw data pro GET /status/full (věk telemetrie a alerty dopočítá Python).';
|