Files
ems/db/migration/V064__signal_outbound.sql
Dusan Vojacek 50a0ca95f4
Some checks failed
CI and deploy / migration-check (push) Failing after 10s
CI and deploy / deploy (push) Has been skipped
implementace LED loxone u zaporncyh cen
2026-04-26 22:49:47 +02:00

123 lines
5.3 KiB
SQL

-- Signály EMS → externí cíle (Loxone VI, HTTP REST), journal + idempotence + verify readback.
-- Kritické řízení výkonu (Deye, EV, TČ) zůstává v modbus_command / exporteru.
-- ------------------------------------------------------------
-- Definice signálů (globální katalog kódů)
-- ------------------------------------------------------------
CREATE TABLE ems.signal_def (
code TEXT PRIMARY KEY,
value_type TEXT NOT NULL,
description TEXT
);
COMMENT ON TABLE ems.signal_def IS
'Katalog signálů EMS (logické výstupy). Hodnotu pro route počítá backend dle doménové logiky.';
COMMENT ON COLUMN ems.signal_def.code IS
'Unikátní kód signálu, např. EXPORT_BAN_ACTIVE.';
COMMENT ON COLUMN ems.signal_def.value_type IS
'bool | int | float | string — očekávaný typ hodnoty po transformaci na cíl.';
INSERT INTO ems.signal_def (code, value_type, description)
VALUES (
'EXPORT_BAN_ACTIVE',
'bool',
'Pravda pokud EMS aktuálně uplatňuje zákaz exportu do sítě (LED varianta B): override block_export, no_export, režimy bez exportu, AUTO se záporným výkupem při ne-negativním grid setpointu.'
)
ON CONFLICT (code) DO NOTHING;
-- ------------------------------------------------------------
-- Směrování signál → cíl (per site)
-- ------------------------------------------------------------
CREATE TABLE ems.signal_route (
id SERIAL PRIMARY KEY,
site_id INT NOT NULL REFERENCES ems.site (id),
destination_type TEXT NOT NULL,
endpoint_id INT NOT NULL REFERENCES ems.site_endpoint (id),
signal_code TEXT NOT NULL REFERENCES ems.signal_def (code),
destination_key TEXT NOT NULL,
route_config_json JSONB,
transform_json JSONB,
verify_readback BOOLEAN NOT NULL DEFAULT true,
verify_config_json JSONB,
enabled BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT uq_signal_route_unique UNIQUE (site_id, destination_type, signal_code, destination_key)
);
CREATE INDEX idx_signal_route_site_enabled
ON ems.signal_route (site_id, enabled)
WHERE enabled = true;
COMMENT ON TABLE ems.signal_route IS
'Mapování signálu na cíl (Loxone Virtual Input, HTTP REST atd.). endpoint_id ukazuje na ems.site_endpoint (loxone_http, budoucí shelly_http, …).';
COMMENT ON COLUMN ems.signal_route.destination_type IS
'loxone_vi = GET /dev/sps/io/{destination_key}/{value}; http_rest = šablona v route_config_json.';
COMMENT ON COLUMN ems.signal_route.destination_key IS
'U Loxone název Virtual Inputu. U HTTP REST stabilní klíč pro log (např. relay0).';
COMMENT ON COLUMN ems.signal_route.route_config_json IS
'Volitelná konfigurace pro http_rest (path_template, method, …). U loxone_vi typicky NULL.';
COMMENT ON COLUMN ems.signal_route.verify_config_json IS
'Readback: u Loxone např. {"loxone_io_name":"EMS_ExportBan_Active_FB"} pro GET /dev/sps/io/{name}. U HTTP JSON path atd.';
-- ------------------------------------------------------------
-- Odchozí journal
-- ------------------------------------------------------------
CREATE TABLE ems.signal_outbound_journal (
id BIGSERIAL PRIMARY KEY,
route_id INT NOT NULL REFERENCES ems.signal_route (id),
site_id INT NOT NULL REFERENCES ems.site (id),
signal_code TEXT NOT NULL,
value_text TEXT NOT NULL,
value_num NUMERIC,
status TEXT NOT NULL,
attempt_count INT NOT NULL DEFAULT 0,
next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_error TEXT,
http_method TEXT,
request_url TEXT,
http_status INT,
latency_ms INT,
response_body_trunc TEXT,
sent_at TIMESTAMPTZ,
verified_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT chk_signal_outbound_status CHECK (
status IN ('queued', 'sent', 'verified', 'failed', 'abandoned')
)
);
CREATE INDEX idx_signal_outbound_worker
ON ems.signal_outbound_journal (status, next_attempt_at);
CREATE INDEX idx_signal_outbound_site_debug
ON ems.signal_outbound_journal (site_id, signal_code, created_at DESC);
COMMENT ON TABLE ems.signal_outbound_journal IS
'Journal odchozích signálů (HTTP). Worker odesílá queued, po úspěchu sent, po readback verified nebo failed s retry.';
-- ------------------------------------------------------------
-- Poslední známý stav (idempotence)
-- ------------------------------------------------------------
CREATE TABLE ems.signal_state (
site_id INT NOT NULL REFERENCES ems.site (id),
signal_code TEXT NOT NULL,
destination_type TEXT NOT NULL,
destination_key TEXT NOT NULL,
last_desired_value_text TEXT,
last_sent_value_text TEXT,
last_verified_value_text TEXT,
last_sent_at TIMESTAMPTZ,
last_verified_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (site_id, signal_code, destination_type, destination_key)
);
COMMENT ON TABLE ems.signal_state IS
'Poslední požadovaná / odeslaná / ověřená hodnota signálu per cíl — idempotence a diagnostika verify.';