Initial commit

Made-with: Cursor
This commit is contained in:
Dusan Vojacek
2026-03-20 13:27:37 +01:00
commit 8b4af663d8
77 changed files with 13337 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
-- =============================================================
-- V006__vehicles.sql
-- EMS Platform vozidla a EV session tracking
-- =============================================================
-- ============================================================
-- Vozidla
-- ============================================================
CREATE TABLE ems.asset_vehicle (
id SERIAL PRIMARY KEY,
site_id INT NOT NULL REFERENCES ems.site(id),
code TEXT NOT NULL,
name TEXT,
make TEXT, -- 'Tesla', 'Renault'
model TEXT, -- 'Model Y', 'Zoe R135'
battery_capacity_kwh NUMERIC(6,2) NOT NULL, -- kapacita trakční baterie
max_charge_power_w INT NOT NULL, -- max přijímaný AC výkon vozidla
default_charger_id INT REFERENCES ems.asset_ev_charger(id),
api_type TEXT NOT NULL DEFAULT 'none', -- 'tesla', 'none'
api_reference TEXT, -- klíč do env/secrets pro API
default_target_soc_pct NUMERIC(5,2) NOT NULL DEFAULT 80,
default_deadline_hour INT NOT NULL DEFAULT 7, -- hodina rána
active BOOLEAN NOT NULL DEFAULT true,
UNIQUE (site_id, code)
);
COMMENT ON TABLE ems.asset_vehicle IS 'Vozidla registrovaná v EMS. Každé vozidlo má výchozí cílový SoC a deadline pro plánování nabíjení.';
COMMENT ON COLUMN ems.asset_vehicle.battery_capacity_kwh IS 'Celková kapacita trakční baterie vozidla v kWh. Tesla Model Y ~75 kWh, Renault Zoe R135 ~52 kWh.';
COMMENT ON COLUMN ems.asset_vehicle.max_charge_power_w IS 'Maximální výkon který vozidlo přijme přes AC nabíjení. Může být nižší než výkon WB. Tesla MY ~11 000 W, Zoe R135 ~7 400 W.';
COMMENT ON COLUMN ems.asset_vehicle.api_type IS 'Typ API pro čtení stavu vozidla. tesla = Tesla API (Tessie nebo přímé), none = žádné API.';
COMMENT ON COLUMN ems.asset_vehicle.api_reference IS 'Název env proměnné nebo klíče v secrets kde je uložen API token/přihlášení. Např. TESLA_MY_TOKEN.';
COMMENT ON COLUMN ems.asset_vehicle.default_target_soc_pct IS 'Výchozí cílový SoC pro deadline charging. Uživatel může přepsat v UI před odjezdem.';
COMMENT ON COLUMN ems.asset_vehicle.default_deadline_hour IS 'Výchozí hodina rána do které musí být dosažen target SoC. 7 = 07:00.';
-- ============================================================
-- EV session tracking
-- ============================================================
CREATE TABLE ems.ev_session (
id SERIAL PRIMARY KEY,
site_id INT NOT NULL REFERENCES ems.site(id),
charger_id INT NOT NULL REFERENCES ems.asset_ev_charger(id),
vehicle_id INT REFERENCES ems.asset_vehicle(id), -- NULL pokud neznámé vozidlo
session_start TIMESTAMPTZ NOT NULL DEFAULT now(),
session_end TIMESTAMPTZ,
-- Stav při připojení (pokud znám)
soc_at_connect_pct NUMERIC(5,2),
-- Deadline požadavek
target_soc_pct NUMERIC(5,2),
target_deadline TIMESTAMPTZ,
-- Průběžný stav (aktualizován z telemetrie)
energy_delivered_wh NUMERIC(12,3) NOT NULL DEFAULT 0,
last_power_w INT,
-- Výsledek při odpojení
soc_at_disconnect_pct NUMERIC(5,2),
total_cost_czk NUMERIC(10,4),
deadline_met BOOLEAN, -- byl deadline splněn?
-- Metadata
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
COMMENT ON TABLE ems.ev_session IS 'Záznamy jednotlivých nabíjecích sessions EV. Session začíná připojením (status != available na WB) a končí odpojením.';
COMMENT ON COLUMN ems.ev_session.vehicle_id IS 'Identifikace vozidla. Může být NULL pokud EMS neví které auto je připojeno (Zoe nemá API).';
COMMENT ON COLUMN ems.ev_session.soc_at_connect_pct IS 'SoC baterie vozidla při připojení. Pro Tesla čteno z API, pro Zoe NULL (neznáme).';
COMMENT ON COLUMN ems.ev_session.target_soc_pct IS 'Cílový SoC pro tuto session. Výchozí z asset_vehicle.default_target_soc_pct, uživatel může změnit v UI.';
COMMENT ON COLUMN ems.ev_session.target_deadline IS 'Deadline pro dosažení target_soc_pct. Výchozí = dnešní/zítřejší default_deadline_hour.';
COMMENT ON COLUMN ems.ev_session.energy_delivered_wh IS 'Kumulativní energie dodaná v této session v Wh. Čteno z WB Modbus (kWh counter). Slouží i pro odhad SoC u Zoe.';
COMMENT ON COLUMN ems.ev_session.deadline_met IS 'True pokud byl target_soc_pct dosažen před target_deadline. NULL pokud session ještě probíhá.';
-- Hypertable pro session log (sessions jsou časová série)
-- Poznámka: ev_session není hypertable sessions jsou krátké záznamy, ne telemetrie.
-- Index pro rychlé dotazy na aktivní session
CREATE INDEX idx_ev_session_active
ON ems.ev_session (charger_id, session_end)
WHERE session_end IS NULL;
CREATE INDEX idx_ev_session_site_time
ON ems.ev_session (site_id, session_start DESC);
-- ============================================================
-- Seed vozidla home-01
-- ============================================================
INSERT INTO ems.asset_vehicle
(site_id, code, name, make, model,
battery_capacity_kwh, max_charge_power_w,
default_charger_id, api_type,
default_target_soc_pct, default_deadline_hour)
SELECT
s.id,
'tesla-my', 'Tesla Model Y', 'Tesla', 'Model Y',
75.0,
11000, -- Tesla MY AC max ~11kW (3fáze × 16A × 230V)
ch1.id,
'none', -- Tesla API fáze 2, zatím none
80, -- 80% výchozí target Tesla má velkou baterii
7 -- do 7:00 ráno
FROM ems.site s
JOIN ems.asset_ev_charger ch1 ON ch1.site_id = s.id AND ch1.code = 'ev-charger-1'
WHERE s.code = 'home-01';
INSERT INTO ems.asset_vehicle
(site_id, code, name, make, model,
battery_capacity_kwh, max_charge_power_w,
default_charger_id, api_type,
default_target_soc_pct, default_deadline_hour)
SELECT
s.id,
'zoe-r135', 'Renault Zoe R135', 'Renault', 'Zoe R135',
52.0,
7400, -- Zoe R135 max 7.4kW AC (jednofáze 32A nebo 3fáze nižší)
ch2.id,
'none', -- Zoe nemá API
90, -- 90% výchozí target Zoe má menší baterii, kritičtější
7
FROM ems.site s
JOIN ems.asset_ev_charger ch2 ON ch2.site_id = s.id AND ch2.code = 'ev-charger-2'
WHERE s.code = 'home-01';