7.5 KiB
7.5 KiB
EMS planner bug triage — reference (MCP)
Všechno jen read-only SELECT. Server: user-postgres-ems, nástroj query.
Seznam lokalit a fn_plan_explain_bundle → ems-plan-explain/reference.md.
1) Bug typy (klasifikace)
| Typ | Popis | Typické flags / signály | Fix větev |
|---|---|---|---|
| A | Degradovaný solve — Infeasible retry krok 3+ | any_relaxed_solve, relaxed_neg_prep_window, evening_push_hard_suppressed |
Branch 1: granulární relaxace + failed-run journal |
| B | Večerní export chybí před neg dnem | Vysoké SoC ve špičce, grid_setpoint_w > 0 @ ~5 Kč buy, neg_evening_push_ts prázdné, zítra buy<0 / vysoká FVE |
Branch 2: neg-večer k reserve_soc |
| C | Fixní tarif — špatné nabíjení / žádný večerní push | evening_push_ts: [], SoC ~60–80 % ve slunci, v58 bc_pv=0 |
Branch 3: charge-slot-budget |
| D | Provoz / exekuce, ne LP | mode != AUTO, starý active run, ruční MANUAL |
Návrat do AUTO, ruční replan po fixu |
| E | GEN port / pole B při sell<0 | BA81 + deye_gen_microinverter_cutoff, audit export v sell<0 |
Branch 4: cutoff exekuce |
2) MCP — aktivní run + relax flags
Nahraď $site_id (např. 2 = home-01):
select pr.id,
pr.created_at,
pr.run_type,
pr.triggered_by,
pr.soc_at_replan_wh,
pr.solver_params->'inputs'->>'any_relaxed_solve' as relaxed,
pr.solver_params->'inputs'->>'relaxed_expensive_import' as r_exp_import,
pr.solver_params->'inputs'->>'relaxed_neg_buy_charge' as r_neg_buy,
pr.solver_params->'inputs'->>'relaxed_neg_prep_window' as r_neg_prep,
pr.solver_params->'inputs'->>'neg_sell_phases_fallback' as r_phases_off,
pr.solver_params->'inputs'->>'evening_push_hard_suppressed' as push_suppressed,
pr.solver_params->'inputs'->>'pre_neg_pv_export_forecast_ok' as pre_neg_ok,
pr.solver_params->'inputs'->>'neg_evening_push_ts' as neg_eve_push,
pr.solver_params->'inputs'->>'evening_push_ts' as evening_push,
pr.solver_params->'inputs'->>'charge_acquisition_buy_czk_kwh' as acq,
pr.solver_params->'inputs'->>'neg_sell_day_pv_usable_wh' as neg_pv_wh,
pr.solver_params->>'planner_build_tag' as tag
from ems.planning_run pr
where pr.site_id = $site_id
and pr.status = 'active'
order by pr.created_at desc
limit 1;
Poslední běhy (včetně comparison) za 48 h:
select pr.id, pr.status, pr.run_type, pr.created_at,
pr.solver_params->'inputs'->>'relaxed_neg_prep_window' as r3,
pr.solver_params->'inputs'->>'evening_push_hard_suppressed' as push_sup
from ems.planning_run pr
where pr.site_id = $site_id
and pr.created_at >= now() - interval '48 hours'
order by pr.created_at desc
limit 20;
3) Site archetypy (orientace)
| home-01 | BA81 | KV1 | |
|---|---|---|---|
| Buy | spot | fixed ~2,55 NT | fixed 5,25 |
block_export_on_negative_sell |
false | false | true |
| Neg sell fáze | 80 % prep | default | 100 % (off) |
deye_gen_microinverter_cutoff |
false | true | false |
planner_terminal_soc_value_factor |
0,9 | 0,2 | 0,2 |
| Typický večerní bug | A + B (relaxed + drží SoC) | C (no evening_push) | občas A, jinak OK |
Konfigurace z DB:
select s.code,
smc.purchase_pricing_mode,
sgc.block_export_on_negative_sell,
ai.deye_gen_microinverter_cutoff_enabled,
ab.reserve_soc_percent,
ab.min_soc_percent,
ab.planner_neg_sell_prep_soc_percent,
ab.planner_terminal_soc_value_factor
from ems.site s
left join ems.site_market_config smc
on smc.site_id = s.id and smc.valid_to is null
left join ems.site_grid_connection sgc on sgc.site_id = s.id
left join ems.asset_inverter ai
on ai.site_id = s.id and ai.code = 'deye-main'
left join ems.asset_battery ab
on ab.site_id = s.id and ab.code = 'bat-main'
where s.code in ('home-01', 'BA81', 'KV1');
4) Provozní režim a log
select mode_code from ems.site_operating_mode where site_id = $site_id;
select activated_at at time zone 'Europe/Prague' as ts_prague,
mode_code,
activated_by
from ems.site_operating_mode_log
where site_id = $site_id
order by activated_at desc
limit 8;
Rolling replan běží jen v AUTO.
5) Večerní okno — planning_interval
select pi.interval_start at time zone 'Europe/Prague' as slot_prague,
pi.battery_setpoint_w,
pi.grid_setpoint_w,
pi.battery_soc_target_pct,
pi.effective_buy_price,
pi.effective_sell_price
from ems.planning_interval pi
where pi.run_id = (
select id from ems.planning_run
where site_id = $site_id and status = 'active'
order by created_at desc limit 1
)
and pi.interval_start >= (current_timestamp at time zone 'Europe/Prague')::date
+ interval '17 hours'
and pi.interval_start < (current_timestamp at time zone 'Europe/Prague')::date
+ interval '1 day' + interval '6 hours'
order by pi.interval_start;
Červená vlajka: battery_setpoint_w = 0 a grid_setpoint_w > 0 při sell ~3 Kč a SoC > reserve — import místo exportu baterie.
6) Zítřejší neg ceny
select interval_start at time zone 'Europe/Prague' as slot_prague,
effective_buy_price_czk_kwh as buy,
effective_sell_price_czk_kwh as sell
from ems.vw_site_effective_price
where site_id = $site_id
and interval_start >= (current_timestamp at time zone 'Europe/Prague')::date
+ interval '1 day'
and interval_start < (current_timestamp at time zone 'Europe/Prague')::date
+ interval '2 days'
and (effective_buy_price_czk_kwh < 0 or effective_sell_price_czk_kwh < 0)
order by interval_start;
7) Slovník solver_params.inputs (výběr)
| Klíč | Význam |
|---|---|
evening_push_hard_suppressed |
true = bez tvrdého ge_bat push (typicky retry krok 3) |
relaxed_neg_prep_window |
Vypnuty neg-evening kotvy, prep hold, neg evening push |
pre_neg_pv_export_forecast_ok |
Cushion FVE v sell<0 okně — false → nemá exportovat ranní PV před neg |
neg_evening_push_ts |
Sloty D−1 večer pro vývoj před neg oknem |
charge_acquisition_buy_czk_kwh |
Účinná cena energie v baterii pro arbitráž exportu |
neg_sell_day_pv_usable_wh |
Forecast Wh do baterie v sell<0 okně zítřka |
morning_pre_neg_export_hard |
Tvrdý ranní export před sell<0 |
Plný snap: select ems.fn_planning_run_debug(<run_id>);
8) Fix větve (implementační plán v repu)
| Branch | Obsah | Priorita |
|---|---|---|
| 1 | Failed-run journal, bisect Infeasible, granulární relaxace | P0 |
| 2 | home-01 neg-večer → reserve_soc, oddělit push od prep relax |
P0 |
| 3 | charge-slot-budget v R__063, BA81/KV1 večerní export | P1 |
| 4 | BA81 GEN cutoff audit | P1 |
| 5 | Dynamický terminal SoC při future neg buy | P2 |
Detail: plán v .cursor/plans/ nebo docs/planning-changelog.md + docs/04-modules/planning-charge-slot-budget.md.
9) Ověření po fixu
pytest backend/tests/test_planning_dispatch_milp.py -k "evening or NegSell or Infeasible"
python scripts/diagnose_home01_infeasible.py
MCP po deployi — nový active run bez relaxed_neg_prep_window nebo s evening_push_hard_suppressed: false a večerní sloty s grid_setpoint_w < 0.