-- ============================================================= -- 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).';