Rozšiřte stávající IoT systém o databázi a REST API. Navrhněte a implementujte službu, která průběžně ukládá data z MQTT brokeru do SQLite databáze a zpřístupňuje je prostřednictvím REST API.
1. Databázové schéma (4 body): Navrhněte a implementujte SQLite databázi s alespoň 2 tabulkami. Jedna tabulka bude uchovávat záznamy měření (teplota, časová známka ISO 8601), druhá bude sloužit jako registr zařízení. Každé zařízení identifikované ČVUT loginem bude mít v tabulce zařízení právě jeden záznam obsahující identifikátor zařízení, časovou známku první detekované zprávy, časovou známku poslední detekované zprávy, uptime získaný z poslední přijaté zprávy, aktuálně nastavenou periodu měření a celkový počet detekovaných zpráv. Mezi tabulkami musí být definován vztah prostřednictvím cizího klíče. Schéma databáze bude uloženo v samostatném souboru schema.sql. Při inicializaci Flask aplikace musí být automaticky ověřeno a zajištěno, že: databázový soubor existuje, obě tabulky jsou přítomny a mají správně definované sloupce. Pokud databáze nebo schéma neexistuje, aplikace je automaticky vytvoří. Na pozadí aplikace musí běžet MQTT klient odebírající téma cvut/nsi/2026/+/telemetry. Logika zpracování příchozí zprávy musí postupovat následovně:
2. REST API (4 body): Implementujte REST API s následujícími endpointy. Každý endpoint musí vracet správný HTTP stavový kód dle situace a tělo odpovědi vždy ve formátu JSON (včetně chybových stavů):
| Metoda | Endpoint | Popis |
|---|---|---|
| GET | /api/devices | Vrátí seznam detekovaných zařízení; 4xx pokud žádné zařízení neexistuje; 2xx při úspěchu. |
| GET | /api/devices/<device_id> | Vrátí detail konkrétního zařízení; 4xx pokud neexistuje; 2xx při úspěchu. |
| GET | /api/telemetry/<id> | Vrátí konkrétní záznam telemetrie (měření); 4xx pokud neexistuje; 2xx při úspěchu. |
| DELETE | /api/telemetry/<id> | Smaže konkrétní záznam telemetrie (měření); 4xx pokud neexistuje; 2xx při úspěchu. |
| DELETE | /api/devices/<device_id> | Smaže zařízení včetně všech jeho telemetrických záznamů (kaskádové smazání); 4xx pokud neexistuje, 2xx při úspěchu. |
| POST | /api/telemetry | Umožní vložení záznamu. Nutná validace struktury těla požadavku; při úspěchu vrací 2xx. V těle požadavku se očekává JSON struktura s položkami: device (povinné), timestamp (povinné), measure-period (povinné), temperature (povinné), uptime (student musí vyřešit logiku aktualizace záznamu zařízení, pokud uptime není součástí payloadu – viz bod 1) a led. |
3. Pokročilé dotazování (4 body): Přidejte endpoint GET /api/telemetry, který bude podporovat následující query parametry a HTTP hlavičky.
URL Query parametry:
device_id - filtrování záznamů pro konkrétní zařízení, from a to - časový rozsah ve formátu ISO 8601. Pokud je from větší než to, server vrací 4xx s vysvětlujícím JSON tělem. HTTP hlavičky požadavků:
X-Sort-Field - pole, podle kterého se výsledky řadí; povolené hodnoty: timestamp, temperature; výchozí hodnota: timestamp. Neznámá hodnota musí být odmítnuta stavem 4xx s vysvětlujícím JSON tělem. X-Sort-Order - směr řazení; povolené hodnoty: asc, desc; výchozí hodnota: desc. HTTP hlavičky odpovědí:
X-Current-Count - počet záznamů odpovídajících zadaným filtrům X-Total –Count - celkový počet záznamů v tabulce (bez ohledu na filtry) Hodnotí se správnost SQL dotazů generovaných pro filtrování a řazení. Řešení, která načtou veškerá data do paměti Pythonu a teprve poté třídí nebo filtrují, nebudou uznána.
4. Vizualizace historických dat (3 body): Implementujte webovou stránku dostupnou na /dashboard, která zobrazuje graf vývoje teploty v čase pro zvolené zařízení a zvolené časové okno. Stránka musí obsahovat HTML formulář s následujícími ovládacími prvky:
select nebo datalist) generovaného ze seznamu registrovaných zařízení.
Student si může zvolit přístup dle vlastního uvážení – server-side rendering nebo client-side rendering. Bez ohledu na zvolenou technologii se hodnotí kvalita a použitelnost výstupu: graf musí mít popsané osy, název, správně formátované časové popisky na ose X a musí být přehledný i při řádu stovek záznamů.
BONUS (+3 body): Implementujte endpoint POST /api/telemetry/batch, který přijme JSON pole obsahující 1–1000 telemetrických záznamů najednou. Celá dávka musí být vložena v rámci jediné transakce – buď se uloží všechny záznamy, nebo žádný. Pokud jakýkoliv záznam v dávce nesplní validaci (chybějící povinné pole, nevalidní datový typ, časová známka ve špatném formátu), transakce se celá zruší a server vrátí 4xx s tělem obsahujícím index prvního chybného záznamu a popis chyby. Při úspěchu vrátí 2xx s počtem vložených záznamů.
Součástí řešení musí být testovací skript batch_test.py, který demonstruje obě větve: úspěšné vložení validní dávky a odmítnutí dávky obsahující jeden nevalidní záznam uprostřed. Skript musí po odmítnuté dávce ověřit, že databáze neobsahuje žádná částečně vložená data – tzn. explicitně dotázat databázi a výsledek vypsat do konzole.