Cílem miniprojektů je vytvořit komplexní IoT aplikaci, na které bude možné experimentálně ověřit probírané technologie a postupy.
Student bude své miniprojekty odevzdávat prostřednictvím fakultní GitLabu. Miniprojekty jsou koncipovány tak, že se postupně rozšiřuje funkcionalita jedné webové aplikace - každý student bude mít tedy jeden GitLab projekt, který bude průběžně hodnocen. Je nutné, aby byl repozitář dostupný, tj. viditelnost internal
nebo public
.
Po dokončení miniprojektu student nahraje změny na GitLab a do BRUTE odevzdá do příslušného miniprojektu (MP01, MP02, …) textový soubor s url adresou projektu (preferujeme rozdělení miniprojektů do jednotlivých větví, např. miniprojekt-1
, miniprojekt-2
, …).
Pokud je pro vývoj aplikace využito virtuální prostředí (například venv
), je nutné odpovídající adresáře a soubory vyloučit z repozitáře pomocí .gitignore
. Pro správnou funkčnost je vyžadována správa balíčků pomocí requirements.txt
(viz první cvičení).
Vytvořte webovou aplikaci ve frameworku Flask s pomocí knihovny Bootstrap. Součástí aplikace budou alespoň 3 endpointy - Dashboard, Přihlášení, Registrace.
Na stránce Dashboard budou alespoň tyto elementy: Poslední naměřená hodnota s časem zápisu, Tabulka zobrazující posledních 15 naměřených hodnot (sloupce = ID, Teplota, Čas zápisu), Tlačítko pro smazání nejstarší hodnoty. Naměřená data simulujte následujícím slovníkovým seznamem, který definujte v main.py:
DATA=[ {"id": 0,"temperature": 21,"timestamp": "2025-01-01 01:00:00"}, {"id": 1,"temperature": 33,"timestamp": "2025-01-01 01:05:52"}, {"id": 2,"temperature": 38,"timestamp": "2025-01-01 01:10:23"}, {"id": 3,"temperature": 21,"timestamp": "2025-01-01 01:15:17"}, {"id": 4,"temperature": 24,"timestamp": "2025-01-01 01:20:08"}, {"id": 5,"temperature": 35,"timestamp": "2025-01-01 01:25:42"}, {"id": 6,"temperature": 40,"timestamp": "2025-01-01 01:30:00"}, {"id": 7,"temperature": 37,"timestamp": "2025-01-01 01:35:19"}, {"id": 8,"temperature": 37,"timestamp": "2025-01-01 01:40:25"}, {"id": 9,"temperature": 20,"timestamp": "2025-01-01 01:45:53"}, {"id": 10,"temperature": 35,"timestamp": "2025-01-01 01:50:15"}, {"id": 11,"temperature": 34,"timestamp": "2025-01-01 01:55:19"}, {"id": 12,"temperature": 28,"timestamp": "2025-01-01 02:00:46"}, {"id": 13,"temperature": 23,"timestamp": "2025-01-01 02:05:55"}, {"id": 14,"temperature": 25,"timestamp": "2025-01-01 02:10:20"}, {"id": 15,"temperature": 23,"timestamp": "2025-01-01 02:15:43"}, {"id": 16,"temperature": 23,"timestamp": "2025-01-01 02:20:52"}, {"id": 17,"temperature": 31,"timestamp": "2025-01-01 02:25:47"}, {"id": 18,"temperature": 29,"timestamp": "2025-01-01 02:30:35"}, {"id": 19,"temperature": 31,"timestamp": "2025-01-01 02:35:52"}, {"id": 20,"temperature": 35,"timestamp": "2025-01-01 02:40:28"}, {"id": 21,"temperature": 26,"timestamp": "2025-01-01 02:45:53"}, {"id": 22,"temperature": 35,"timestamp": "2025-01-01 02:50:50"}, {"id": 23,"temperature": 28,"timestamp": "2025-01-01 02:55:56"}, {"id": 24,"temperature": 39,"timestamp": "2025-01-01 03:00:31"}, {"id": 25,"temperature": 36,"timestamp": "2025-01-01 03:05:56"}, {"id": 26,"temperature": 39,"timestamp": "2025-01-01 03:10:40"}, {"id": 27,"temperature": 23,"timestamp": "2025-01-01 03:15:47"}, {"id": 28,"temperature": 31,"timestamp": "2025-01-01 03:20:11"}, {"id": 29,"temperature": 21,"timestamp": "2025-01-01 03:25:43"}, {"id": 30,"temperature": 23,"timestamp": "2025-01-01 03:30:58"}, {"id": 32,"temperature": 28,"timestamp": "2025-01-01 03:35:51"}, {"id": 31,"temperature": 29,"timestamp": "2025-01-01 03:40:46"}, {"id": 33,"temperature": 31,"timestamp": "2025-01-01 03:45:38"}, {"id": 34,"temperature": 40,"timestamp": "2025-01-01 03:50:09"}, {"id": 35,"temperature": 37,"timestamp": "2025-01-01 03:55:26"}, {"id": 36,"temperature": 32,"timestamp": "2025-01-01 04:00:25"}, {"id": 37,"temperature": 39,"timestamp": "2025-01-01 04:05:03"}, {"id": 38,"temperature": 31,"timestamp": "2025-01-01 04:10:39"}, {"id": 39,"temperature": 31,"timestamp": "2025-01-01 04:15:16"}, {"id": 40,"temperature": 32,"timestamp": "2025-01-01 04:20:14"}, {"id": 41,"temperature": 33,"timestamp": "2025-01-01 04:25:03"}, {"id": 42,"temperature": 21,"timestamp": "2025-01-01 04:30:01"}, {"id": 43,"temperature": 34,"timestamp": "2025-01-01 04:35:24"}, {"id": 44,"temperature": 39,"timestamp": "2025-01-01 04:40:10"}, {"id": 45,"temperature": 36,"timestamp": "2025-01-01 04:45:47"}, {"id": 46,"temperature": 40,"timestamp": "2025-01-01 04:50:18"}, {"id": 47,"temperature": 27,"timestamp": "2025-01-01 04:55:35"}, {"id": 48,"temperature": 37,"timestamp": "2025-01-01 05:00:11"}, {"id": 49,"temperature": 38,"timestamp": "2025-01-01 05:05:45"} ]
navbar
a tělo stránky. (2b)
Speciální případy, které student musí ošetřit:
BONUS (2b): Na dashboard přidejte graf naměřených hodnot v čase.
Místo slovníkového seznamu implementujte SQLite databázi. Databáze bude mít dvě tabulky - Data
, Users
. Zprovozněte registraci a přihlašování uživatelů.
Dále definujte REST API s následujícími endpointy:
{“temperature“: <value>}
URI endpointy pro API oddělte od ostatních endpointů do vlastního api_routes.py
souboru. Endopointy budou mít prefix /api/<api endpoint>
.
BONUS (2b): Definujte endpoint pro získání všech naměřených hodnot. Součástí endpointu bude nepovinný argument sort
, který bude rozhodovat o tom, zda budou data v odpovědi řazena od nejnovější, nebo od nejstarší hodnoty. Argument může nabývat hodnot [asc, desc]
.
Naprogramujte Raspberry Pi Pico W tak, aby periodicky odesílalo data o aktuální teplotě do SQLite databáze. Ke komunikaci použijte MQTT protokol.
BONUS (2 b): Zajistěte MQTT QoS třídy 1.
Rozšiřte funkcionalitu webové aplikace a programu pro Raspberry Pi Pico W o obousměrnou MQTT komunikaci. Pico W bude kromě odesílání naměřených dat také přijímat příkazy z webového serveru pro ovládání LED diody a řízení měření.
BONUS (2b): Implementujte možnost nastavení periody měření přes webové rozhraní. Uživatel může zadat požadovanou periodu v sekundách, webserver odešle hodnotu přes MQTT a Pico W podle ní upraví interval měření.
Nasaďte svou Flask aplikaci do produkčního prostředí pomocí WSGI serveru.
/health
pro kontrolu stavu aplikace. Kontrola bude zahrnovat dostupnost a funkčnost databáze (provedení testovací query), dostupnost MQTT brokeru, dobu běhu aplikace, počet zpracovaných požadavků od startu. Odpověď bude ve formátu JSON. (2b)
BONUS (2b): Omezte počet požadavků na jednotlivých API endpointech pomocí rate-limitingu. O stavu limitů informujte v odpovídajících hodnotách HTTP hlavičky (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset). Při překročení server odpovídá správným HTTP kódem.
Virtualizujte svou Flask aplikaci pomocí Docker technologií.
BONUS (2b): Konfigurace Docker volumes pro persistenci dat (alespoň pro InfluxDB). Po zastavení, odstranění, znovuvytvoření a spuštění kontejneru jsou dostupná data z doby před zastavením kontejneru.