first commit

This commit is contained in:
Mateusz Gruszczyński
2026-08-23 21:34:07 +02:00
commit 1d3dcba1a9
62 changed files with 12456 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
//! Centralized SQLite statements used by the controller.
//!
//! Keep SQL in this module so database access code stays focused on mapping,
//! transactions and domain behavior. New queries and schema migrations should
//! be added here instead of embedding SQL strings in other Rust modules.
pub const INIT_SCHEMA: &str = r#"
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA foreign_keys=ON;
CREATE TABLE IF NOT EXISTS schema_migrations (
version INTEGER PRIMARY KEY,
applied_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS devices (
id TEXT PRIMARY KEY,
mac TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
ip TEXT NOT NULL,
simulated INTEGER NOT NULL DEFAULT 0,
payload TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS zones (
id TEXT PRIMARY KEY,
payload TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS schedules (
id TEXT PRIMARY KEY,
zone_id TEXT NOT NULL,
payload TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS schedules_zone_idx ON schedules(zone_id);
CREATE TABLE IF NOT EXISTS automations (
id TEXT PRIMARY KEY,
payload TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS readings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL,
timestamp TEXT NOT NULL,
indoor_temperature REAL,
outdoor_temperature REAL,
target_temperature REAL NOT NULL,
power INTEGER NOT NULL,
source TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS readings_device_time_idx
ON readings(device_id, timestamp DESC);
CREATE TABLE IF NOT EXISTS event_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
level TEXT NOT NULL,
kind TEXT NOT NULL,
message TEXT NOT NULL,
metadata TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS event_log_time_idx ON event_log(timestamp DESC);
CREATE TABLE IF NOT EXISTS api_tokens (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
token_hash TEXT NOT NULL UNIQUE,
token_prefix TEXT NOT NULL,
created_at TEXT NOT NULL
);
INSERT OR IGNORE INTO schema_migrations(version, applied_at)
VALUES (1, strftime('%Y-%m-%dT%H:%M:%fZ','now'));
INSERT OR IGNORE INTO schema_migrations(version, applied_at)
VALUES (2, strftime('%Y-%m-%dT%H:%M:%fZ','now'));
"#;
pub const COUNT_DEVICES: &str = "SELECT COUNT(*) FROM devices";
pub const UPSERT_DEVICE: &str = r#"
INSERT INTO devices(id, mac, name, ip, simulated, payload, updated_at)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
ON CONFLICT(id) DO UPDATE SET
mac=excluded.mac,
name=excluded.name,
ip=excluded.ip,
simulated=excluded.simulated,
payload=excluded.payload,
updated_at=excluded.updated_at
"#;
pub const LIST_DEVICES: &str = "SELECT payload FROM devices ORDER BY name COLLATE NOCASE";
pub const GET_DEVICE_BY_ID: &str = "SELECT payload FROM devices WHERE id=?1";
pub const GET_DEVICE_BY_MAC: &str = "SELECT payload FROM devices WHERE lower(mac)=lower(?1)";
pub const DELETE_DEVICE_READINGS: &str = "DELETE FROM readings WHERE device_id=?1";
pub const DELETE_ZONES_BY_DEVICE_ID: &str =
"DELETE FROM zones WHERE json_extract(payload, '$.device_id')=?1";
pub const DELETE_DEVICE: &str = "DELETE FROM devices WHERE id=?1";
pub const UPSERT_ZONE: &str = r#"
INSERT INTO zones(id,payload,updated_at) VALUES(?1,?2,?3)
ON CONFLICT(id) DO UPDATE SET
payload=excluded.payload,
updated_at=excluded.updated_at
"#;
pub const LIST_ZONES: &str =
"SELECT payload FROM zones ORDER BY json_extract(payload, '$.name') COLLATE NOCASE";
pub const GET_ZONE: &str = "SELECT payload FROM zones WHERE id=?1";
pub const DELETE_SCHEDULES_BY_ZONE_ID: &str = "DELETE FROM schedules WHERE zone_id=?1";
pub const DELETE_ZONE: &str = "DELETE FROM zones WHERE id=?1";
pub const UPSERT_SCHEDULE: &str = r#"
INSERT INTO schedules(id,zone_id,payload,updated_at) VALUES(?1,?2,?3,?4)
ON CONFLICT(id) DO UPDATE SET
zone_id=excluded.zone_id,
payload=excluded.payload,
updated_at=excluded.updated_at
"#;
pub const LIST_SCHEDULES: &str =
"SELECT payload FROM schedules ORDER BY json_extract(payload, '$.name') COLLATE NOCASE";
pub const GET_SCHEDULE: &str = "SELECT payload FROM schedules WHERE id=?1";
pub const DELETE_SCHEDULE: &str = "DELETE FROM schedules WHERE id=?1";
pub const UPSERT_AUTOMATION: &str = r#"
INSERT INTO automations(id,payload,updated_at) VALUES(?1,?2,?3)
ON CONFLICT(id) DO UPDATE SET
payload=excluded.payload,
updated_at=excluded.updated_at
"#;
pub const LIST_AUTOMATIONS: &str =
"SELECT payload FROM automations ORDER BY json_extract(payload, '$.name') COLLATE NOCASE";
pub const GET_AUTOMATION: &str = "SELECT payload FROM automations WHERE id=?1";
pub const DELETE_AUTOMATION: &str = "DELETE FROM automations WHERE id=?1";
pub const INSERT_READING: &str = r#"
INSERT INTO readings(
device_id,
timestamp,
indoor_temperature,
outdoor_temperature,
target_temperature,
power,
source
)
VALUES(?1,?2,?3,?4,?5,?6,?7)
"#;
pub const LIST_READINGS_BY_DEVICE: &str = r#"
SELECT id,device_id,timestamp,indoor_temperature,outdoor_temperature,target_temperature,power,source
FROM readings
WHERE device_id=?1 AND timestamp>=?2
ORDER BY timestamp ASC
LIMIT ?3
"#;
pub const LIST_READINGS_ALL: &str = r#"
SELECT id,device_id,timestamp,indoor_temperature,outdoor_temperature,target_temperature,power,source
FROM readings
WHERE timestamp>=?1
ORDER BY timestamp ASC
LIMIT ?2
"#;
pub const PRUNE_READINGS: &str = "DELETE FROM readings WHERE timestamp < ?1";
pub const INSERT_EVENT: &str =
"INSERT INTO event_log(timestamp,level,kind,message,metadata) VALUES(?1,?2,?3,?4,?5)";
pub const LIST_EVENTS: &str =
"SELECT id,timestamp,level,kind,message,metadata FROM event_log ORDER BY id DESC LIMIT ?1";
pub const LIST_API_TOKENS: &str =
"SELECT id,name,token_prefix,created_at FROM api_tokens ORDER BY created_at DESC";
pub const INSERT_API_TOKEN: &str =
"INSERT INTO api_tokens(id,name,token_hash,token_prefix,created_at) VALUES(?1,?2,?3,?4,?5)";
pub const API_TOKEN_EXISTS: &str = "SELECT 1 FROM api_tokens WHERE token_hash=?1 LIMIT 1";
pub const DELETE_API_TOKEN: &str = "DELETE FROM api_tokens WHERE id=?1";
pub const LOAD_RUNTIME_SETTINGS: &str = "SELECT value FROM settings WHERE key='runtime'";
pub const UPSERT_RUNTIME_SETTINGS: &str = r#"
INSERT INTO settings(key,value,updated_at) VALUES('runtime',?1,?2)
ON CONFLICT(key) DO UPDATE SET
value=excluded.value,
updated_at=excluded.updated_at
"#;