nova stranka flow a obsluha
All checks were successful
deploy / deploy (push) Successful in 8m52s
test / smoke-test (push) Successful in 5s

This commit is contained in:
Dusan Vojacek
2026-04-10 22:13:58 +02:00
parent 64221f701a
commit f714cab0ab
14 changed files with 1670 additions and 4 deletions

View File

@@ -45,6 +45,37 @@ DECLARE
v_counter_export_last BIGINT;
v_delta_import NUMERIC;
v_delta_export NUMERIC;
-- 7 směrových toků (prioritní alokace per minuta; součet W/60 = Wh)
r_flow RECORD;
v_flow_samples INT := 0;
v_acc_ptl NUMERIC := 0;
v_acc_ptb NUMERIC := 0;
v_acc_ptg NUMERIC := 0;
v_acc_btl NUMERIC := 0;
v_acc_btg NUMERIC := 0;
v_acc_gtl NUMERIC := 0;
v_acc_gtb NUMERIC := 0;
v_pv NUMERIC;
v_load_m NUMERIC;
v_gi NUMERIC;
v_ge NUMERIC;
v_bc NUMERIC;
v_bd NUMERIC;
v_ptl NUMERIC;
v_ptb NUMERIC;
v_ptg NUMERIC;
v_btl NUMERIC;
v_btg NUMERIC;
v_gtl NUMERIC;
v_gtb NUMERIC;
v_flow_pv_to_load_wh NUMERIC;
v_flow_pv_to_batt_wh NUMERIC;
v_flow_pv_to_grid_wh NUMERIC;
v_flow_batt_to_load_wh NUMERIC;
v_flow_batt_to_grid_wh NUMERIC;
v_flow_grid_to_load_wh NUMERIC;
v_flow_grid_to_batt_wh NUMERIC;
BEGIN
-- Najít aktivní plán pro tento interval
SELECT pi.* INTO v_plan
@@ -195,6 +226,58 @@ BEGIN
);
END LOOP;
-- Prioritní alokace toků: PV → load → batt charge → export; pak batt discharge → load/export; grid → zbytek
FOR r_flow IN
SELECT pv_power_w, grid_power_w, battery_power_w, load_power_w
FROM ems.telemetry_inverter
WHERE site_id = p_site_id
AND measured_at >= p_interval_start
AND measured_at < v_interval_end
ORDER BY measured_at
LOOP
v_flow_samples := v_flow_samples + 1;
v_pv := GREATEST(COALESCE(r_flow.pv_power_w, 0)::NUMERIC, 0);
v_load_m := GREATEST(COALESCE(r_flow.load_power_w, 0)::NUMERIC, 0);
v_gi := GREATEST(COALESCE(r_flow.grid_power_w, 0)::NUMERIC, 0);
v_ge := ABS(LEAST(COALESCE(r_flow.grid_power_w, 0)::NUMERIC, 0));
v_bc := ABS(LEAST(COALESCE(r_flow.battery_power_w, 0)::NUMERIC, 0));
v_bd := GREATEST(COALESCE(r_flow.battery_power_w, 0)::NUMERIC, 0);
v_ptl := LEAST(v_pv, v_load_m);
v_ptb := LEAST(v_pv - v_ptl, v_bc);
v_ptg := LEAST(v_pv - v_ptl - v_ptb, v_ge);
v_btl := LEAST(v_bd, v_load_m - v_ptl);
v_btg := LEAST(v_bd - v_btl, GREATEST(0::NUMERIC, v_ge - v_ptg));
v_gtl := GREATEST(0::NUMERIC, v_load_m - v_ptl - v_btl);
v_gtb := GREATEST(0::NUMERIC, v_bc - v_ptb);
v_acc_ptl := v_acc_ptl + v_ptl;
v_acc_ptb := v_acc_ptb + v_ptb;
v_acc_ptg := v_acc_ptg + v_ptg;
v_acc_btl := v_acc_btl + v_btl;
v_acc_btg := v_acc_btg + v_btg;
v_acc_gtl := v_acc_gtl + v_gtl;
v_acc_gtb := v_acc_gtb + v_gtb;
END LOOP;
IF v_flow_samples = 0 THEN
v_flow_pv_to_load_wh := NULL;
v_flow_pv_to_batt_wh := NULL;
v_flow_pv_to_grid_wh := NULL;
v_flow_batt_to_load_wh := NULL;
v_flow_batt_to_grid_wh := NULL;
v_flow_grid_to_load_wh := NULL;
v_flow_grid_to_batt_wh := NULL;
ELSE
v_flow_pv_to_load_wh := ROUND(v_acc_ptl / 60, 1);
v_flow_pv_to_batt_wh := ROUND(v_acc_ptb / 60, 1);
v_flow_pv_to_grid_wh := ROUND(v_acc_ptg / 60, 1);
v_flow_batt_to_load_wh := ROUND(v_acc_btl / 60, 1);
v_flow_batt_to_grid_wh := ROUND(v_acc_btg / 60, 1);
v_flow_grid_to_load_wh := ROUND(v_acc_gtl / 60, 1);
v_flow_grid_to_batt_wh := ROUND(v_acc_gtb / 60, 1);
END IF;
-- Upsert do audit_interval
INSERT INTO ems.audit_interval (
site_id, interval_start, planning_run_id,
@@ -213,7 +296,14 @@ BEGIN
actual_batt_charge_wh,
actual_batt_discharge_wh,
actual_pv_production_wh,
actual_load_consumption_wh
actual_load_consumption_wh,
flow_pv_to_load_wh,
flow_pv_to_batt_wh,
flow_pv_to_grid_wh,
flow_batt_to_load_wh,
flow_batt_to_grid_wh,
flow_grid_to_load_wh,
flow_grid_to_batt_wh
) VALUES (
p_site_id, p_interval_start, v_run_id,
v_avg_pv_power_w,
@@ -237,7 +327,14 @@ BEGIN
v_batt_charge_wh,
v_batt_discharge_wh,
v_pv_production_wh,
v_load_consumption_wh
v_load_consumption_wh,
v_flow_pv_to_load_wh,
v_flow_pv_to_batt_wh,
v_flow_pv_to_grid_wh,
v_flow_batt_to_load_wh,
v_flow_batt_to_grid_wh,
v_flow_grid_to_load_wh,
v_flow_grid_to_batt_wh
)
ON CONFLICT (site_id, interval_start) DO UPDATE SET
planning_run_id = EXCLUDED.planning_run_id,
@@ -258,7 +355,14 @@ BEGIN
actual_batt_charge_wh = EXCLUDED.actual_batt_charge_wh,
actual_batt_discharge_wh = EXCLUDED.actual_batt_discharge_wh,
actual_pv_production_wh = EXCLUDED.actual_pv_production_wh,
actual_load_consumption_wh = EXCLUDED.actual_load_consumption_wh;
actual_load_consumption_wh = EXCLUDED.actual_load_consumption_wh,
flow_pv_to_load_wh = EXCLUDED.flow_pv_to_load_wh,
flow_pv_to_batt_wh = EXCLUDED.flow_pv_to_batt_wh,
flow_pv_to_grid_wh = EXCLUDED.flow_pv_to_grid_wh,
flow_batt_to_load_wh = EXCLUDED.flow_batt_to_load_wh,
flow_batt_to_grid_wh = EXCLUDED.flow_batt_to_grid_wh,
flow_grid_to_load_wh = EXCLUDED.flow_grid_to_load_wh,
flow_grid_to_batt_wh = EXCLUDED.flow_grid_to_batt_wh;
END;
$$;
@@ -267,6 +371,7 @@ COMMENT ON FUNCTION ems.fn_fill_audit_interval(INT, TIMESTAMPTZ) IS
Agreguje průměry z telemetrie (střídač, EV, TČ), porovná se skutečným plánem a spočítá odchylky.
Nově: per-minutový split pro 6 energetických veličin (import/export/batt/PV/load Wh);
grid import/export primárně z delta Deye total counterů (reg 522-525), fallback per-minute.
7 směrových toků (flow_*_wh): prioritní alokace per minuta z telemetrie (PV→load→batt→export; baterie→load/export; síť→zbytek).
actual_cost_czk = per-direction (import_wh × buy - export_wh × sell).
Zelený bonus: součet přes pole s green_bonus_czk_kwh.
Volat každých 15 minut pro interval který právě skončil.';