138 lines
4.9 KiB
PL/PgSQL
138 lines
4.9 KiB
PL/PgSQL
-- =============================================================
|
||
-- R__005_fn_cop_estimate.sql
|
||
-- EMS Platform – odhad COP tepelného čerpadla dle venkovní teploty
|
||
-- Repeatable migration
|
||
-- =============================================================
|
||
|
||
CREATE OR REPLACE FUNCTION ems.fn_cop_estimate(
|
||
p_heat_pump_id INT,
|
||
p_outdoor_temp_c NUMERIC
|
||
)
|
||
RETURNS NUMERIC(4,2)
|
||
LANGUAGE plpgsql
|
||
STABLE
|
||
AS $$
|
||
DECLARE
|
||
v_cop_rated NUMERIC;
|
||
v_cop_ref_temp NUMERIC;
|
||
v_cop_estimated NUMERIC;
|
||
BEGIN
|
||
-- Načíst referenční COP a teplotu z konfigurace čerpadla
|
||
SELECT cop_rated, cop_temp_reference_c
|
||
INTO v_cop_rated, v_cop_ref_temp
|
||
FROM ems.asset_heat_pump
|
||
WHERE id = p_heat_pump_id;
|
||
|
||
IF v_cop_rated IS NULL OR v_cop_ref_temp IS NULL THEN
|
||
-- Fallback: obecný odhad pro vzduch-voda TČ bez konfigurace
|
||
-- Zdroj: přibližná lineární závislost COP na venkovní teplotě
|
||
-- COP ≈ 2.0 při -10°C, COP ≈ 4.5 při +15°C
|
||
v_cop_estimated := 2.0 + (p_outdoor_temp_c + 10.0) * (4.5 - 2.0) / 25.0;
|
||
ELSE
|
||
-- Lineární interpolace od referenčního bodu
|
||
-- COP klesá přibližně o 0.10 na každý stupeň poklesu venkovní teploty
|
||
-- Toto je zjednodušený model – zpřesnit dle skutečných dat z tepelky
|
||
v_cop_estimated := v_cop_rated + (p_outdoor_temp_c - v_cop_ref_temp) * 0.10;
|
||
END IF;
|
||
|
||
-- Omezit na rozumné hodnoty (COP vzduch-voda reálně 1.5–6.0)
|
||
v_cop_estimated := GREATEST(1.5, LEAST(6.0, v_cop_estimated));
|
||
|
||
RETURN ROUND(v_cop_estimated, 2);
|
||
END;
|
||
$$;
|
||
|
||
COMMENT ON FUNCTION ems.fn_cop_estimate(INT, NUMERIC) IS
|
||
'Odhadne COP tepelného čerpadla pro danou venkovní teplotu.
|
||
Používá lineární model od referenčního bodu (cop_rated při cop_temp_reference_c).
|
||
Výstup slouží k rozhodnutí zda je výhodné spustit TČ v daném intervalu.
|
||
Přesnost modelu zlepšit kalibrací na historická data (cop_actual z telemetrie).
|
||
Výsledek omezen na rozsah 1.5–6.0.';
|
||
|
||
-- ------------------------------------------------------------
|
||
|
||
CREATE OR REPLACE FUNCTION ems.fn_heat_pump_cost_per_kwh_heat(
|
||
p_heat_pump_id INT,
|
||
p_outdoor_temp_c NUMERIC,
|
||
p_buy_price_czk_kwh NUMERIC
|
||
)
|
||
RETURNS NUMERIC(8,4)
|
||
LANGUAGE sql
|
||
STABLE
|
||
AS $$
|
||
-- Cena za 1 kWh tepla = cena elektřiny / COP
|
||
-- Čím vyšší COP, tím levnější teplo
|
||
SELECT ROUND(
|
||
p_buy_price_czk_kwh / NULLIF(ems.fn_cop_estimate(p_heat_pump_id, p_outdoor_temp_c), 0),
|
||
4
|
||
);
|
||
$$;
|
||
|
||
COMMENT ON FUNCTION ems.fn_heat_pump_cost_per_kwh_heat(INT, NUMERIC, NUMERIC) IS
|
||
'Vypočte efektivní cenu za 1 kWh dodaného tepla v Kč.
|
||
Vstup: ID tepelného čerpadla, venkovní teplota, nákupní cena elektřiny.
|
||
Výstup slouží k porovnání výhodnosti ohřevu v různých časových intervalech.
|
||
Nižší hodnota = výhodnější čas pro provoz TČ.';
|
||
|
||
-- ------------------------------------------------------------
|
||
|
||
CREATE OR REPLACE FUNCTION ems.fn_heat_pump_should_run(
|
||
p_heat_pump_id INT,
|
||
p_interval_start TIMESTAMPTZ,
|
||
p_outdoor_temp_c NUMERIC,
|
||
p_tuv_tank_temp_c NUMERIC,
|
||
p_buy_price_czk_kwh NUMERIC,
|
||
p_max_cost_threshold NUMERIC DEFAULT 3.0 -- Kč/kWh tepla – maximální akceptovatelná cena
|
||
)
|
||
RETURNS BOOLEAN
|
||
LANGUAGE plpgsql
|
||
STABLE
|
||
AS $$
|
||
DECLARE
|
||
v_hp ems.asset_heat_pump%ROWTYPE;
|
||
v_cost_per_kwh NUMERIC;
|
||
v_override BOOLEAN;
|
||
BEGIN
|
||
SELECT * INTO v_hp FROM ems.asset_heat_pump WHERE id = p_heat_pump_id;
|
||
|
||
-- Kontrola override (blokování TČ)
|
||
SELECT EXISTS(
|
||
SELECT 1 FROM ems.site_override
|
||
WHERE site_id = v_hp.site_id
|
||
AND override_type = 'block_heat_pump'
|
||
AND valid_from <= p_interval_start
|
||
AND (valid_to IS NULL OR valid_to > p_interval_start)
|
||
) INTO v_override;
|
||
|
||
IF v_override THEN
|
||
RETURN false;
|
||
END IF;
|
||
|
||
-- Povinný ohřev: teplota pod minimem
|
||
IF p_tuv_tank_temp_c IS NOT NULL AND p_tuv_tank_temp_c < v_hp.tuv_min_temp_c THEN
|
||
RETURN true;
|
||
END IF;
|
||
|
||
-- Zásobník je plný
|
||
IF p_tuv_tank_temp_c IS NOT NULL AND p_tuv_tank_temp_c >= v_hp.tuv_max_temp_c THEN
|
||
RETURN false;
|
||
END IF;
|
||
|
||
-- Ekonomické rozhodnutí: spustit pokud cena tepla je pod prahem
|
||
v_cost_per_kwh := ems.fn_heat_pump_cost_per_kwh_heat(
|
||
p_heat_pump_id, p_outdoor_temp_c, p_buy_price_czk_kwh
|
||
);
|
||
|
||
RETURN v_cost_per_kwh <= p_max_cost_threshold;
|
||
END;
|
||
$$;
|
||
|
||
COMMENT ON FUNCTION ems.fn_heat_pump_should_run(INT, TIMESTAMPTZ, NUMERIC, NUMERIC, NUMERIC, NUMERIC) IS
|
||
'Rozhodne zda má tepelné čerpadlo v daném intervalu běžet.
|
||
Logika priorit:
|
||
1. Pokud existuje override block_heat_pump → false.
|
||
2. Pokud teplota zásobníku pod tuv_min_temp_c → true (povinný ohřev).
|
||
3. Pokud zásobník nad tuv_max_temp_c → false.
|
||
4. Jinak ekonomické rozhodnutí: spustit pokud cena tepla ≤ p_max_cost_threshold Kč/kWh.
|
||
Výhodné časy jsou přes poledne v chladných měsících (vyšší venkovní teplota = lepší COP).';
|