diff --git a/db/migration/V045__seed_site_kv1.sql b/db/migration/V045__seed_site_kv1.sql new file mode 100644 index 0000000..41a04e0 --- /dev/null +++ b/db/migration/V045__seed_site_kv1.sql @@ -0,0 +1,201 @@ +-- ============================================================= +-- V045__seed_site_kv1.sql +-- Idempotentní seed lokality KV1 (viz docs/new-site-setup-template.md). +-- 25 A přívod → import max 17 kW; přetok / export max 8 kW. +-- Nákup fixní 5,25 Kč/kWh bez DPH (jednotná sazba – na místě není NT tarif; HDO NULL). +-- Prodej na spotu jako home-01 (marže sell -0,02 Kč/kWh). +-- Deye 12 kW LV, baterie 12,5 kWh, 0,5C; Waveshare 172.16.2.10. Bez Loxone. +-- Start: MANUAL (EMS nezapisuje setpointy); fyzicky Deye PASSIVE dle poznámky. +-- ============================================================= + +DO $$ +DECLARE + v_site_code TEXT := 'KV1'; + + v_host_deye TEXT := '172.16.2.10'; + v_port_deye INT := 502; + + v_site_id INT; + v_ep_deye INT; + v_inv_main INT; +BEGIN + INSERT INTO ems.site (code, name, timezone, latitude, longitude, active, notes) + VALUES ( + v_site_code, + 'KV1', + 'Europe/Prague', + 49.23988687187006, + 17.47170575741328, + true, + 'Připojení max 25 A → import cca 17 kW; povolený přetok / export 8 kW. ' + 'Waveshare RS485→TCP ' || v_host_deye || '. Loxone na instalaci není. ' + 'Provozní start: EMS režim MANUAL (bez zápisů); střídač nechat v PASSIVE do ověření.' + ) + ON CONFLICT (code) DO UPDATE SET + name = EXCLUDED.name, + timezone = EXCLUDED.timezone, + latitude = EXCLUDED.latitude, + longitude = EXCLUDED.longitude, + active = EXCLUDED.active, + notes = EXCLUDED.notes + RETURNING id INTO v_site_id; + + SELECT se.id INTO v_ep_deye + FROM ems.site_endpoint se + WHERE se.site_id = v_site_id + AND se.endpoint_type = 'modbus_tcp' + AND se.notes ILIKE '%Deye%' + ORDER BY se.id + LIMIT 1; + + IF v_ep_deye IS NULL THEN + INSERT INTO ems.site_endpoint ( + site_id, endpoint_type, host, port, protocol, unit_id, enabled, notes + ) + VALUES ( + v_site_id, 'modbus_tcp', v_host_deye, v_port_deye, 'modbus_tcp', 1, true, + 'Deye 12kW LV – Modbus TCP (Waveshare).' + ) + RETURNING id INTO v_ep_deye; + END IF; + + INSERT INTO ems.site_grid_connection ( + site_id, max_import_power_w, max_export_power_w, no_export, reserved_capacity_w, notes + ) + VALUES ( + v_site_id, 17000, 8000, false, 0, + 'Max 25 A přívod → cca 17 kW import; přetok do sítě max 8 kW.' + ) + ON CONFLICT (site_id) DO UPDATE SET + max_import_power_w = EXCLUDED.max_import_power_w, + max_export_power_w = EXCLUDED.max_export_power_w, + no_export = EXCLUDED.no_export, + reserved_capacity_w = EXCLUDED.reserved_capacity_w, + notes = EXCLUDED.notes; + + IF NOT EXISTS ( + SELECT 1 FROM ems.site_market_config smc + WHERE smc.site_id = v_site_id AND smc.valid_to IS NULL + ) THEN + INSERT INTO ems.site_market_config ( + site_id, + purchase_pricing_mode, sale_pricing_mode, + buy_margin_fixed_czk, buy_margin_percent, + sell_margin_fixed_czk, sell_margin_percent, + currency, valid_from, valid_to, notes, + tariff_id, hdo_code_id, system_services_czk_kwh, ote_fee_czk_kwh, + buy_fixed_energy_nt_czk_kwh, buy_fixed_vt_surcharge_czk_kwh + ) + VALUES ( + v_site_id, + 'fixed', 'spot', + 0, 0, + -0.020, 0, + 'CZK', now(), NULL, + 'Nákup fixní 5,25 Kč/kWh bez DPH (jednotná sazba; NT tarif na místě není – bez HDO okna). ' + 'Prodej na spotu jako home-01 (sell_margin_fixed -0,02 Kč/kWh). ' + 'Distribuce v efektivní ceně 0 (tariff_id NULL).', + NULL, + NULL, + 0, + 0, + 5.25, + 0 + ); + END IF; + + INSERT INTO ems.site_operating_mode (site_id, mode_code, activated_by, notes) + VALUES ( + v_site_id, + 'MANUAL', + 'migration:V045_seed_site_kv1', + 'Start MANUAL; střídač PASSIVE. Po ověření přepnout na AUTO a Deye dle plánu.' + ) + ON CONFLICT (site_id) DO NOTHING; + + SELECT ai.id INTO v_inv_main + FROM ems.asset_inverter ai + WHERE ai.site_id = v_site_id AND ai.code = 'deye-main' + LIMIT 1; + + IF v_inv_main IS NULL THEN + INSERT INTO ems.asset_inverter ( + site_id, code, manufacturer, model, endpoint_id, + max_charge_power_w, max_discharge_power_w, max_export_power_w, + max_ac_output_w, max_dc_input_w, max_battery_charge_w, max_battery_discharge_w, + gen_port_max_power_w, + controllable, active, notes + ) + VALUES ( + v_site_id, + 'deye-main', + 'Deye', + NULL, + v_ep_deye, + 6250, 6250, 8000, + 12000, 15000, 6250, 6250, + NULL, + true, true, + '12kW LV hybrid. BMS max proud z/do baterie 280 A; plánování dle 0,5C ≈ 6,25 kW. ' + 'Export do DS max 8 kW dle site_grid_connection.' + ) + RETURNING id INTO v_inv_main; + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM ems.asset_battery ab + WHERE ab.site_id = v_site_id AND ab.code = 'bat-main' + ) THEN + INSERT INTO ems.asset_battery ( + site_id, inverter_id, code, + usable_capacity_wh, min_soc_percent, reserve_soc_percent, max_soc_percent, + charge_efficiency, discharge_efficiency, degradation_cost_czk_kwh, + max_charge_c_rate, max_discharge_c_rate, bms_max_charge_w, bms_max_discharge_w + ) + VALUES ( + v_site_id, v_inv_main, 'bat-main', + 12500, + 10, 15, 95, + 0.95, 0.95, + 0.50, + 0.5, 0.5, + 6250, 6250 + ); + END IF; + + -- String 1: 9×460 Wp, sklon 50°, azimut 150° (řiditelné) + IF NOT EXISTS ( + SELECT 1 FROM ems.asset_pv_array ap + WHERE ap.site_id = v_site_id AND ap.code = 'pv-str-1' + ) THEN + INSERT INTO ems.asset_pv_array ( + site_id, inverter_id, code, name, + nominal_power_wp, azimuth_deg, tilt_deg, module_count, shading_factor, + controllable, telemetry_source, notes + ) + VALUES ( + v_site_id, v_inv_main, 'pv-str-1', 'String 1 – 9×460 Wp', + 4140, 150, 50, 9, 1.0, true, 'pv_strings', + 'Hlavní telemetrie stringů Deye; druhý string má telemetry_source NULL.' + ); + END IF; + + -- String 2: 7×620 Wp, sklon 50°, azimut 241° (řiditelné) + IF NOT EXISTS ( + SELECT 1 FROM ems.asset_pv_array ap + WHERE ap.site_id = v_site_id AND ap.code = 'pv-str-2' + ) THEN + INSERT INTO ems.asset_pv_array ( + site_id, inverter_id, code, name, + nominal_power_wp, azimuth_deg, tilt_deg, module_count, shading_factor, + controllable, telemetry_source, notes + ) + VALUES ( + v_site_id, v_inv_main, 'pv-str-2', 'String 2 – 7×620 Wp', + 4340, 241, 50, 7, 1.0, true, NULL, + 'Vlastní predikce orientace; telemetrie sdílená se stringem 1.' + ); + END IF; + +END; +$$;