-- Modbus command journal + cut-off switch audit (EMS) CREATE TABLE ems.modbus_command ( id SERIAL PRIMARY KEY, site_id INT NOT NULL REFERENCES ems.site(id), asset_type TEXT NOT NULL, -- 'inverter', 'ev_charger', 'heat_pump', 'cutoff' asset_id INT NOT NULL, -- ID v příslušné asset tabulce asset_code TEXT NOT NULL, -- např. 'deye-main' (denorm. pro čitelnost) device_host TEXT NOT NULL, device_port INT NOT NULL, device_unit_id INT NOT NULL, register INT NOT NULL, -- číslo registru (decimal) register_name TEXT, -- 'export_limit', 'charge_limit' (pro čitelnost) value_to_write INT NOT NULL, value_written INT, -- skutečně zapsaná hodnota (NULL = nezapsáno) value_verified INT, -- přečtená hodnota po verifikaci (NULL = neověřeno) status TEXT NOT NULL DEFAULT 'pending', -- 'pending', 'written', 'verified', 'failed', 'mismatch', 'retrying' planning_run_id INT REFERENCES ems.planning_run(id), attempt_count INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), written_at TIMESTAMPTZ, verified_at TIMESTAMPTZ, error_msg TEXT ); COMMENT ON TABLE ems.modbus_command IS 'Command journal pro Modbus zápisy do zařízení. Každý zápis = jeden řádek. Verifikační job ověří value_verified == value_to_write. Při mismatch: retry max 3× → přepnout na SELF_SUSTAIN + Discord alert. asset_type+asset_id odkazuje na příslušnou asset tabulku (inverter/ev_charger/...).'; CREATE INDEX idx_modbus_command_status ON ems.modbus_command (site_id, status, created_at DESC); CREATE INDEX idx_modbus_command_pending ON ems.modbus_command (status, created_at) WHERE status IN ('pending', 'retrying'); CREATE TABLE ems.cutoff_switch_log ( id SERIAL PRIMARY KEY, site_id INT NOT NULL REFERENCES ems.site(id), asset_code TEXT NOT NULL, -- 'cutoff-pv-b', 'cutoff-microinverter' switched_at TIMESTAMPTZ NOT NULL DEFAULT now(), new_state BOOLEAN NOT NULL, -- true=zapnuto/připojeno, false=odpojeno previous_state BOOLEAN, reason TEXT NOT NULL, -- 'negative_sell_price', 'manual', 'auto_restore' sell_price_czk NUMERIC(10,6), -- spotová cena v době přepnutí triggered_by TEXT -- 'control_exporter', 'user:jan', 'system' ); COMMENT ON TABLE ems.cutoff_switch_log IS 'Log přepnutí cut-off přepínačů. Loguje se jen při změně stavu (edge trigger). Používá se pro mikroinvertory na GEN portu při záporných prodejních cenách.';