Files
ems/db/migration/V004__operating_modes.sql
Dusan Vojacek 8b4af663d8 Initial commit
Made-with: Cursor
2026-03-20 13:27:44 +01:00

118 lines
7.9 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =============================================================
-- V004__operating_modes.sql
-- EMS Platform provozní režimy lokalit
-- =============================================================
-- ============================================================
-- Číselník provozních režimů
-- ============================================================
CREATE TABLE ems.operating_mode_def (
code TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL,
ev_enabled BOOLEAN NOT NULL DEFAULT false,
heat_pump_enabled BOOLEAN NOT NULL DEFAULT false,
battery_mode TEXT NOT NULL, -- 'plan', 'self_sustain', 'charge_max', 'hold', 'none'
grid_mode TEXT NOT NULL, -- 'plan', 'import_ok', 'no_import', 'no_export', 'none'
loxone_mode_value INT NOT NULL, -- integer posílaný do Loxone Virtual Input
is_autonomous BOOLEAN NOT NULL DEFAULT false, -- Loxone umí sám bez EMS setpointů
sort_order INT NOT NULL DEFAULT 50
);
COMMENT ON TABLE ems.operating_mode_def IS 'Číselník provozních režimů systému. Každý režim definuje chování baterie, sítě a flexibilních zařízení.';
COMMENT ON COLUMN ems.operating_mode_def.code IS 'Unikátní kód režimu. Příklad: AUTO, SELF_SUSTAIN.';
COMMENT ON COLUMN ems.operating_mode_def.name IS 'Lidsky čitelný název režimu pro UI.';
COMMENT ON COLUMN ems.operating_mode_def.description IS 'Popis chování v daném režimu.';
COMMENT ON COLUMN ems.operating_mode_def.ev_enabled IS 'Zda je povoleno nabíjení EV v tomto režimu.';
COMMENT ON COLUMN ems.operating_mode_def.heat_pump_enabled IS 'Zda je tepelné čerpadlo povoleno v tomto režimu.';
COMMENT ON COLUMN ems.operating_mode_def.battery_mode IS 'Chování baterie: plan=dle EMS plánu, self_sustain=vybíjí do domu, charge_max=max nabíjení, hold=drží SoC, none=žádné akce.';
COMMENT ON COLUMN ems.operating_mode_def.grid_mode IS 'Chování vůči síti: plan=dle EMS, import_ok=import povolen, no_import=bez importu, no_export=bez exportu, none=žádné akce.';
COMMENT ON COLUMN ems.operating_mode_def.loxone_mode_value IS 'Celočíselná hodnota posílaná do Loxone Virtual Input EMS_Mode. Loxone interně přepíná stavový stroj.';
COMMENT ON COLUMN ems.operating_mode_def.is_autonomous IS 'Pokud true, Loxone zvládne tento režim bez průběžných setpointů od EMS (fallback bezpečný).';
COMMENT ON COLUMN ems.operating_mode_def.sort_order IS 'Pořadí zobrazení v UI.';
INSERT INTO ems.operating_mode_def
(code, name, description, ev_enabled, heat_pump_enabled, battery_mode, grid_mode, loxone_mode_value, is_autonomous, sort_order)
VALUES
('AUTO', 'Automatický', 'EMS řídí vše podle optimalizovaného plánu. Setpointy posílány každých 15 min.',
true, true, 'plan', 'plan', 1, false, 10),
('SELF_SUSTAIN', 'Soběstačný', 'Fallback bez EMS. FVE + baterie pokrývají spotřebu. Žádný import, žádný export, EV a TČ odstaveny.',
false, false, 'self_sustain', 'no_export', 2, true, 20),
('CHARGE_CHEAP', 'Nabíjení levnou cenou', 'Manuální: max nabíjení baterie ze sítě. Použít při ručně identifikované levné ceně nebo akci.',
false, false, 'charge_max', 'import_ok', 3, false, 30),
('PRESERVE', 'Ochrana baterie', 'Dovolená / servis. Baterie drží aktuální SoC, žádné akce. EV a TČ odstaveny.',
false, false, 'hold', 'import_ok', 4, true, 40),
('MANUAL', 'Manuální', 'Technický přepis. EMS ani Loxone logika neřídí střídač. Pouze pro servisní práce.',
false, false, 'none', 'none', 0, true, 50);
-- ============================================================
-- Aktivní provozní režim per lokalita
-- ============================================================
CREATE TABLE ems.site_operating_mode (
site_id INT NOT NULL REFERENCES ems.site(id) PRIMARY KEY,
mode_code TEXT NOT NULL REFERENCES ems.operating_mode_def(code),
activated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
activated_by TEXT,
valid_until TIMESTAMPTZ, -- NULL = platí do ručního přepnutí
previous_mode TEXT REFERENCES ems.operating_mode_def(code),
notes TEXT
);
COMMENT ON TABLE ems.site_operating_mode IS 'Aktuálně aktivní provozní režim per lokalita. Jeden řádek na lokalitu (upsert při přepnutí).';
COMMENT ON COLUMN ems.site_operating_mode.site_id IS 'Vazba na lokalitu. PK jedna lokalita má vždy právě jeden aktivní režim.';
COMMENT ON COLUMN ems.site_operating_mode.mode_code IS 'Aktuálně aktivní režim. FK na operating_mode_def.';
COMMENT ON COLUMN ems.site_operating_mode.activated_at IS 'Čas přepnutí do tohoto režimu.';
COMMENT ON COLUMN ems.site_operating_mode.activated_by IS 'Kdo nebo co přepnulo režim: user:jan, system:watchdog, api, loxone.';
COMMENT ON COLUMN ems.site_operating_mode.valid_until IS 'Automatické vypršení režimu. NULL = platí do ručního přepnutí.';
COMMENT ON COLUMN ems.site_operating_mode.previous_mode IS 'Předchozí režim pro rychlý návrat zpět.';
COMMENT ON COLUMN ems.site_operating_mode.notes IS 'Volný komentář k přepnutí.';
-- ============================================================
-- Historie přepnutí režimů (audit log)
-- ============================================================
CREATE TABLE ems.site_operating_mode_log (
id SERIAL PRIMARY KEY,
site_id INT NOT NULL REFERENCES ems.site(id),
mode_code TEXT NOT NULL REFERENCES ems.operating_mode_def(code),
activated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deactivated_at TIMESTAMPTZ,
activated_by TEXT,
notes TEXT
);
COMMENT ON TABLE ems.site_operating_mode_log IS 'Auditní log všech přepnutí provozních režimů per lokalita.';
COMMENT ON COLUMN ems.site_operating_mode_log.id IS 'Primární klíč.';
COMMENT ON COLUMN ems.site_operating_mode_log.site_id IS 'Vazba na lokalitu.';
COMMENT ON COLUMN ems.site_operating_mode_log.mode_code IS 'Aktivovaný režim.';
COMMENT ON COLUMN ems.site_operating_mode_log.activated_at IS 'Čas aktivace režimu.';
COMMENT ON COLUMN ems.site_operating_mode_log.deactivated_at IS 'Čas deaktivace (přepnutí na jiný režim). NULL = stále aktivní.';
COMMENT ON COLUMN ems.site_operating_mode_log.activated_by IS 'Zdroj přepnutí: user:jan, system:watchdog, system:ems_start.';
COMMENT ON COLUMN ems.site_operating_mode_log.notes IS 'Volný komentář.';
-- ============================================================
-- Heartbeat tabulka pouze informační, pro EMS vlastní diagnostiku
-- POZOR: Loxone watchdog NEČTE tuto tabulku.
-- Loxone sleduje HTTP pulzy přímo (nezávisle na DB).
-- Tato tabulka slouží jen pro EMS dashboard a alerting.
-- ============================================================
CREATE TABLE ems.site_heartbeat (
site_id INT NOT NULL REFERENCES ems.site(id) PRIMARY KEY,
last_seen TIMESTAMPTZ NOT NULL DEFAULT now(),
ems_version TEXT,
status TEXT NOT NULL DEFAULT 'ok'
);
COMMENT ON TABLE ems.site_heartbeat IS 'Informační záznam posledního úspěšného heartbeat pulzu EMS per lokalita. Slouží pouze pro EMS dashboard a alerting Loxone watchdog tuto tabulku nečte a nezávisí na ní. Fallback logika je implementována čistě v Loxone (viz docs/loxone-integration.md).';
COMMENT ON COLUMN ems.site_heartbeat.site_id IS 'Vazba na lokalitu. PK.';
COMMENT ON COLUMN ems.site_heartbeat.last_seen IS 'Čas kdy EMS backend naposledy úspěšně odeslal pulz do Loxone.';
COMMENT ON COLUMN ems.site_heartbeat.ems_version IS 'Verze EMS backendu pro diagnostiku.';
COMMENT ON COLUMN ems.site_heartbeat.status IS 'Stav EMS backendu: ok, degraded (částečný výpadek), error (kritická chyba).';