uprava adutiu - nacitani dalsich registru, uprava ekonomiky
Some checks failed
deploy / deploy (push) Failing after 1m15s
test / smoke-test (push) Successful in 2s

This commit is contained in:
Dusan Vojacek
2026-04-10 21:53:32 +02:00
parent 25090a9d95
commit 806274cf59
9 changed files with 440 additions and 130 deletions

View File

@@ -29,6 +29,22 @@ DECLARE
v_pv_b_production_wh NUMERIC;
v_array_prod_wh NUMERIC;
r_bonus RECORD;
-- per-minute Wh veličiny
v_grid_import_wh NUMERIC;
v_grid_export_wh NUMERIC;
v_batt_charge_wh NUMERIC;
v_batt_discharge_wh NUMERIC;
v_pv_production_wh NUMERIC;
v_load_consumption_wh NUMERIC;
-- Deye counter delta
v_counter_import_first BIGINT;
v_counter_import_last BIGINT;
v_counter_export_first BIGINT;
v_counter_export_last BIGINT;
v_delta_import NUMERIC;
v_delta_export NUMERIC;
BEGIN
-- Najít aktivní plán pro tento interval
SELECT pi.* INTO v_plan
@@ -42,24 +58,58 @@ BEGIN
v_run_id := v_plan.run_id;
-- Agregovat telemetrii střídače (průměr za 15min; agregace bez GROUP BY vrací vždy 1 řádek)
-- Agregovat telemetrii střídače: průměry (pro zpětnou kompatibilitu) + per-minute split pro Wh
SELECT
AVG(pv_power_w)::INT,
AVG(battery_power_w)::INT,
AVG(grid_power_w)::INT,
AVG(load_power_w)::INT,
LAST(battery_soc_percent, measured_at)
LAST(battery_soc_percent, measured_at),
-- Per-minute split: každý vzorek × 1/60 h = Wh
ROUND(SUM(GREATEST(grid_power_w, 0))::NUMERIC / 60, 1),
ROUND(SUM(ABS(LEAST(grid_power_w, 0)))::NUMERIC / 60, 1),
ROUND(SUM(ABS(LEAST(battery_power_w, 0)))::NUMERIC / 60, 1),
ROUND(SUM(GREATEST(battery_power_w, 0))::NUMERIC / 60, 1),
ROUND(SUM(GREATEST(pv_power_w, 0))::NUMERIC / 60, 1),
ROUND(SUM(GREATEST(load_power_w, 0))::NUMERIC / 60, 1),
-- Deye total energy counter delta
FIRST(grid_import_total_wh, measured_at),
LAST(grid_import_total_wh, measured_at),
FIRST(grid_export_total_wh, measured_at),
LAST(grid_export_total_wh, measured_at)
INTO
v_avg_pv_power_w,
v_avg_battery_power_w,
v_avg_grid_power_w,
v_avg_load_power_w,
v_last_soc
v_last_soc,
v_grid_import_wh,
v_grid_export_wh,
v_batt_charge_wh,
v_batt_discharge_wh,
v_pv_production_wh,
v_load_consumption_wh,
v_counter_import_first,
v_counter_import_last,
v_counter_export_first,
v_counter_export_last
FROM ems.telemetry_inverter
WHERE site_id = p_site_id
AND measured_at >= p_interval_start
AND measured_at < v_interval_end;
-- Deye counter delta (primární zdroj pro grid import/export, pokud jsou čítače dostupné)
IF v_counter_import_first IS NOT NULL AND v_counter_import_last IS NOT NULL
AND v_counter_import_last >= v_counter_import_first THEN
v_delta_import := v_counter_import_last - v_counter_import_first;
v_grid_import_wh := v_delta_import;
END IF;
IF v_counter_export_first IS NOT NULL AND v_counter_export_last IS NOT NULL
AND v_counter_export_last >= v_counter_export_first THEN
v_delta_export := v_counter_export_last - v_counter_export_first;
v_grid_export_wh := v_delta_export;
END IF;
-- Agregovat EV nabíječky (součet průměrů po charger_id)
SELECT COALESCE(SUM(avg_power), 0)::INT
INTO v_sum_ev_power_w
@@ -84,12 +134,10 @@ BEGIN
v_buy_price := ems.fn_effective_buy_price(p_site_id, p_interval_start);
v_sell_price := ems.fn_effective_sell_price(p_site_id, p_interval_start);
-- Skutečné náklady (kladný grid = nákup, záporný = prodej)
IF v_avg_grid_power_w IS NOT NULL THEN
v_actual_cost := (v_avg_grid_power_w::NUMERIC / 1000.0 / 4.0)
* CASE WHEN v_avg_grid_power_w >= 0
THEN COALESCE(v_buy_price, 0)
ELSE COALESCE(v_sell_price, 0) END;
-- Skutečné náklady per-direction (import × buy - export × sell)
IF v_grid_import_wh IS NOT NULL OR v_grid_export_wh IS NOT NULL THEN
v_actual_cost := COALESCE(v_grid_import_wh, 0) / 1000.0 * COALESCE(v_buy_price, 0)
- COALESCE(v_grid_export_wh, 0) / 1000.0 * COALESCE(v_sell_price, 0);
END IF;
-- Zelený bonus: výroba bonusových polí z reálné telemetrie (Wh = průměr W × 0,25 h)
@@ -122,7 +170,6 @@ BEGIN
AND ti.measured_at < v_interval_end;
END IF;
-- Fallback na forecast pokud telemetrie není k dispozici
IF v_array_prod_wh IS NULL THEN
SELECT fpi.power_w * 0.25
INTO v_array_prod_wh
@@ -160,7 +207,13 @@ BEGIN
pv_b_production_wh,
green_bonus_czk,
deviation_grid_w,
deviation_cost_czk
deviation_cost_czk,
actual_grid_import_wh,
actual_grid_export_wh,
actual_batt_charge_wh,
actual_batt_discharge_wh,
actual_pv_production_wh,
actual_load_consumption_wh
) VALUES (
p_site_id, p_interval_start, v_run_id,
v_avg_pv_power_w,
@@ -178,7 +231,13 @@ BEGIN
ELSE NULL END,
CASE WHEN v_plan.run_id IS NOT NULL
THEN ROUND(v_actual_cost - COALESCE(v_plan.expected_cost_czk, 0), 4)
ELSE NULL END
ELSE NULL END,
v_grid_import_wh,
v_grid_export_wh,
v_batt_charge_wh,
v_batt_discharge_wh,
v_pv_production_wh,
v_load_consumption_wh
)
ON CONFLICT (site_id, interval_start) DO UPDATE SET
planning_run_id = EXCLUDED.planning_run_id,
@@ -193,15 +252,23 @@ BEGIN
pv_b_production_wh = EXCLUDED.pv_b_production_wh,
green_bonus_czk = EXCLUDED.green_bonus_czk,
deviation_grid_w = EXCLUDED.deviation_grid_w,
deviation_cost_czk = EXCLUDED.deviation_cost_czk;
deviation_cost_czk = EXCLUDED.deviation_cost_czk,
actual_grid_import_wh = EXCLUDED.actual_grid_import_wh,
actual_grid_export_wh = EXCLUDED.actual_grid_export_wh,
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;
END;
$$;
COMMENT ON FUNCTION ems.fn_fill_audit_interval(INT, TIMESTAMPTZ) IS
'Naplní nebo aktualizuje jeden řádek v audit_interval pro danou lokalitu a 15min interval.
Agreguje průměry z telemetrie (střídač, EV, TČ), porovná se skutečným plánem a spočítá odchylky.
Zelený bonus: součet přes pole s green_bonus_czk_kwh; výroba primárně z reálné telemetrie
(dle asset_pv_array.telemetry_source), fallback na forecast_pv_interval pokud telemetrie chybí.
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.
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.';
-- ============================================================