nova stranka flow a obsluha
This commit is contained in:
28
db/migration/V042__energy_flow_columns.sql
Normal file
28
db/migration/V042__energy_flow_columns.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
-- =============================================================
|
||||
-- V042 – Energy flow decomposition (7 directional flows per 15min)
|
||||
-- Plní se v ems.fn_fill_audit_interval (prioritní alokace per minuta).
|
||||
-- =============================================================
|
||||
|
||||
ALTER TABLE ems.audit_interval
|
||||
ADD COLUMN IF NOT EXISTS flow_pv_to_load_wh NUMERIC(10,1),
|
||||
ADD COLUMN IF NOT EXISTS flow_pv_to_batt_wh NUMERIC(10,1),
|
||||
ADD COLUMN IF NOT EXISTS flow_pv_to_grid_wh NUMERIC(10,1),
|
||||
ADD COLUMN IF NOT EXISTS flow_batt_to_load_wh NUMERIC(10,1),
|
||||
ADD COLUMN IF NOT EXISTS flow_batt_to_grid_wh NUMERIC(10,1),
|
||||
ADD COLUMN IF NOT EXISTS flow_grid_to_load_wh NUMERIC(10,1),
|
||||
ADD COLUMN IF NOT EXISTS flow_grid_to_batt_wh NUMERIC(10,1);
|
||||
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_pv_to_load_wh IS
|
||||
'Modelovaný tok FVE → spotřeba (Wh/slot). Per-minutová prioritní alokace: PV nejdřív load.';
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_pv_to_batt_wh IS
|
||||
'Modelovaný tok FVE → nabíjení baterie (Wh/slot).';
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_pv_to_grid_wh IS
|
||||
'Modelovaný tok FVE → export do sítě (Wh/slot).';
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_batt_to_load_wh IS
|
||||
'Modelovaný tok vybití baterie → spotřeba (Wh/slot).';
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_batt_to_grid_wh IS
|
||||
'Modelovaný tok vybití baterie → export (Wh/slot).';
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_grid_to_load_wh IS
|
||||
'Modelovaný tok import ze sítě → spotřeba (Wh/slot).';
|
||||
COMMENT ON COLUMN ems.audit_interval.flow_grid_to_batt_wh IS
|
||||
'Modelovaný tok import ze sítě → nabíjení baterie (Wh/slot).';
|
||||
@@ -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.';
|
||||
|
||||
32
db/views/R__vw_energy_flows.sql
Normal file
32
db/views/R__vw_energy_flows.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
-- =============================================================
|
||||
-- R__vw_energy_flows.sql
|
||||
-- Denní agregace 6 základních Wh + 7 směrových toků z audit_interval
|
||||
-- Repeatable migration (závisí na audit_interval + V042 sloupcech)
|
||||
-- =============================================================
|
||||
|
||||
DROP VIEW IF EXISTS ems.vw_energy_flows_daily CASCADE;
|
||||
|
||||
CREATE VIEW ems.vw_energy_flows_daily AS
|
||||
SELECT
|
||||
site_id,
|
||||
(date_trunc('day', interval_start AT TIME ZONE 'Europe/Prague'))::date AS day_local,
|
||||
ROUND(SUM(COALESCE(actual_pv_production_wh, 0)) / 1000, 3) AS pv_production_kwh,
|
||||
ROUND(SUM(COALESCE(actual_grid_import_wh, 0)) / 1000, 3) AS grid_import_kwh,
|
||||
ROUND(SUM(COALESCE(actual_grid_export_wh, 0)) / 1000, 3) AS grid_export_kwh,
|
||||
ROUND(SUM(COALESCE(actual_batt_charge_wh, 0)) / 1000, 3) AS batt_charge_kwh,
|
||||
ROUND(SUM(COALESCE(actual_batt_discharge_wh, 0)) / 1000, 3) AS batt_discharge_kwh,
|
||||
ROUND(SUM(COALESCE(actual_load_consumption_wh, 0)) / 1000, 3) AS load_kwh,
|
||||
ROUND(SUM(COALESCE(flow_pv_to_load_wh, 0)) / 1000, 3) AS pv_to_load_kwh,
|
||||
ROUND(SUM(COALESCE(flow_pv_to_batt_wh, 0)) / 1000, 3) AS pv_to_batt_kwh,
|
||||
ROUND(SUM(COALESCE(flow_pv_to_grid_wh, 0)) / 1000, 3) AS pv_to_grid_kwh,
|
||||
ROUND(SUM(COALESCE(flow_batt_to_load_wh, 0)) / 1000, 3) AS batt_to_load_kwh,
|
||||
ROUND(SUM(COALESCE(flow_batt_to_grid_wh, 0)) / 1000, 3) AS batt_to_grid_kwh,
|
||||
ROUND(SUM(COALESCE(flow_grid_to_load_wh, 0)) / 1000, 3) AS grid_to_load_kwh,
|
||||
ROUND(SUM(COALESCE(flow_grid_to_batt_wh, 0)) / 1000, 3) AS grid_to_batt_kwh
|
||||
FROM ems.audit_interval
|
||||
GROUP BY
|
||||
site_id,
|
||||
(date_trunc('day', interval_start AT TIME ZONE 'Europe/Prague'))::date;
|
||||
|
||||
COMMENT ON VIEW ems.vw_energy_flows_daily IS
|
||||
'Denní součty energie a modelovaných toků (prioritní alokace z fn_fill_audit_interval). kWh z Wh sloupců.';
|
||||
@@ -35,6 +35,7 @@ GRANT SELECT ON ems.market_price_stats TO ems_anon;
|
||||
GRANT SELECT ON ems.tuv_usage_stats TO ems_anon;
|
||||
GRANT SELECT ON ems.baseline_load_forecast_accuracy TO ems_anon;
|
||||
GRANT SELECT ON ems.vw_baseline_load_forecast_accuracy_daily TO ems_anon;
|
||||
GRANT SELECT ON ems.vw_energy_flows_daily TO ems_anon;
|
||||
|
||||
|
||||
grant select on ems.asset_heat_pump to ems_anon;
|
||||
|
||||
Reference in New Issue
Block a user