\chapter{Úvod}
Již nějakou dobu je na vzestupu internet věcí (Internet of Things --  IoT)\footnote{\url{https://explodingtopics.com/blog/iot-stats}}. Jedná se o~síť fyzických věcí (\uv{things}), které komunikují spolu navzájem či s~jinými systémy pomocí internetu. Většinou obsahují řadu senzorů, kterými získávají data z~reálného světa a následně je využívájí pro různé akce -- ať už se jedná o~automatizaci či jejich reprezentaci v~uživatelském prostředí. Do této kategorie spadají různé věci -- od teploměru v~akváriu, přes chytré náramky či domácí spotřebiče, až po auta.
Tento velice rychlý rozvoj je způsobem mimo jiné dostupností levných a energeticky málo náročných senzorů, jednoduchostí připojením do cloudu a obecně rozvojem cloudových technologií\footnote{\url{https://www.oracle.com/internet-of-things/what-is-iot/}}.

Zároveň jsem chtěl prozkoumat chytré pěstování rostlin v~domácím prostředí. Existující řešení většinou spoléhají pouze na automatické zalívání, či i světlo podporující růst. Ovšem ne každé rostlině vyhovuje stejné světlo a navíc spektrum nelze ovlivnit. Různé vlnové délky mají na rostliny jiný vliv \cite{plants_wavelength_effect}. Proto by mohla být konkurenční výhoda mít možnost měnit intenzitu světla a i v~jaké vlnové délce. Tímto by bylo možné ovlivnit jakým způsobem rostlina roste -- jestli spíše do šířky či výšky nebo její kvetení.
Žádné dostupné řešení neumí ani analyzovat spektrum světla, přitom již existují senzory právě pro tento účel a jejich cena není astronomická

Cílem této práce je navrhnout autonomní květináč, který bude analyzovat data ze senzorů a dle přednastavení uživatele používat aktuátory pro zefektivnění růstu. A~tento systém následně implementovat pomocí dostupných vývojových platforem (v~tomto případě ESP32).


\chapter{Existující řešení}
Mnohé řešení na crowfundingových platformách, jako třeba jedno hezky graficky zpracované\footnote{\url{https://www.indiegogo.com/projects/lua-the-smart-planter-with-feelings}} jsou ve skutečnosti podvody, kdy po kampani firma vyhlásí bankrot a lidi nevidí produkt, ani své peníze.

Existují i květináče využívající hydroponii. Hydroponie je způsob pěstování rostlin mimo půdu, jen v~roztoku se živinami. Toto řešení přináší výhody v~tom, že lze přímo řídit dávkování živin, je zde menší riziko plísní a škůdců a zaručuje vyšší efektivitu růstu\footnote{\url{https://www.higarden.cz/blog/hyroponie-co-obnasi-a-jak-zacit/}}.
Nevýhodou je ovšem vyšší pořizovací cena\footnote{\url{https://www.conserve-energy-future.com/advantages-disadvantages-hydroponics.php}}. Komerčně prodávaná řešení většinou mají tyto živiny v~kapsli spolu s~rostlinou, které cenově opět nevychází úplně nejlevněji.

Nepovedlo se mi tedy najít řešení, které by obsahovalo všechno zmíněné zároveň. Tedy knihovnu přednastavení pro rostliny, osvětlení, které není stálé, ale lze nastavit v~určitých spektrech, automatické zavlažování pumpou a dostupnost skrze cloud s~dostupnými informacemi v~grafech.


\chapter{Platforma ESP32}
Série ESP32 zahrnuje čipy zaměřené na malou spotřebu, nízkou cenu a bezdrátovou konektivitu vyráběné firmou Espressif sídlící v~Číně. Ve světě má další 4 pobočky. Jedna z~poboček je dokonce v~naší republice, v~Brně. Informace jsem čerpal z~oficálních webových stránek \cite{web_espressif}.

Pro domácí kutilství a prototypování existují tzv. \uv{Devkity}, které již implementují mimo ESP32 čipu i UART pro USB komunikaci, vývody pinů a většinou alespoň jedno tlačítko a LED diodu. Některé dokonce obsahují i zabudovaný držák na baterie\footnote{\url{https://wiki.geekworm.com/WEMOS_ESP32_Board_with_18650_Battery_Holder}} nebo OLED displej\footnote{\url{https://www.lilygo.cc/products/lilygo\%C2\%AE-ttgo-t-display-1-14-inch-lcd-esp32-control-board}}

Na rozdíl od konkurenčního Arduina má již zabudovanou WiFi a Bluetooth, není tedy nutné řešit rozšiřující desky. Ale pracuje na 3.3V místo 5V, je tedy nutné dát si pozor (některé senzory potřebují 5V).

Jedná se o~nástupce ESP8266, hlavní rozdíly jsou v~tabulce:

\begin{center}
\begin{tabular}{ |c|c|c|c| } 
\hline
Funkce & ESP8266 & ESP32 \\
\hline\hline
CPU & 1 jádro Xtensa LX6 @ 160MHz & 1-2 jádra Xtensa LX6 @ 240MHz \\
\hline
WiFI & HT20 (130 Mbit) & HT40 (300 Mbit) \\
\hline
Bluetooth & ne & 4.2 + BLE \\
\hline
GPIO & 17 & 34 \\
\hline
SPI/I\textsuperscript{2}C/I\textsuperscript{2}S/UART & 2/1/2/2 & 4/2/2/2  \\
\hline
PWM & 8 kanálů & 16 kanálů \\
\hline
ADC & 10 bit & 12 bit \\
\hline
Dotykové piny & 0 & 10 \\
\hline
\end{tabular}
\end{center}

Ačkoliv může mít ESP32 dvě jádra, tak jedno je používáno pro WiFi komunikaci, aby neblokovala aplikační jádro. Uživatel je ale schopen spouštět kód na libovolném jádře.

Existují i novější typy ESP32, které obsahují RISC-V instrukční sady, novější WiFi 6 a Bluetooth 5 Low Energy či standard IEEE 802.15.4 pro komunikace na blízko mezi zařízení:

\begin{itemize}
    \item \texttt{ESP32-S2} -- LX7 @ 240MHz, jen WiFi
    \item \texttt{ESP32-S3} -- 2x LX7 @ 240MHz, WiFi + Bluetooth 5, podpora vektorových instrukcí
    \item \texttt{ESP32-C2} -- RISC-V @ 120MHz, WiFi + BL 5
    \item \texttt{ESP32-C3} -- RISC-V @ 160MHz, WiFi + BL 5
    \item \texttt{ESP32-C6} -- RISC-V @ 160MHz, WiFi 6 + BL 5 + IEEE 802.15.4
    \item \texttt{ESP32-H2} -- RISC-V @ 96MHz, BL5 + IEEE 802.15.4
\end{itemize}

\section{Komunikace se senzory a aktuátory}
Platforma ESP32 má bohaté možnosti propojení s~jinými prvky díky podpoře různých sběrnic a jejich počtu. V~podkapitolách níže uvedu jejich příklady. Pro specifikaci ohledně počtu sběrnic na ESP32 jsem čerpal z~oficiálních stránek espressif \cite{web_espressif}, pro popis I\textsuperscript{2}C a SPI sběrnic z~látky předmětu IMP (Mikroprocesorové a vestavěné systémy)\footnote{\url{https://www.fit.vut.cz/study/course/IMP/.cs}}.

\subsection{Analogová komunikace}
Funguje pomocí převodu mezi analogovým signálem na digitální nebo obráceně. Jinými slovy mapování napětí na číselné hodnoty. ESP32 obsahuje dva 8-bit digitálně analogové převodníky (DAC) a dva 12-bit analogově digitálně převodníky (ADC).

ESP32 samozřejmě umí generovat i pulzně šírkovou modulaci (PWM) na až 16-ti kanálech zároveň.

\subsection{SPI}
Je zkratka pro Serial Peripheral Interface. Jedná se o~sériovou plně duplexní komunikaci po sběrnici, tedy přenos probíhá oběma směry. ESP32 obsahuje čtyři SPI sběrnice, ovšem dvě z~nich se používají pro komunikaci s~interní flash pamětí, proto se je nedoporučuje používat.
Používá tyto vodiče:
\begin{itemize}
    \item MOSI -- Master Out Slave In -- data z~masteru do slave
    \item MISO -- Master In Slave Out -- data ze slave do masteru
    \item SPSCK -- SPI Serial Clock -- hodinový signál generovaný master zařízením
    \item SS -- Slave Select -- pro každý slave zvlášť, vybírá a aktivuje jednotku pro přenos dat v~log~0 
\end{itemize}

\subsection{I\textsuperscript{2}C}
Znamená Inter-Integrated Circuit. Stejně jako SPI se jedná o~synchronní sériovou komunikace mezi master a slave komponentami, ovšem I\textsuperscript{2}C je pouze half-duplex, tedy data mohou jít jedním směrem v~jeden moment. Původní specifikace byla navržena firmou Philips Semiconductors v~roce 1982, později proběhlo pár aktualizací.
ESP32 obsahuje dvě I\textsuperscript{2}C sběrnice.
Používá tyto vodiče:
\begin{itemize}
    \item SDA -- Serial Data -- přenos dat, start/stop podmínka, potvrzení příjmu
    \item SCL -- Serial Clock -- synchronizační signál
\end{itemize}

K~jedné sběrnici lze připojit až 127 jiných zařízení, což je velká výhoda oproti SPI, kde každý slave potřebuje vlastní SS propojení. Je toho docíleno pomocí adresování jednotlivých slave komponent. Ovšem zde nastává problém, že adresy musí být unikátní. Pokud by byly shodné, tak je nutné použít multiplexor, další I\textsuperscript{2}C sběrnici nebo změnit adresu na slave (některé devkity se senzory tuto funkci podporují, většinou stačí spájet určité plošky na desce). Tento limit je dán tím, že adresování je 8bitové, kde 1 bit je pro výběr zápisu či čtení a zbylých 7 pro adresu.

\section{Softwarová podpora}
Oficiální vývojovou platformou je ESP-IDF, která používá jazyk C/C++. Existují ovšem i alternativy, například Arduino IDE, které je vhodné pro rychlé prototypování či menší projekty (takzvané \texttt{sketch}e), ale hlavní výhoda je v~přenositelnosti mezi různými platformami mikrokontrolerů a větší množství knihoven. Jako vývojové prostředí lze použít i \texttt{PlatformIO}, které podporuje jak Arduino, tak ESP-IDF a necelých 200 ESP32 desek. 
Pokud se chceme vyvarovat C/C++, tak je možnost zvolit \texttt{MicroPython} -- což je Python určený pro mikrokontrolery.

Samotné ESP32 implementuje FreeRTOS (Real-Time Operating System) v~upravené podobě pod názvem \texttt{ESP-IDF FreeRTOS}, primárně z~důvodu podpory více CPU jader\footnote{\url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html}}. Jedná se o~jednoduchý systém vyvinutý pro mikrokontrolery, který mimo jiné umožňuje za běhu vytvářet úkoly (\texttt{tasks}), které s~využitím čekání a přerušení umožňují multitasking.

Mimo programování pro mikrokontroler lze psát kód i v~assembleru pro ULP (Ultra Low Power) koprocesor, který je aktivní i v~hlubokém spánku, kdy nejsou aktivní jádra procesoru. ULP slouží pro převody pomocí ADC, měření pomocí teplotního čidla či externích I2C senzorů a obsluhu RTC GPIO pinů. Je taky možné pomocí něj probudit ESP32 ze spánku\footnote{\url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/ulp.html}}.

\chapter{Cloudová komunikace s~ESP32}
Pro komunikaci je možné využít více protokolů, ovšem každý má své výhody a nevýhody a proto se hodí na rozdílné věci.

Taktéž je možné využít P2P (Peer-to-peer) komunikaci mezi jednotlivými mikrokontrolery v~místech, kde není WiFi signál. Pokud bych uvažoval téma mé práce, tak třeba velký skleník, kde je mnoho květináčů, ale není zde 100\% pokrytí WiFi signálem. Pak by byla data posílána mezi jednotlivými senzorickými uzly a odeslána tím, který by měl dostupný WiFi signál z~routeru. Jedná se  o~\textbf{ESP-NOW} a \textbf{ESP-WIFI-MESH}.

\section{ESP-NOW}
Redukuje 5 vrstev OSI pouze na 1, navíc nepoužívá hlavičky jako typická komunikace po internetu, je tedy méně náročný. Odezva je maximálně 150ms.
Nevýhodou je nutnost znát MAC adresu. Je zde taktéž limit 20 spárovaných zařízení, 6 pokud je zapnuté šifrování. Jedná se o~limit na zařízení, lze tedy vytvořit síť s~více zařízeními, kdy nejsou všechny spojeny se všemi. Je možné využít broadcast, který žádný limit nemá, ale posílá úplně všem, i nespárovaným, tedy nutno vyřešit zabezpečení. Limit velikosti přenášených dat je 250 bajtů\footnote{\url{https://docs.espressif.com/projects/espressif-esp-faq/en/latest/application-solution/esp-now.html}}.

\section{ESP-WIFI-MESH}
Na rozdíl od ESP-NOW má výhodu, že podporuje automatické formování a uzdravování meshe při odebrání/přidání nového zařízení. Rychlost přenosu je až 10Mbps a dosah 200 metrů. Limit velikosti přenášených dat je 1456 bajtů.
Nevýhodou je nutno použít vývojový framework \textbf{ESP-MDF} místo \textbf{ESP-IDF} (ten je již obsažen)\footnote{\url{https://www.espressif.com/en/products/sdks/esp-wifi-mesh/overview}}.

\section{REST}
\label{section_rest}
Jedná se o~akronym -- \texttt{REpresentative State Transfer}, který popisuje architekturu komunikace přes protokol (většinou HTTP). Umožňuje práci s~daty na serveru dle dotazů klienta.
Rozhraní (API) splňující podmínky RESTu se označuje jako \uv{RESTful} \cite{web_rest_api}.
Definuje tzv. \texttt{endpointy} (koncové body) na které se klient dotazuje a je mu odeslána odpověd.

Používá 4 základní operace -- \textbf{CRUD} a jejich příklady:
\begin{itemize}
    \item Create (POST) -- \texttt{HTTP POST /devices}
    \item Read (GET) -- \texttt{HTTP GET /devices/dev1}
    \item Update (PUT) -- \texttt{HTTP PUT /devices/dev1}
    \item Delete (DELETE) -- \texttt{HTTP DELETE /devices/dev1}
\end{itemize}

Díky této architektuře je možné vytvořit aplikaci formou klient -- server, kdy tyto 2 celky mohou být na odlišných strojích a komunikovat spolu pomocí REST API. Klient nemusí být ani frontend webové aplikace, ale třeba přímo nativní aplikace na telefonu či jiné plaformě, ale stále může používat stejné API serveru pomocí HTTP dotazů. To znamená i~jednodušší vývoj a škálovatelnost do budoucna, jen je nutno zachovat kompatibilitu API mezi klienty a serverem. Což lze docílit po velké změně API pomocí úpravy cesty k~endpointu, např. přidat \uv{ver1} do URI a tak zachovat více verzí API zároveň.

\section{MQTT}
\label{section_mqtt}
Dlouze \texttt{Message Queuing Telemetry Transport}, ovšem tento název se příliš nepoužívá, neboť protokol zpracovává více věcí, než je z~názvu patrné.
Jedná se o~protokol vhodný pro IoT zařízení, neboť díky své jednoduchosti není příliš náročný na výpočetní výkon a objem přenesených dat.

Architektura MQTT potřebuje mezičlen, tzv. \uv{MQTT Broker}. Ten obstarává klienty tak, že zpracovává přijaté zprávy tříděním dle témat, tzv \uv{topiců} a ty následně odesílá všem klientům, kteří mají o~ně zájem.
Témata tvoří strukturu podobnou adresářové oddělenou lomítky, např. \texttt{domov/pokoj1/teplota}.

Komunikace probíhá pomocí pub/sub modelu. Odesílání zpráv je za pomoci \uv{publish} na dané téma, broker následně přepošle danou zprávu všem klientům, kteří požádali o~\uv{subscribe} na zmíněné téma. Aby mohl klient odesílat zprávy, tak není nutné, aby byl přihlášen k~danému tématu.

Zprávy mohou mít 3 úrovně QoS (Quality of Service), které určují garanci doručení:
\begin{itemize}
    \item \texttt{QoS 0} -- \uv{Maximálně jednou} -- zpráva se může ztratit
    \item \texttt{QoS 1} -- \uv{Minimálně jednou} -- zpráva může být doručena vícekrát
    \item \texttt{QoS 2} -- \uv{Pouze jednou} -- zpráva je doručena přesně jednou
\end{itemize}
Je důležité je správně použít v~implementaci, protože využitím nesprávné se mohou ztratit důležitá data nebo naopak bude zbytečná zátěž co se týče datových přenosů v~řádu desítek procent -- rozdíl mezi QoS 0 a 1 je zhruba 40\% a mezi QoS 1 a 2 zhruba 50\%\footnote{\url{https://medium.com/@dheeptuck/how-to-optimize-data-usage-over-mqtt-792abebd2cd1}}.

\subsection{MQTT vs HTTP přenos}
Pokud porovnáme tyto 2 typy přenosů, tak vyjde najevo, že již při 2 zprávách je výhodnější použít MQTT než zasílat data přes HTTP. Tabulka převzata od HiveMQ\footnote{\url{https://www.hivemq.com/blog/mqtt-vs-http-protocols-in-iot-iiot/}}.

\begin{center}
\begin{tabular}{ |c|c|c|c| } 
\hline
Akce & MQTT & HTTP \\
\hline\hline
Připojení & 5572 & 2261 \\
\hline
Odpojení & 376 (opt) & 0 \\
\hline
Odeslání zprávy & 388 & 3285 \\
\hline
Součet pro 1 zprávu & 6336 & 5546 \\
\hline
Součet pro 10 zpráv & 9829 & 55460 \\
\hline
Součet pro 100 zpráv & 44748 & 546000 \\
\hline
\end{tabular}
\end{center}

Důvodem velkého rozdílu je to, že primární overhead u~MQTT je připojení na broker, ale u~HTTP je overhead u~každého requestu.

\chapter{Chytré pěstování rostlin}
V~dnešní době lze zefektivnit pěstování rostlin díky využití IoT zařízení, které monitorují prostředí v~reálném čase díky různým senzorům a následně provádí akce pro optimalizaci -- ať už se jedná o~zrychlení růstu či o~úsporu zdrojů. Z~pravidla se jedná o~světelné, teplotní, vlhkostní a živiny upravující akce.

\section{Půdní vlastnosti}
Půda ovlivňuje mnoho faktorů pro růst rostliny a i ostatní veličiny. Je pro rostlinu zdrojem živin. Pro následující teorii jsem čerpal z~\cite{plants_water_webpage} a \cite{plants_water}. Z~druhého zmíněného zdroje jsou i informace ohledně půdní pH.

\subsection{Obsah vody}
Pro měření obsahu vody v~půdě jsou nejběžnější 2 způsoby:
Gravimetrický obsah vody v~půdě (GWC -- \textbf{Gravimetric Water Content}) měří hmotnost vody v~půdě. Tato hodnota se získává měřením rozdílu váhy vysušené půdy

\[\text{GWC }(\%) = \frac{\text{hmotnost mokré půdy (g)} - \text{hmotnost vysušené půdy (g)}}{\text{hmotnost vysušené půdy (g)}} * 100\] 

Jelikož se půda suší v~troubě při teplotě okolo 105°C, tak je tato metoda považována za destruktivní, jelikož je půda nepoužitelná na další analýzu.

Dalším způsobem je objemový obsah vody (VWC -- \textbf{Volumetric Water Content}), který se zabývá poměrem objemu vody a půdy. Na tomto způsobu pracují i senzory půdní vlhkosti. Rovnice je následující:

\[\text{VWC }(\%) = \frac{\text{objem vody (ml)}}{\text{objem půdy (ml)}} * 100\]

\subsection{Kyselost a zásaditost}
Koncentrace vodíkového kationtu ($H^+$) určuje kyselost, z~tohoto vychází logaritmická stupnice pH s~rozsahem od 0 po 14 s~tím, že interval mezi 6,5 až 7,4 definuje neutrální pH. Půdy mají většinou pH mezi 4 a 8.

Rostliny preferují rozmezí podobné neutrálnímu, ale mírně ke kyselosti, tedy mezi 6 a 7 pH, ale třeba borůvky mají nejraději pH 4\footnote{\url{https://www.almanac.com/plant-ph}}. Důvod proč je vhodné udržovat ideální pH je ten, že rostliny jsou pak schopny nejlépe získávat živiny z~půdy.

\section{Světelné vlastnosti}
\label{section_plants_light_effects}
V~této kapitole jsem čerpal primárně z~\cite{plants_wavelength_effect}.

Světlo je pro rostliny jeden z~nejdůležitějších prvků, který ovlivňuje jak rostlina roste.
Záleží na vlnové délce (kvalitě), množství (kvantitě), úhlu a trvání (fotoperiodě).

Rostliny reagují na světlo fotosyntézou v~rozmezí fotosynteticky aktivního záření (Photosynthetically Active Radiation -- \textbf{PAR}) mezi 400 a 700nm. S~tím, že nejvíce v~části s~modrým a červeným světlem. Rozpětí mezi 500 a 600nm má velmi malou absorbci kvůli rozptylu světla mezi molekulami vody v~rostlinných buňkách listů a vzduchem ve vnitrobuněčných prostorách.

Relativně novým prvkem pozorování je ovšem i spektrum mezi 700 a 800nm označované jako \uv{daleká červená} (Far Red, občas taky Deep Red). Světlo o~této vlnové délce je sotva viditelné lidským okem, pouze jako velmi tmavá červená o~malém jasu. U~rostlin toto záření podporuje velmi rychlý růst, neboť si rostlina myslí, že je ve stínu pod jinou vyšší rostlinou, která blokuje světlo ze slunce. Tento jev je označován jako 
\textbf{shade-avoidance response}, tedy reakce na vyhýbání se stínu \cite{plants_far_red}. Cílem tohoto růstu je získat co nejvíce světla ze slunce pro sebe.
Princip tohoto chování tkví v~tom, že rostliny mají 2 fytochromy (fotoreceptory pro červenou barvu\footnote{\url{https://www.studysmarter.co.uk/explanations/biology/plant-biology/phytochromes/}}), jeden pro červenou P\textsubscript{R} a druhý pro dalece červenou P\textsubscript{FR}. Pokud klesne podíl červené a stoupne podíl daleké červené, rostlina na to zareaguje výše popsaným zrychlením růstu. Důvod, proč je podíl dalece červené vyšší pod rostlinami je ten, že listy absorbují více červenou a méně dalece červenou.

\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{obrazky-figures/red_far_red.png}
\caption{Spektrum s~označeným P\textsubscript{R} a P\textsubscript{FR}\cite{plants_far_red}}
\label{fig_red_far_red}
\end{figure}

Další veličinou je \textbf{PPF} (Photosynthetic Photon Flux), která určuje množství vyzářených fotonů v~rozmezí PAR. Její jednotkou je µmol/s. Tato veličina nepočítá s~plochou, jedná se pouze o~počet vyzářených fotonů. Na tento účel se používá následující veličina.

Tím je \textbf{PPFD} (Photosynthetic Photon Flux Density), definuje kolik fotonů dopadne na jeden metr čtvereční za sekundu. Jednotkou je µmol/m2/s.
Důležitá je i vzdálenost od zdroje světla. Čím blíže znamená větší koncentrace fotonů. Tento efekt by tedy šlo přirovnat k~brokovnici\footnote{\url{https://www.growmarket.cz/a/metriky-pro-mereni-pestebniho-svetla-ppf-ppfd-dli}}. Pokles koncentrace je i vidět na následujícím obrázku \ref{fig_ppf_ppfd}.

\begin{figure}[!hbt]
\centering
\includegraphics[width=0.8\textwidth]{obrazky-figures/ppf_ppfd.jpg}
\caption[]{Rozdíl mezi PPF a PPFD\footnotemark}
\label{fig_ppf_ppfd}
\end{figure}
\footnotetext{Převzato z: \url{https://www.waveformlighting.com/horticulture/what-is-the-difference-between-ppfd-and-ppf}}

V~komerční sféře mají skleníkové rostliny mezi 100 a 200 µmol/m2/s po dobu 16-ti až 20-ti hodin denně.


\chapter{Návrh vestavěného systému}
Samotný návrh lze rozdělit do 2 celků -- senzorický uzel s~aktuátory ovládaný ESP32 a~webovou aplikaci běžící v~cloudu.

\begin{figure}[hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/navrh.pdf}
\caption{Obecný návrh systému}
\label{navrh}
\end{figure}

\section{Senzorický uzel}
Jádrem celé jednotky je mikrokontroler obsluhující celkově 4 senzory a 2 aktuátory. S~tím, že aktuátor PCA9685 PWM Driver ovládá 7 různých 1W LED diod s~rozdílnou vlnovou délkou pro pokrytí rozsahu spektra PAR. Jelikož se jedná o~vysoce svítivé diody, tak potřebují chladič a externí napájení, proto bylo nutné zvolit dostatečně výkonný zdroj. 

Informace a specifikace použitých senzorů jsou zmíněny v~následující kapitole s~implementací hardwaru, viz \ref{section_hardware}.

Po stránce softwaru musí být možné skrze mikrokontroler zadat údaje k~připojení se na WiFi a možnost unikátní identifikace zařízení. Pro tyto účely se hodí možnost zapnout ESP32 v~režimu WiFi přístupového bodu a zobrazit uživateli formulář pro zadání těchto údajů. Pro identifikaci zařízení je použito UUID\footnote{UUID -- Universally unique identifier}, které zároveň slouží jako primární klíč v~databázi.

\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{obrazky-figures/esp32_flow.pdf}
\caption{Schéma chování senzorového uzlu}
\label{esp32_flow}
\end{figure}

\section{Webová aplikace}
Jako frontend pro prezentaci dat a změnu nastavení chování senzorického uzlu jsem zvolil jednoduchou webovou aplikaci, neboť je dostupná ze všech typů zařízení a ne jen z~jedné platformy, pokud bych se vydal cestou nativní aplikace.

Jelikož celkový návrh počítá s~více možnostmi nastavení, tak aplikace obsahuje knihovnu přednastavení, kde jsou jak oficiální (vytvořené admin účtem), tak od jiných uživatelů. U~všech lze psát komentáře jako forma zpětné vazby a informace pro jiné uživatele.

Webová aplikace je navržena formou klient--server, kde klientem je webový frontend využívající javascriptovou knihovnu React\footnote{\url{https://react.dev/}} -- pro tvorbu uživatelského prostředí za pomoci komponent, které se následně spojují pro vytvoření celých stránek.
Serverem je backend využívající framework Express pod frameworkem Node.js\footnote{\url{https://nodejs.org/en}} -- ten slouží pro spouštění javascript kódu mimo webový prohlížeč. Tím pádem je oddělena logika práce s~daty na serveru a zobrazování na klientu. Díky tomu je systém lepší na údržbu. Tyto 2 celky spolu komunikují pomocí REST API.


\section{Databáze}
Z~důvodu velkého množství dat ze senzorů není vhodné použít klasickou relační databázi, ale \textbf{Time Series DataBase} (TSDB). Tyto databáze jsou pro tyto účely optimalizovány. Jeden záznam obsahuje časový údaj (time stamp) a datový pár měření-hodnota, většinou ale i nějaké identifikační tagy (např. kde se senzor nachází a kdo jej vlastní).

\subsection{InfluxDB}
Nejpoužívanější TSDB je InfluxDB\footnote{\url{https://www.influxdata.com/time-series-database/\#ranking}}, kterou jsem se rozhodl v~této práci taktéž použít. Její datový záznam vypadá následovně:
\texttt{<measurement name>,<tag set> <field set> <timestamp>} \cite{influx_case_study}.

Nejvyšším prvkem datového modelu v~této databázi je \textbf{Organizace}. Ta obsahuje skupinu uživatelů, kbelíky a úkoly. 

Data jsou v~databázi rozdělena do kbelíků (\textbf{Bucket}). Tento objekt uchovává jednotlivá měření -- i více než jeden druh. Navíc je možné na něm nastavit časový údaj, po který se mají uložená data uchovat. Tím pádem lze mít automatické čištění již nepotřebných dat.

Samotné měření (\textbf{Measurement}) je vlastně kontejner pro množinu dat. Jedná se o~páry typu \texttt{field -- value}, \texttt{tag key -- tag value} a časem měření. Jeho identifikace je název ve formě řetězce. Tento název je následně v~databázi ve sloupci \texttt{\_measurement}.

Množina \textbf{Field}ů většinou obsahuje samotná data, která se mají uchovat. Jedná se o~dvojice kdy klíč a hodnota jsou ve 2 různých sloupcích -- \texttt{\_field} a \texttt{\_value}. 

Množina štítků (\textbf{Tag}) je volitelná, ale hodí se pro odlišení dat (slouží jako metadata) a použití v~dotazech do databáze. A~to z~důvodu, že jsou na rozdíl od fieldů indexované a tedy daleko rychlejší. Stejně jako fieldy se jedná o~dvojici klíč -- hodnota, ale v~tomto případě je klíč název sloupce a jednotlivé hodnoty jsou jako řádky.

Dalším důležitým pojmem jsou série (\textbf{Series}). Ty tvoří množiny bodů, které mají stejné měření, štítky a klíč od fieldu.

Jednotlivé body (\textbf{Points}) jsou definovány sérií v~určitém čase a hodnotou fieldů.

Další výhodou InfluxDB jsou úkoly (\textbf{Tasks}), což jsou uživatelem definované skripty, které se spouští v~určitém čase\footnote{\url{https://docs.influxdata.com/influxdb/v2.7/process-data/get-started/}}. Mohou sloužit pro agregování dat z~celého dne (například průměr za hodinu místo velkého množství dat generovaných každých 5 minut) z~kbelíku A~a následné vložení do kbelíku B, který má nastavený delší limit vymazání dat, neboť je v~něm méně záznamů vůči předchozímu kbelíku.

Pro účely této práce se zapisují data obsahující název měření, štítek s~UUID zařízení pro identifikaci a následně samotný pár field--value. Tedy výchozí, pouze s~jedním identifikačním štítkem.

\begin{figure}[hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/influx_web.jpg}
\caption{Přehled dat v~administraci Influx DB}
\label{influx_web_db}
\end{figure}

\subsection{Relační DB}
Pro uchování ostatních dat webové aplikace jsem použil relační databázi MySQL. 

S~oběmi databázemi komunikuje pouze backend webové aplikace. Klient tedy musí zasílat dotazy na server přes REST API a senzorický uzel zasílá data přes MQTT na server.

\begin{figure}[hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/uml-db.pdf}
\caption{ER diagram tříd v MySQL databázi}
\label{uml_db}
\end{figure}

\section{Komunikace mezi komponentami}
\label{section_communiction_between_components}
Z~důvodu použití různých technologí je vhodné mít i různé typy komunikace vyhovující pro daný účel. Pro tuto práci používám přenos přes WiFi pomocí MQTT a HTTP dotazů na API.

\subsection{Mikrokontroler a backend webové aplikace}
\label{subsection_communication_mcu_backend}
Z~důvodu ideálně co nejmenší spotřeby zdrojů na ESP32 je pro tuto komunikaci vybrán protokol MQTT, který je detailně popsaný v~podkapitole \ref{section_mqtt}. V~tomto případě MQTT přenáší zprávy ve formátování JSON.
Z~důvodu obousměrné komunikace je mikrokontroler a backend připojen do různých témat. 

Prvním tématem je \texttt{esp32/alive}. Zde publikuje zprávy mikrokontroler, neboť dává o~sobě vědět serveru, že je aktivní a chtěl by získat aktuální informace o~přednastavení definované uživatelem. Obsahem zprávy je pouze UUID zařízení. Jelikož je tato zpráva důležitá, tak se používá QoS 1 (tedy garanci doručení alespoň jednou).

Dalším tématem, spíše tématy, je \texttt{esp32/devices/\{UUID zařízení\}}. Zde probíhá komunikace ze strany serveru, který zasílá přednastavení do mikrokontroleru. Jedná se o~jediné téma, které je odebíráno mikrokontrolerem. Zprávy zde opět používájí QoS 1.

Pro zasílání dat na server z~mikrokontroleru slouží téma \texttt{esp32/sensors}. Zde publikované zprávy obsahují UUID zařízení pro identifikaci a jeho aktuální naměřené hodnoty ze senzorů. Jelikož se jedná pouze o~data pro vizualizaci na frontendu webu v~grafech, tak je zde použit QoS 0 (zpráva je doručena maximálě jednou, ale může se stát, že nebude doručena vůbec).

\subsection{Frontend a backend webové aplikace}
\label{subsection_communication_frontend_backend}
Pro účely komunikace mezi těmito komponentami by nebylo příliš vhodné komunikovat přes broker jak u~MQTT, proto se zde používá \texttt{REST API}. Jak funguje tento způsob komunikace je již popsáno v~podkapitole \ref{section_rest}. Data jsou přenášena taktéž ve formě JSON objektů.

Aplikace používá koncové body odpovídající datovému modelu v~relační databázi a jeden pro data ze senzorů. Jedná se o~následující body:

\begin{itemize}
    \item \texttt{/users} -- primárně pro čtení uživatelů z~databáze, jelikož tvorba uživatelů probíhá skrze koncové body určené pro autentizaci
    \item \texttt{/records} -- slouží pro čtení záznamů ze senzorů v~InfluxDB
    \item \texttt{/devices} -- pro práci s~jednotlivými zařízeními, plná podpora CRUD
    \item \texttt{/presets} -- slouží pro editaci přednastavení, jak privátních pro zařízení, tak veřejných. Obsahuje ještě koncový bod \texttt{/data}, který vrací pouze data o~přednastavení, plná podpora CRUD
    \item \texttt{/comments} -- pro CRUD operace s~komentáři
\end{itemize}

Pro autentizaci uživatele slouží ještě další samostatné koncové body, které jsou definované v~\texttt{authRoutes.js}, a to: \texttt{/login}, \texttt{/register}, \texttt{/logout}. A~pro změny údajů uživatele \texttt{/changePassword} a \texttt{/changeEmail}. 

\subsection{Mikrokontroler a klient (webový prohlížeč)}
Tato komunikace probíhá pouze pokud je zařízení v~režimu WiFi přístupového bodu při konfiguraci. Jedná se podobně jako u~\ref{subsection_communication_frontend_backend} komunikaci pomocí HTTP API, ale obsahuje pouze 2 koncové body se 3 možnostmi.

\begin{itemize}
    \item \texttt{/ (GET)} -- Jako odpověď se odešle stránka s~konfiguračním formulářem do webového prohlížeče uživatele.
    \item \texttt{/ (POST)} -- Zaslání dat od uživatele na mikrokontroler.
    \item \texttt{/restart} -- Bez přenosu dat, pouze pro restartování zařízení.
\end{itemize}



\chapter{Implementace}
V~této kapitole se budu věnovat samotné realizaci návrhu, výběru konkrétních senzorů a překonání strastí, které vypluly na povrch.

Samotná kapitola je rozdělena na více sekcí. První se týká použitých součástek a elektronického zapojení \ref{section_hardware}. Poté tisknutí květináče na 3D tiskárně \ref{section_3D_print}. Následující pasáže se týkají již samotné implementace v~softwaru, jak na ESP32 \ref{section_impl_esp_idf_libs}, tak část s~webovou aplikací \ref{section_impl_web_app}.

Prvně jsem chtěl tuto práci implementovat v~prostředí Arduino IDE -- zde jsem i napsal demo implementaci obsahující většinu návrhu bez senzorů (tedy primárně komunikaci pomocí MQTT, konfiguraci přes WiFi AP a experimenty se spánkovými režimy ESP32). Důvod byl, že je zde více dostupných knihoven, ale pak jsem vyzkoušel ESP-IDF pod PlatformIO a práce mi ve výsledku přišla příjemnější, ba dokonce připojování na domácí WiFi síť a MQTT probíhalo rychleji. Navíc možnost eliminovat blokování celého programu kvůli \texttt{delay()} metodám, které jsou i v~Arduino knihovnách, pomocí FreeRTOS tasků se taky hodí.

\section{Hardware}
\label{section_hardware}
Pro účely této práce jsem jako mikrokontroler použil \textbf{FireBeetle 2 ESP32--E}. Informace jsem čerpal z~wiki stránek produktu \cite{web_dfrobot_esp32}, které byly v~březnu roku 2023 upraveny s~lepším přehledem pinů a jejich vlastností. Jedná se o~vylepšenou verzi FireBeetle ESP32, jak již název napovídá, obsahuje modul ESP32--E (opravuje primárně chyby na HW úrovni\footnote{\url{https://www.dfrobot.com/product-2195.html}}). 

Výhody tohoto devkitou jsou, že obsahuje PH2.0 konektor pro Li--ion baterie a i zabudovaný nabíjecí obvod. Dále pak GDI konektor pro připojení displeje. Pro zpětnou vazbu jsou přímo na desce 2 uživatelsky ovládané LED diody. Jedna zelená LED dioda na pinu D9 a poté WS2812 RGB LED dioda na pinu D8.
Důležitá vlastnost je i ta, že tato deska má velmi nízkou spotřebu ve spánkovém režimu, již její předchůdce v~tomto vynikal\footnote{\url{https://diyi0t.com/reduce-the-esp32-power-consumption/}}. Pro dosažení ještě větší úspory energie je možné přeříznout tenkou spojnici na desce, která odpojí zabudovanou RGB diodu při napájení z~baterie pro pokles odběru o~\SI{500}{\micro\ampere}. Spotřeba ve spánku je pak \SI{13}{\micro\ampere}.
Menší nevýhoda vůči jiným ESP32 devkitům je interní flash pamět o~velikosti 4MB (předchůdce měl 16MB), ale i tak je dostatečná.

Co se týče senzorů, tak na okolní teplotu a vlhkost byl použit \textbf{SHT31} jelikož je přesnější a i levnější než často používaný \textbf{DHT22} \cite{web_sensors_humidity_compare}. Senzor zvládá měřit teplotu v~rozsahu -40 až 120°C s~přesností 0,3°C a vlhkost v~rozsahu 0 až 100\% RH s~přesností 2\%\footnote{\url{https://www.laskakit.cz/senzor-teploty-a-vlhkosti-vzduchu-sht31/}}. Tento senzor je zapojen v~nepájivém poli vedle samotného devkitu. Jeho I\textsuperscript{2}C adresa je 0x44.

Pro monitoring hladiny vody v~nádržce byl použit ToF (Time of Flight) senzor \textbf{VL53L0X}. Jedná se spíše o~nevšední řešení pro hobby projekt (invazivní plováky jsou častější), ale šlo dohledat použití konkrétního senzoru i pro tento účel, který skončil úspěchem\footnote{\url{https://www.hackster.io/team-protocentral/liquid-level-sensing-using-a-laser-tof-sensor-d04232}}. Princip tohoto senzoru spočívá v~tom, že vyšle infračervený laserový paprsek (není vidět lidským okem) a následně měří dobu jeho letu než se odrazí od nějakého objektu zpátky k~senzoru\footnote{\url{https://www.makeuseof.com/what-is-time-of-flight-sensor-how-does-tof-work/}}. Nevýhoda tohoto řešení je ta, že je zde minimální vzdálenost pod kterou nezvládne měřit -- v~případě VL53L0X to jsou zhruba 3cm. Je tedy nutné si dát pozor na to, aby voda nevystoupala nad tuto úroveň, což je vyřešeno umístěním senzoru na podstavu. Ta je tvořena distančním stojánkem určeným pro krabici pizzy nalepeným na víku nádržky s~vodou. I\textsuperscript{2}C adresa tohoto senzoru je 0x29.

Nejexotičtější senzor celého projektu je spektrální senzor světla \textbf{DFRobot AS7341}, který je i dostatečně přesný pro měření PPFD \cite{sensors_light_plants_par}. Informace jsem čerpal z~wiki stránek produktu \cite{web_dfrobot_as7341}. Měří v~11-ti kanálech. Z~těchto kanálu je 8 (pojmenovány \uv{F1} až \uv{F8}) dle vlnové délky s~rozsahem začínajícím na 405nm a končícím u~690nm -- což zhruba odpovídá rozsahu PAR na který reagují rostliny (popsáno v~kapitole \ref{section_plants_light_effects}).
Dalším kanálem s~filtrem dle vlnové délky je \uv{NIR} (Near InfraRed), který zvládá měřit v~blízkosti IR záření okolo 900nm. Předposlední kanál je bez filtru na vlnovou délku nazýván \uv{Clear}, který měří všechno dopadající světlo. Poslední kanál slouží pro detekci blikání ve frekvenci 50 nebo 60Hz.
Výhodou tohoto senzoru je to, že měří světlo dopadající z~okolí a nefunguje pouze na principu poznání barvy nasvíceného předmětu pomocí zdroje světla, což by pro tuto práci nebylo vyhovující. Ovšem i tuto funkci může zastoupit díky 2 LED diodám určným pro tento účel.
Senzor obsahuje 6 nezávislých 16-ti bitových ADC převodníků, proto je nutné měřit ve 2 krocích pro získání všech kanálů. Jejich citlivost lze nastavit v~11-ti stupních změnou parametru \texttt{AGAIN} v~rozmezí 0 až 10. To odpovídá hodnotám 0,5 a poté druhé mocnině od 1 po 512\cite{sensors_as7341_datasheet}. Reálně ovšem hodnoty nejsou násobeny přesně touto hodnotou, ale jsou zde mírné odchylky, které jsou uvedeny v~dokumentaci AS7341. Jeho I\textsuperscript{2}C adresa je 0x39.

Až na senzor půdní vlhkosti, který je analogový, komunikují senzory s~ESP32 pomocí I\textsuperscript{2}C sběrnice, což znamená pouze propojit SDA a SCL piny a samozřejmě napájení 3V3 a GND. Jediný požadavek tedy je, aby měly všechny senzory unikátní I\textsuperscript{2}C adresu a nekomunikovali po stejné sběrnici zároveň. Použité senzory tento požadavek splňují, ovšem po I\textsuperscript{2}C komunikuje i PWM driver, ale jeho adresa je taktéž unikátní -- 0x40. V~případě, kdyby nebyla, tak je možné jeho adresu změnit spájením plošek na jeho desce.

\subsection{Senzor vlhkosti půdy}
Následující informace jsem čerpal ze srovnání více typů senzorů na měření vlhkosti z~\cite{web_sensors_soil_compare}.

Pro měření vlhkosti v~půdě lze použít několik typů senzorů. Odporové fungují na principu měření vodivosti mezi 2 elektrodami zanořenými do půdy, zvýšení obsahu vody znamená snížení odporu. Odezva na změnu obsahu vody je zhruba 9 minut. Nevýhoda těchto čidel je ale ta, že mají obnažené elektrody a tedy zde probíhá elektrolýza a tím pádem degradují při měření. Proto je nutné do tohoto typu senzoru pouštět proud po co nejmenší časový úsek.

Druhým typem jsou kapacitní čidla. Na rozdíl od odporových mají jen jednu sondu místo dvou, navíc není obnažená, proto tento typ senzorů nepodléhá degradaci při měření. Další výhodou je rychlejší reakce na změnu obsahu vody v~půdě, jen okolo jedné minuty. Fungují na principu změny dielektrické konstanty, čím více vody, tím je vyšší. Nevýhodou je trochu vyšší cena, ale hlavně to, že konkrétní použité čidlo\footnote{\url{https://www.laskakit.cz/kapacitni-cidlo-pro-mereni-vlhkosti-pudy/}} nemá voděodolnou horní část sondy, neboť jsou zde elektronické součástky. Tento problém byl vyřešen zalitím obvodu do lepidla z~tavné pistole.

Senzor půdní vlhkosti je zapojen do GPIO 35, což je pin 1. ADC převodníku na 7. kanálu. Pro tento účel se musel použít ADC1 a ne ADC2 z~důvodu, že ten je používán WiFi, která je aktivní. Rozlišení převodníku je nastaveno na plných 12 bitů a attentuation (útlum) je nastaven na 11dB, což je maximální možný pro největší rozsah napětí\footnote{\url{https://docs.espressif.com/projects/esp-idf/en/v4.4.4/esp32/api-reference/peripherals/adc.html\#adc-attenuation}}.

\begin{figure}[hbt]
\centering
\includegraphics[width=0.5\textwidth]{obrazky-figures/esp32_sensors.pdf}
\caption{Schéma zapojení senzorů}
\label{esp32_sensors}
\end{figure}

\subsection{LED osvětelní}
\label{subsection_led_lightning}
Ovládání LED diod obstarává 16-ti kanálový PWM driver \textbf{PCA9685}. Jedná se o~verzi z~LaskaKit, ale specifikace je stejná jako deska od Adafruit. Odtud jsem tedy čerpal informace \cite{web_pca9685}. Má oddělené napájení desky (VCC) a napájení servo motorů (V+) s~limitem \SI{10}{\ampere} a \SI{6}{\volt}. Což plně dostačuje pro LED diody. Zároveň každý datový PWM pin má v~sérii odpor o~hodnotě \SI{220}{\ohm}, což limituje maximální proud na \SI{25}{\milli\ampere}. Tohoto limitu se ovšem nikdy nedosáhne, neboť deska je v~případě této práce napájena z~3V3 pinu, tedy maximální proud je \SI{15}{\milli\ampere}.

Důvod, proč jsem použil tento driver a ne PWM přímo z~ESP32 je ten, že diod je 7 a jsou vzdálené od ESP32, tedy je rozdíl natahovat mnoho dlouhých kabelů pro každou diodu zvlášť a nebo 2 kabely pro I\textsuperscript{2}C propojení a 2 pro napájení. Zároveň se tím uspoří mnoho GPIO pinů.

Samotné LED diody jsou běžné 1W SMD s~chladičem. Jejich vlnové délky jsou následující: 400, 450, 525, 595, 625, 690 a 730nm. Jejich úhel svitu je 120° (díky čočce z~výroby), nebylo tedy potřeba používat difuzor či jiné čočky.

Jelikož mají LED diody vysoký odběr proudu na to, aby je nápajelo ESP32, bylo nutno rozdělit napájení MCU a diod. Použil jsem USB zdroj (5V @ 3.1A) s~2 výstupy -- jeden USB-C kabel pro napájení ESP32 a USB-A zdířka pro zapojení dalšího kabelu, který vede energii k~osvětlení. Jelikož mají použité LED diody různé požadavky na napětí, tak byly rozděleny do 2 shluků. Pro snížení napětí se používají dva DC -- DC stepdown měniče \textbf{LM2596}, které mají maximální proud 2A, chvilkově zvládnou až 3A.
První shluk o~4 diodách má napětí 2.35V, IR dioda má ovšem limit 2.1V, proto je zde použit odpor o~hodnotě 0.47Ω. Druhý shluk napájí zbylé 3 diody 3.55V. Detailnější spotřebě energie je věnována následující sekce \ref{section_power_consumption}.

Pro rozsvícení diod se používají NPN tranzistory zapojené jako přepínač. Jedná se o~\textbf{BC338-40}, které mají maximální proud 0.8A a dostatečný koeficient $h_{FE}$. Jejich báze jsou napojeny na jednotlivé datové piny PWM driveru, ty zvládají maximální proud 25mA, ale mají sériově zapojen 220Ω odpor, což limituje proud při použití desky na 3V3 na 15mA, ale to by i tak povolovalo velký proud do LED diod. Pro proud 300mA je dle specifikace $h_{FE}$ minimálně 170, typicky 320. Z~tohoto důvodu jsem zde připojil ještě odpor o~hodnotě 1kΩ, tedy celkově 1220Ω před bází tranzistoru:
\[I_B = \frac{U_B - U_{BE}}{R_B}\]
\[I_B = \frac{3,3 - 0,7}{1220} = 2,13mA\]
Pokud uvažujeme $h_{FE}$ 170, tak to odpovídá proudu zhruba 362mA mezi kolektorem a emitorem. Což je dostatečné.

\begin{figure}[!hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/esp32_leds.pdf}
\caption{Schéma zapojení LED diod}
\label{esp32_leds}
\end{figure}


\subsection{Čerpadlo}
\label{subsection_pump}
Pro zalévání bylo použito mini čerpadlo s~odběrem pouhých 220mA\footnote{\url{https://navody.dratek.cz/navody-k-produktum/mini-dc-cerpadlo.html}}, tedy je možné jej zapojit přímo na Vcc pin mikrokontroleru (zvládnul by to i 3V3 pin, dle specifikace je maximální odběr proudu \SI{600}{\milli\ampere}\footnote{\url{https://www.dfrobot.com/product-2195.html}}). Motor je aktivován pomocí NPN tranzistoru \textbf{BC338-40} (stejný jako u~LED diod), zde jsem použil odpor o~hodnotě 2kΩ:

\[I_{BE} = \frac{I_C}{h_{FE}}\]
\[I_{BE} = 0.22 / 170 = 1,294 mA\]

\[R_B = \frac{U_B - U_{BE}}{I_B}\]
\[R_B = \frac{3,3 - 0,7}{0,001294} = 2009,27 \Omega\]

Pro jistotu jsem použil i paralelně zapojenou Schottkyho diodu jako flyback, pro zamezení nežádoucí špičky napětí při odpojení DC motoru čerpadla. Tento jev nastane v~momentě odpojení přívodu energie do elektromotoru, který pak začne fungovat jako generátor, neboť se stále ještě točí. Reverzně zapojená Schottkyho dioda tuto energii spotřebuje a tedy není uvolněna do systému\footnote{\url{https://www.circuitbread.com/ee-faq/how-does-a-flyback-diode-work}}.

Při tomto zapojení pumpa zvládnula přečerpat 100ml vody zhruba za 4 sekundy, tedy 25ml/s. Toto bude využito při nastavení objemu vody na jedno zalívání z~webu.

\begin{figure}[hbt]
\centering
\includegraphics[width=0.5\textwidth]{obrazky-figures/esp32_pump.pdf}
\caption{Schéma zapojení čerpadla}
\label{esp32_pump}
\end{figure}

Aby byla voda při zalívání rozprostřena po celém květináči, tak okolo horní hrany je přilepena hadička do tvaru kruhu ve které jsou dírky. Voda tak teče rovnoměrně ze všech stran shora na hlínu a ne do jednoho místa či pouze do květináče zespod.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{obrazky-figures/pump_assembly.jpg}
\caption{Sestavená část pro zalívání}
\label{pump_assembly}
\end{figure}


\section{Odběr energie}
\label{section_power_consumption}
Jak již bylo zmíněno v~podsekci \ref{subsection_led_lightning}, pro napájení celého květináče slouží 5V napájecí zdroj o~maximálním odběru proudu 3,1A.

Největší spotřebu mají LED diody. Ovšem ty jsou za DC--DC stepdown měniči napětí.
Při výpočtech vycházím z~části podsekce \ref{subsection_led_lightning}, konkrétně z~popisu spotřeby LED diod.

V~kalkulacích se používá vzorec na výkon \(P = U~* I\).

\[\text{První skupina} = 3,55 * 0,35 * 3 = 3,7275W\]

\[\text{Druhá skupina} = 2,35 * (0,7 + 3 * 0,4) = 4,465W\]

\[\text{Celkem} = 3,7275 + 4,465 = 8,1925W\]

Je ovšem nutné započítat ztrátu z~měničů LM2596. Dle specifikace je maximální účinnost 92\%. Ovšem v~tomto konkrétním použití lze očekávat účinnost jen okolo 70\%\footnote{\url{https://lygte-info.dk/review/Power\%20Adjustable\%20buck\%20converter\%20LM2596\%20UK.html}}.

\[ \text{Odběr LED modulu vč. ztrát} = 8,1925 / 0,7 = 11,7W  \]

Maximální odběry proudu pro ostatní použité komponenty jsou následující:
\begin{itemize}
    \item \texttt{AS7341} -- 5mA (bez používání přisvětlovacích LED -- případ této práce. Při jejich zapnutí až +42mA) \cite{sensors_as7341_datasheet};
    \item \texttt{SHT31} -- 1.5mA \cite{sensors_sht31_datasheet}
    \item \texttt{VL53L0X} -- 40mA \cite{sensors_vl53l0x_datasheet}
    \item \texttt{Senzor vlhkosti půdy} -- 5mA\footnote{\url{https://www.laskakit.cz/kapacitni-cidlo-pro-mereni-vlhkosti-pudy/}}
    \item \texttt{PCA9685} -- 10mA + odběr z~PWM pinů (7 * 2,13mA) = 14,91mA \cite{actuator_pca9685_datasheet}
    \item \texttt{Pumpa} -- 220mA\footnote{\url{https://navody.dratek.cz/navody-k-produktum/mini-dc-cerpadlo.html}}
\end{itemize}

Jelikož senzory a PCA9685 berou proud z~3V3 pinu devkitu, tak je zde limit 600mA daný použitým LDO\footnote{\url{https://www.dfrobot.com/product-2195.html}}. Tento limit je ale dostatečný, neboť je využito maximálně \(5 + 1.5 + 40 + 5 + 10 + 14,91 = 76,41mA\) z~jeho kapacity senzory/aktuátory.

\[\text{Maximální celkový odběr senzorů, PCA9685 a desky} = 5 * 0,6 = 3W\]

\[\text{Odběr pumpy} = 5 * 0,22 = 1,1W\]

Maximální výkon použitého zdroje je \(P = 5 * 3.1 = 15,5W\). Při součtu spotřeby senzorů, aktuátorů a samotného devkitu s~ESP32 ovšem vychází \(11,7 + 3 + 1,1 = 15.8W\). Avšak této hodnoty není dosaženo díky dočasnému vypnutí osvětlení pokud je zapnuté čerpadlo.

Reálně by se ovšem nemělo nic stát ani kdyby osvětlení bylo stále zapnuté, neboť odběr senzorického uzlu (bez osvětlení) je nižší než limit 600mA z~LDO a senzory již neměří při pumpování vody.


\section{3D model a tisk}
\label{section_3D_print}
Jelikož bylo nutné upevnit LED diody nad květináč a zároveň zaručit, že se celá konstrukce nezhroutí, tak jsem se vydal cestou 3D tisku. Model (Obrázek \ref{fig_3d_model}) obsahuje otvory pro diody a místa pro uchycení obou měničů napětí a PWM driveru. Stability je docíleno zatížením podstavy květináčem.

Jako materiál pro tisk byl zvolen PETG\footnote{PETG -- Polyethylene Terephthalate Glycol}. Neboť na rozdíl PLA\footnote{PLA -- Polylactic Acid} má vyšší tepelnou odolnost -- začne měknout až okolo 80°C vůči 60°C\footnote{\url{https://3dsolved.com/3d-filament-glass-transition-temperatures/}}. Tento parametr je zde důležitý z~důvodu, že 1W LED diody se i s~chladičem velmi zahřívají.

Bohužel jsem měl udělat otvory pro LED o~něco málo širší, neboť přesná šířka 20mm není ve skutečnosti dostatečná, zřejmě kvůli hranám chladičů SMD diod. Proto diody hezky nesedí a bylo nutno improvizovat s~dodatečným upevněním.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{obrazky-figures/model.jpg}
\caption{3D model konstrukce}
\label{fig_3d_model}
\end{figure}

\section{Knihovny v~ESP-IDF}
\label{section_impl_esp_idf_libs}
Menší komplikací při použití ESP-IDF byl problém v~podání neexistujících knihoven pro spektrální a ToF senzor. Pro ostatní jsem našel knihovny v~\texttt{ESP-IDF Components library} \cite{web_idf_components}. Proto jsem se rozhodl, že zkonvertuji knihovny určené pro Arduino IDE na ESP-IDF. Jedná se o~DFRobot AS7341\footnote{\url{https://github.com/DFRobot/DFRobot_AS7341}} a DFRobot VL53L0X\footnote{\url{https://github.com/DFRobot/DFRobot_VL53L0X}}.

Jelikož ostatní použité knihovny pro senzory využívají \textbf{i2cdev}\footnote{\url{https://esp-idf-lib.readthedocs.io/en/latest/groups/i2cdev.html}} knihovnu pro správu I\textsuperscript{2}C sběrnice, tak jsem ji využil taktéž, abych mohl používat všechny I\textsuperscript{2}C senzory zároveň a nemusel řešit kompatibilitu knihoven mezi nimi. Jedná se o~jednoduchou pomocnou knihovnu využívající semafory pro zablokování zápisu či čtení ze sběrnice jiným zařízením, než aktuálně používaným.
Primárně bylo nutné přepsat zápisy a čtení do/z registrů přes sběrnici (detail na obrázku \ref{fig_arduino_to_idf_lib}) a nahradit \texttt{delay()} metody z~Arduina metodou \texttt{vTaskDelay()} z~FreeRTOSu.

\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{obrazky-figures/arduino_to_idf_lib.jpg}
\caption{Část ESP-IDF konverze knihovny pro AS7341}
\label{fig_arduino_to_idf_lib}
\end{figure}

\section{ESP32}
\label{section_impl_esp32_sw}
Implementace softwaru na mikrokontroleru je samozřejmě rozdělena do více souborů, jejich funkcionalita je následující:

\begin{itemize}
    \item \texttt{main.cpp} -- Zde začíná celý program v~metodě \texttt{app\_main()} (definováno ESP-IDF), nastavuje se GPIO, přerušení pro konfiguraci a zapíná WiFi STA. Zároveň je zde jednoduchá implementace debounceru tlačítka pro přepínání WiFi režimů. Debounce je metoda určena pro ošetření zákmitů tlačítka při jeho zmáčknutí/pouštění, aby nebylo zaregistrováno několik aktivací místo jedné.
    \item \texttt{actuators .cpp/.hpp} -- Ovládání aktuátorů, tedy pumpy a LED osvětlení
    \item \texttt{mqtt .cpp/.hpp} -- Zprostředkovává komunikaci přes MQTT broker s~backendem webové aplikace. Tedy přijímá přednastavení a zasílá naměřené hodnoty ze senzorů.
    \item \texttt{sensors .cpp/.hpp} -- Provádí jednotlivá měření a ukládá je do datové struktury. Jakmile je vše hotovo, inicializuje aktuátory.
    \item \texttt{utility .cpp/.hpp} -- Obsahuje metody použitelné z~více částí kódu. Hlavičkový soubor definuje většinu konstant použitých v~programu.
    \item \texttt{webserver .cpp/.hpp} -- Stará se o~zobrazení a zisk dat z~webového formuláře určeného ke konfiguraci WiFi a ID zařízení.
    \item \texttt{wifiswitcher .cpp/.hpp} -- Slouží k~přepínání mezi režimy WiFi AP a WiFi STA.
\end{itemize}

Implementace používá globální \uv{Event Group} pojmenovanou \texttt{STATUS\_GROUP} (definováno v~\texttt{main.cpp}). Jedná se o~skupinu určenou k~synchronizaci jednotlivých úkolů, aby se následná akce spustila až po dokončení všech/konkrétních předešlých \cite{web_freertos_groups}. V~případě této práce slouží k~synchronizaci úkolů pro propřipojení na WiFi, MQTT, status senzorů a následně pro spouštění aktuátorů.

\subsection{Nastavení Wifi a ID}
Pro konfiguraci WiFi a ID zařízení je použit WebServer, který je na IP  adrese \texttt{192.168.1.1} po připojení se na WiFi AP vytvořený mikrokontrolerem.

Tento WiFi přístupový bod se zapíná automaticky pokud nejsou WiFi údaje a ID zařízení uloženy v~NVS paměti zařízení. Případně manuálně po stisku tlačítka. Jeho název je \uv{ESP32} s~heslem \uv{1234567890}. Jako indikace, že je zapnut tento režim slouží svítící zelená LED dioda na desce.

Nastal zde ovšem problém, že hlavičky požadavků byly větší než defaultní nastavení HTTP serveru a s~každým odesláním formuláře z~webového UI se mikrokontroler zhroutil. Jako oprava posloužilo zvýšit limit \texttt{CONFIG\_HTTPD\_MAX\_REQ\_HDR\_LEN} z~512 na 1024 v~sdkconfig souboru (pro použitou desku \texttt{sdkconfig.dfrobot\_firebeetle2\_esp32e}).

Vycházel jsem z~oficiální dokumentace HTTP Serveru pod ESP-IDF\footnote{\url{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_server.html}}.

Samotný WebServer obsahuje tři URI handlery:
\begin{itemize}
    \item \texttt{uriGet} -- Slouží pro odeslání webové stránky klientovi. Zasílá stránku po částech s~využitím \texttt{httpd\_resp\_send\_chunk} z~důvodu zobrazení názvu WiFi a ID zařízení (pokud jsou uloženy) bez jejich konkatenace ke konstantě obsahující celý HTML + CSS kód. Pro zjednodušení se zobrazují aktuální hodnoty pomocí JavaScriptu (díky využití getElementById se vybere prvek formuláře a nastaví se mu hodnota uložená v~zařízení), abych mohl data připojit na konec a nemusel je měnit ve středu dlouhého řetězce -- obsahu celé stránky, který je v~jedné statické proměnné.
    \item \texttt{uriPost} -- Prohledá zaslaná data z~konfiguračního formuláře pro údaje a uloží je do interní paměti zařízení.
    \item \texttt{uriRestart} -- Restartuje zařízení. Tím pádem se zařízení následně zapne v~normálním režimu a využívá nakonfigurované údaje.
\end{itemize}

\subsection{Senzory}
Každý senzor má definovanou bitovou masku (Event Bit), která se po dokončení nastaví do \texttt{STATUS\_GROUP}.

Postup každého měření probíhá následovně:
\begin{enumerate}
    \item Inicializace senzoru.
    \item Samotné měření.
    \item Zapsání do datové struktury a JSONu
    \item Nastavení bitové masky v~\texttt{STATUS\_GROUP}.
\end{enumerate}

Jak již bylo zmíněno v~sekci \ref{section_hardware}, čidla komunikují pomocí I\textsuperscript{2}C s~vyjímkou senzoru půdní vlhkosti. Ten je analogový a proto používá zabudovaný AD převodník v~ESP32. Jeho návratová hodnota je menší, čím vyšší je detekovaná vlhkost. Pro namapování hodnot se používá metoda \textbf{map()} z~utility.cpp/.hpp. 
Hodnota odpovídající 100\% vlhkosti byla změřena při saturaci hlíny vodou. Pro zisk hodnoty pro 0\% vlhkosti by byl ideální způsob kalibrace změřit hlínu vysušenou v~peci/troubě, ale při cenách energií v~době řešení této práce jsem se uchýlil k~méně přesnému řešení -- použít hodnotu naměřenou senzorem, když je vytažený z~hlíny. Neboť proces vysoušení trvá alespoň 1 den.

Kalibrace ToF senzoru \textbf{VL53L0X} pro snímání hladiny vody v~nádržce byla jednoduchá -- stačilo pouze zaznamenat naměřenou vzdálenost při plné nádržce a když byla úroveň vody menší než zvládlo čerpadlo ještě nasát. Tyto hodnoty jsou opět mapovány metodou \texttt{map()} na rozmezí 0 až 100\%, opět reverzním způsobem -- větší číslo (vzdálenost) odpovídá méně vody v~nádržce. Senzor se projevil jako přesný (porovnáváno vůči pravítku), ale velmi náchylný na rušení -- při použití jiného nepájivého pole stačilo mírně pohnout s~kontakty (i mimo aktivní měření) a hodnoty byly jiné, či se senzor ani neinicializoval.

Senzor teploty a vlhkosti vzduchu \textbf{SHT31} jsem porovnával s~pokojovým termostatem (ovšem pouze s~teploměrem). Naměřené hodnoty se zdály pokaždé mírně vyšší -- většinou o~necelý 1°C, ale to by mohlo být ovlivněno i umístěním senzoru. Co se týče otestování vlhkoměru, tak již sestavený květináč byl položen v~místnosti vedle koupelny (propojeno chodbou, ne přímo), která byla zavřená počas používání sprchy. Po otevření dvěří bylo vidět, že vlhkost stoupla zhruba o~7\% a teplota 
o~0,3°C za půl hodiny a následně klesala k~původním hodnotám. Rozdíl teploty se zdá být malý, ale na grafech \ref{fig_test_sht31} je změna hezky vidět.

\begin{figure}[hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/test_sht31.jpg}
\caption{Test SHT31}
\label{fig_test_sht31}
\end{figure}

Implementace spektrálního senzoru \textbf{AS7341} je zajímavější než ostatní v~tom, že navrácené hodnoty jsou v~rozmezí 0 až 1000. Což ovšem nestačí pro pokrytí všech intenzit. Dle dokumentace je výchozí hodnota parametru \texttt{AGAIN} nastavena na 9 \cite{web_dfrobot_as7341}, tedy zesílení 256x. Dle mého pozorování to je dostatečné pro běžné testování světla v~domě, ale na přímém slunci či poblíž silného zdroje světla, což použité LED diody jsou, nastane problém se saturováním senzoru a tedy ztrátě podstatné části informace. 
Z~tohoto důvodu je měření implementováno v~jednoduchém algoritmu, který mění zmíněný parametr \texttt{AGAIN} pro úpravu zesílení převodníků na senzoru v~případě, že jsou hodnoty příliš malé či se blíží 1000 tak, aby ke ztrátě nedocházelo.
Pro vyzkoušení jsem postupně zapínal LED diody na 100\% svítivosti v~tmavé místnosti a zaznamenával hodnoty naměřené senzorem drženým ve stejné vzdálenosti od aktivní diody. Na obrázku \ref{fig_led_wavelengths} je patrné, že pokud je vlnová délka diody mimo rozsah senzoru, tak je její hodnota nižší.
Kalibrace pro získání PPFD hodnoty by byla v~domácích podmínkách bez příslušného referenčního zařízení pro měření PPFD ze světla poněkud nereálná, tak jsem se rozhodl převzít výsledné hodnoty modelu z~práce zaměřující se využít tento senzor jako měřič PPFD \cite{sensors_light_plants_par}. Tento model je lineární -- stačí tedy pronásobit získané údaje ze sezoru koeficienty:

\begin{center}
\begin{tabular}{ |c|c|c|c|c| } 
\hline
b0 & b1 & b2 & b3 & b4 \\
-9,8853 & 0,0046 & 0,0136 & 0,0243 & 0,0459  \\
\hline
b5 & b6 & b7 & b8 &  \\
-0,0471 & 0,0195 & 0,0178 & -0,0026 &  \\
\hline
\end{tabular}
\end{center}

\[y_i = b_0 + \sum_{i=1}^n\ (b_i x_i) + \epsilon\]

Pro ověření výsledné hodnoty PPFD jsem vyzkoušel aplikaci \texttt{PPFD Meter}\footnote{\url{https://play.google.com/store/apps/details?id=com.homestudio.ppfdmeter}} využívající senzory pro okolní osvětlení v~telefonu. Naměřené hodnoty z~AS7341 byly zhruba dvojnásobné -- ve jmenované práci použili difuzor, ale senzor by se měl dát používat i bez něj. Proto jsem je následně dělil dvěmi.

\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/led_light_data.jpg}
\caption{Zaznamenané hodnoty z~jednotlivých LED}
\label{fig_led_wavelengths}
\end{figure}

\subsection{Aktuátory}
Jakmile senzory dokončí svá měření, tak se zapnou aktuátory. To je řešeno pomocí čekání na bity nastavené ze senzorů v~\texttt{STATUS\_GROUP} za využití metody \texttt{xEventGroupWaitBits}.

Prvně se aktivuje pumpa za pár podmínek:
\begin{itemize}
    \item Vlhkost půdy je menší než přednastavená s~připočítanou hysterezí
    \item V~nádržce na vodu je dostatek vody
    \item Doba od posledního zalití je více než 1 hodina
\end{itemize}
Pokud jsou všechny splněny, tak se pumpa zapne po dobu nutnou k~přečerpání přednastaveného množství vody.  Zároveň je po tuto dobu vypnuté LED osvětlení z~důvodu limitů zdroje, více v~kapitole o~spotřebě \ref{section_power_consumption}.
Dle měření jsem vypozoroval, že rychlost toku vody je zhruba 25ml/s, což je zmíněno v~podkapitole \ref{subsection_pump}. To odpovídá 40ms na 1ml vody.

Poté se nastavuje svit LED diod. Driver PCA9685 se inicializuje na maximální frekvenci PWM, tedy 1.5kHz. 

\subsection{Zakončení jednoho běhu}
Po změření hodnot ze senzorů se odešlou naměřené hodnoty přes MQTT na backend webové aplikace. Tento proces je více popsán v~sekci týkající se komunikace \ref{subsection_communication_mcu_backend}.
Následně se mikrokontroler uspí na 15 minut. Ovšem pokud by se použila pevná hodnota, tak by docházelo k~mírnému posunu s~každým během. Proto je od tohoto času odečtena doba běhu mikrokontroleru získána metodou \texttt{esp\_timer\_get\_time()}. Před samotným uspáním se ještě nakonfiguruje probuzení pomocí tlačítka určeného k~nastavení WiFi a ID zařízení a nastaví se výše zmíněný časovač.


\begin{figure}[hbt]
\centering
\includegraphics[width=0.7\textwidth]{obrazky-figures/assembled.jpg}
\caption{Sestavený květináč}
\label{assembled_all}
\end{figure}

\section{Webová aplikace}
\label{section_impl_web_app}
Jak již bylo popsáno v~návrhu řešení, webová část používá model klient--server.

Server se skládá z~frameworku Node.js a webového frameworku Express, který slouží pro cesty ke koncovým bodům API a obecně práci s~požadavky a odpovědmi. 

Jak klient, tak i server mají konfigurační soubor \texttt{.env}, kde se nachází nastavení tokenů, URL adres databází a komponent (klient, server). Tento soubor je specifický pro každý stroj a z~důvodu bezpečnosti je nutné mít pokaždé jiné tokeny.

Pro psaní webové části jsem použil IDE IntelliJ IDEA.

\subsection{Autentizace}
Jelikož se jedná o~veřejně dostupnou centrální webovou aplikaci, tak je nutné určit, o~jakého uživatele se jedná. Autentizace využívá JSON Web Tokeny (JWT). Jedná se o~standard určený pro podepsání datové struktury v~JSONu \cite{web_jwt}.
S~implementací jsem se inspiroval dle návodu publikovaného na TowardsDev\footnote{\url{https://towardsdev.com/jwt-authentication-with-node-js-and-react-dc41ef0e6136}}.

Proces probíhá tak, že klient zašle serveru pokus o~přihlášení, pokud údaje odpovídají, server vygeneruje token pomocí tajného klíče v~\texttt{.env} s~userID v~obsahu a zašle jej klientovi, který si jej uloží v~cookie a/nebo zasílá v~hlavičce. Tato cookie je podepsána dalším tajným klíčem definovaným v~\texttt{.env}.
Zároveň si klient uloží údaje o~uživateli do react kontextu pro použití na jiných místech, třeba v~podmínkách na zobrazení obsahu.

Poté musí klient zasílat v~hlavičce tento token serveru nebo mít povolené cookies a využít token uložený tímto způsobem, aby se ním mohl prokázat. Pokud je nutno použít hlavičky, tak abych jej nemusel manuálně přidávat do každého požadavku, tak je použita možnost definovat defaultní hlavičku v~axiosu jako autorizační Bearer token.

Server poté verifikuje v~\texttt{authMiddleware} přijatý token pomocí tajného klíče. Pokud je vše validní, tak se do requestu přidá objekt s~daty uživatele, které se pak používají na dalších místech. Třeba jako podmínka pro použití API na serveru.

Pro tento účel jsou na klientu komponenty \texttt{AuthMiddleware}, což je výše zmíněný react kontext starající se o~získání dat uživatele ze serveru. Proto obaluje v~\texttt{App.js} veškerý obsah. Jeho doplněk je komponenta \texttt{AuthRequired}, která zobrazí obsah jen pokud je uživatel přihlášen. Pokud ne, je přesměrován na přihlašovací obrazovku. Stránka, kterou chtěl uživatel vidět je zapamatována a po úspěšném přihlášení je na ni přesměrován.

Na serveru je kromě výše zmíněného authMiddlewaru důležitý \texttt{authController}, který se stará o~registraci a přihlašování včetně generování a zasílání tokenu. Zde jsou tedy všechny podmínky na hesla, jestli uživatel již neexistuje v~databázi a jiné.

\subsection{Frontend}
\label{subsection_impl_frontend}
Frontent je to, co uživatel vidí, proto je nutné zobrazit co nejvíce dat, ale zároveň přehledně, aby nebylo uživatelské prostředí chaotické. Navíc se musí počítat s~responzivním designem, aby byl web použitelný i na menším displeji. Neboť mobilní telefony nyní tvoří 60\% internetového provozu\footnote{\url{https://www.oberlo.com/statistics/mobile-internet-traffic}}.

Jelikož je React knihovna zaměřená na opětovné použití kódu, je vhodné vytvářet menší komponenty, které pak skládat do větších.

Webová aplikace je jednoduchá, má 4 hlavní obsahové pohledy:
\begin{itemize}
    \item Přehled přednastavení
    \item Přehled zařízení
    \item Detail přednastavení
    \item Detail zařízení
    \item Stránku s~profilem uživatele
\end{itemize}

V~přehledu přednastavení se zobrazují jen názvy a krátký popis. Výchozí chování je, že se zobrazí přednastavení od všech uživatelů -- to lze vypnout přepínačem.

V~přehledu zařízení vidí běžný uživatel jen svoje zařízení, ale admin uživatel si může přepnout pohled na všechna zařízení a filtrovat dle jména uživatele (tedy jako u~přehledu přednastavení). V~náhledu zařízení se zobrazují poslední naměřené hodnoty (Obrázek \ref{fig_web_devices}).

\begin{figure}[hbt]
\centering
\includegraphics[width=0.95\textwidth]{obrazky-figures/web_devices.jpg}
\caption{Přehled zařízení -- pohled administrátora}
\label{fig_web_devices}
\end{figure}

Detail veřejného přednastavení rozdělí stránku do 4 částí -- obecné informace, dlouhý popis, přednastavení a komentáře (Obrázek \ref{fig_web_public_preset}). V~obecných informacích je možnost editovat název a krátký popis, či smazat toto přednastavení. Je zde implementován limit počtu znaků -- 50 u~nadpisu a 200 u~popisu, při překročení je textové pole podbarveno červeně a nelze více psát. Detailní popis má limit 800 znaků. Samotné přednastavení lze měnit manuálně, či využít tlačítka pro zkopírování/vložení. Kopírování funguje globálně na celé webové aplikaci, pro tyto účely se používá cookie \texttt{copiedPreset}, do které se  uloží všechny proměnné přednastavení až na objem pumpované vody -- neboť ta se liší od velikosti květináče. Možnost editovat a ukládat může pouze vlastník přednastavení či admin uživatel.
Komentáře může psát kdokoliv. Komentář je zvýrazněn zeleně v~případě, že aktuální uživatel jej napsal, či pokud jej napsal admin, tak červeně. Možnost smazat již napsaný komentář může pouze admin uživatel.

\begin{figure}[hbt]
\centering
\includegraphics[width=0.95\textwidth]{obrazky-figures/web_public_preset.jpg}
\caption{Detail veřejného přednastavení -- pohled administrátora}
\label{fig_web_public_preset}
\end{figure}

Detail zařízení rozdělí pohled na 3 části -- přehled s~obecnými informacemi, konfigurovatelné přednastavení a grafy s~daty ze senzorů v~čase.
V~přehledu informací je nejdůležitější údaj ID zařízení ve formátu UUID, který se dá zkopírovat a následně se vkládá do formuláře při konfiguraci senzorického uzlu. Dále jsou zde poslední naměřené hodnoty a možnost změnit název zařízení či jej smazat.
Přednastavení květináče se chová stejně jako nastavení pod veřejným přednastavením.
Pro zobrazení grafů je použita knihovna \textbf{react-chartjs-2}\footnote{\url{https://react-chartjs-2.js.org/}} se zásuvným modulem pro přibližování. Ovšem nevýhoda této knihovny je, že u~dotykového displeje se mi nepovedlo implementovat omezovací obdélník pro přibližování/posun grafu jako při práci s~myší. Proto je nutné na telefonu scrollovat po krajích displeje.

Na stránce s~profilem uživatele je pouze přehled s~údaji a možná změna hesla či emailu.

Komponenty, které podporují zobrazení více objektů z~databáze (tedy přehled přednastavení či zařízení a komentáře) používají stránkování, aby se nezobrazilo všechno naráz.


\subsection{Backend}
Backend obstarává všechnu práci s~daty, jak se zápisy, tak se čtením z~databází. Používá komunikaci jak přes REST API s~klientem, tak pomocí MQTT se senzorickým uzlem. Toto téma již bylo řešeno v~návrhu, konkrétně v~kapitole \ref{section_communiction_between_components} věnující se komunikaci v~celém systému.

Struktura serveru je ve stylu Models/Routes/Controllers/Services pro přehlednost a rozdělení, co se kde v~kódu děje. Datové modely objektů jsou ovšem definovány již pomocí knihovny \texttt{Prisma} \cite{web_prisma}, která komunikuje s~MySQL databází. Jedná se o~ORM (\uv{Object Relation Mapping}), tedy objektově-relační mapování. Slouží pro propojení databázových tabulek s~objekty použitými v~kódu. Prisma tohle řeší trochu jinak, neboť se definují databázové tabulky i objekty společně v~jednom souboru -- \texttt{schema.prisma}\footnote{\url{https://www.prisma.io/docs/concepts/overview/prisma-in-your-stack/is-prisma-an-orm}}. Proto v~projektu není složka \uv{Models}.
Zbylé části tohoto typu návrhu jsou:
\begin{itemize}
    \item \texttt{Routes} -- mapují endpointy na controllery
    \item \texttt{Controllers} -- parsují parametry z~dotazů a volají metody v~services
    \item \texttt{Services} -- vytváří dotazy do databáze a vrací data. Většinou obsahují metodu \texttt{getByID()} sloužící k~získání jednoho konkrétního objektu, \texttt{update()} sloužící ke změně objektu, \texttt{deleteByID()} pro smazání, \texttt{getByFilter()} pro navrácení více objektů a \texttt{createForUser()} určené pro vyvoření pro daného uživatele.
\end{itemize}

Aplikace začíná v~souboru \texttt{index.js}, kde se nastavují jednotlivé cesty ke koncovým bodům definovaným v~\texttt{routes} složce. Zároveň je zde definován \texttt{CORS}, což znamená \texttt{Cross-Origin Resource Sharing}. To omezuje přístup na API pouze z~klienta. Je použita knihovna \texttt{cors}\footnote{\url{https://expressjs.com/en/resources/middleware/cors.html}}.

Důležitým prvkem je \texttt{authMiddleware}, tento soubor definuje middleware pro zisk JWT tokenu od uživatele. Tento token je pak ověřen, jestli je validní. Pokud ano, tak je přidán datový objekt uživatele do požadavku jdoucího od klienta. Proto pak mohou controllery zjistit, o~jakého uživatele se jedná (třeba výpis vlastních zařízení).

Některé \uv{service} nejsou napojeny na controllers a routes, neboť slouží pro jiný účel. Například \texttt{mqttService.js} je vlastně MQTT klientem, který obstarává všechny instance senzorických uzlů. Detailnější popis je v~návrhu věnujícímu se komunikaci \ref{subsection_communication_mcu_backend}. Tento klient využívá knihovnu \texttt{mqtt}\footnote{\url{https://www.npmjs.com/package/mqtt}}. Zde je tedy implementována i logika zisku dat ze senzorů ze zprávy a jejich následné zapsání do InfluxDB -- to je implementováno v~\texttt{recordsService.js}. Data jsou zapsána pouze v~případě, že v~relační databázi existuje zařízení s~ID odpovídajícímu UUID v~přijaté zprávě. Jiným příkladem může být \texttt{dbService.js}, která inicializuje připojení do databází a poskytuje metody pro práci s~nimi na dalších místech v~databázi.

Backend implementuje i jednoduché odesílání emailů uživateli (např. při registraci či změně hesla). Toho je docíleno použitím knihovny \texttt{Nodemailer} \cite{web_nodemailer}, která je nakonfigurována pro použití příkazu \texttt{sendmail}  -- chováním tedy podobně jako funkce \texttt{mail()} v~PHP\footnote{\url{https://nodemailer.com/transports/sendmail/}}.

Jak již bylo zmíněno v~implementaci frontendu \ref{subsection_impl_frontend}, tak některé jeho komponenty používají stránkování. Pro jejich funkčnost je tedy potřeba podpora na backendu. Této podpory je docíleno vracením ne jen seznamu dat, ale i informací o~jejich celkovém počtu dle zadaného filtru. Implementováno je to ve všech metodách \texttt{getByFilter()} v~souborech v~services.

\chapter{Nasazení}
Jelikož je systém navrhnut a implementován tím způsobem, že je nutná webová aplikace, která je ideálně dostupná veřejně na internetu, tak jsem ke zprovoznení využil VPS\footnote{Virtual Private Server}.

Pro spouštění lokálně na svém PC jsem použil program \textbf{XAMPP}, který distribuuje mimo jiné Apache včetně MySQL databáze\footnote{\url{https://www.apachefriends.org/}} -- tyto komponenenty jsem používal při vývoji.

\section{Testování}
Průběh testování lze rozdělit na více částí. Primárně z~počátku při psaní API na serverové části webové implementace jsem používal aplikaci \textbf{Postman}. Zde lze psát dotazy na API endpointy a analyzovat odpovědi. Jako příklad na obrázku \ref{fig_postman} je odpověď s~daty komentářů pro přednastavení a taky jak velká je odpověď a kolik času trvalo, než přišla. 

\begin{figure}[hbt]
\centering
\includegraphics[width=0.9\textwidth]{obrazky-figures/postman.jpg}
\caption{Příklad dotazu na komentáře v~Postman}
\label{fig_postman}
\end{figure}

Pro testování klientské části webové aplikace na kritických místech jsem používal javascript debugger a rozšíření do prohlížeče pro react\footnote{\url{https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi}}. Díky těmto nástrojům je možné vidět aktuální rozložení react komponent, jejich vlastnosti a proměnné.

Pro vyzkoušení a analýzu MQTT komunikace jsem použil aplikaci \textbf{MQTTX}. Jedná se o~klienta, který podporuje přihlášení do více témat a taky možnost publikovat zprávy s~různými QoS. Všechny zprávy jsou vidět dle času pod sebou.

Jelikož použitá deska nemá přímo v~sobě zabudovaný JTAG adaptér pro debugging a ani jsem nepoužíval externí, tak jsem využil debug výpisy do serial monitoru do PC. Pro analýzu pádů z~důvodu chyby v~kódu zase \texttt{exception decoder} v~PlatformIO, stačí jej povolit v~konfiguračním souboru projektu pro danou desku.

\section{Zprovoznění}
Pro zprovoznění ESP32 je nutné na něj nahrát program pomocí PlatformIO (šlo by i v~ESP-IDF, neboť jej využívám, ale PlatformIO se stará o~konfiguraci). Použité knihovny jsou již obsaženy ve zdrojových souborech ve složce \uv{lib}. Po nahrání na ESP32 a po zapnutí se spustí WiFi AP s~názvem \uv{ESP32} a heslem \uv{1234567890}, zde se musí nastavit ID zařízení a údaje domácí sítě WiFi k~připojení.

Pro zprovoznění webové aplikace je použita jedna instance VPS na které běží vše potřebné, tedy databáze (MySQL a InfluxDB), backend i frontend webové aplikace a pomocné programy. Primárně Apache pro proxyPass, aby se nemusel do URL psát i port frontendu a sendmail pro odesílání emailů.

Jelikož jsem pro účely demonstrace nezakoupil vlastní doménu, tak emaily používají \uv{@example.com}, což je doména určená pro testovací účely\footnote{\url{https://example.com/}} -- z~tohoto důvodu se může stát, že email nepřijde do hlavní složky s~poštou, ale do spamu.

Obě instance node.js jsou spravovány pomocí \textbf{pm2} -- což je manažer procesů k~tomuto určený\footnote{\url{https://pm2.keymetrics.io/}}. Jeho obsluha je velmi jednoduchá -- pro pro přidání frontendu posloužil příkaz \verb|pm2 start index.js --name "node-api"| (vykonán ve složce \uv{client}) a pro backend \verb|pm2 start --name "node-react" npm -- start| (vykonán ve složce \uv{server}). Následně stačilo povolit automatické spouštění pm2 po restartu VPS a to bylo vše.

\begin{figure}[hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/pm2_list.jpg}
\caption{Přehled node aplikací pod pm2}
\label{vps_pm2}
\end{figure}

\section{Pozorování}
\label{section_observation}
V~této kapitole je probráno pozorování zpětné vazby systému na změny okolního prostředí a následně samotný experiment s~rostlinou.


Na následujícím obrázku \ref{fig_web_charts} je možné vidět krátký časový úsek po západu slunce s~vypnutým svícením LED diodami. Lze vypozorovat postupné snižování teploty, ze světelných dat úbytek světla ve všech spektrech (krátké zvýšení kvůli otočení žaluzií) a následné rozsvícení velkého světla v~místnosti.
Zároveň je vidět špatná konfigurace ze strany uživatele, neboť bylo nastaveno příliš velké množství vody při jednom zalévání -- velký úbytek v~nádržce s~vodou a přílišné zalití květináče. Následné zvýšení vodní hladiny v~nádržce je způsobeno tím, že v~případě použité vázy jako nádržky je nutné, aby byla hadička dost dlouhá. Proto po nějaké době z~ní voda steče zpátky do nádoby a to se projeví jako zvýšení hladiny.

Pozorování věnovaná reakci čidla na teplotu a vlhkost byla již probrána v~implementaci, konkrétně na obrázku \ref{fig_test_sht31}. Za zmínku v~této kapitole stojí i testování spektrálního senzoru AS7341 na jednotlivé LED diody na obrázku \ref{fig_led_wavelengths}.

\begin{figure}[hbt]
\centering
\includegraphics[width=\textwidth]{obrazky-figures/web_charts.png}
\caption{Grafy v~detailu květináče}
\label{fig_web_charts}
\end{figure}

\subsection{Experiment s~rostlinou}
Pro vyzkoušení, jak funguje implementovaný květináč, jsem použil rukolu setou (Eruca Sativa). Experiment probíhal tak, že byl porovnáván růst bez osvětlení a s~osvětlením. 

Ve všech případech je osvětlení zapnuto maximálně 10 hodin denně. Neboť při více než 12-ti hodinách by se mohlo stát, že rostlina přejde do stádia pro tvorbu semínek a konce své životnosti \cite{web_arugula}.

Prvotní nastavení bylo (dle výkonu LED) 50\% modrá, 10\% červená, 45\% rudá a 65\% dalece červená. Bohužel AS7341 nezvládne zachytit vlnovou délku 730nm, tak nebylo možné porovnat její intenzitu.

\begin{figure}[bht]
\centering
\subfloat[Bez LED]{{\includegraphics[width=5.5cm]{obrazky-figures/day_3.jpg} }}
\subfloat[S LED]{{\includegraphics[width=6cm]{obrazky-figures/day_3_led.jpg} }}
\caption{3. den}
\label{fig_plant_day_3}
\end{figure}

Již 4. dnem byl spozorován náskok rostliny pod umělým osvětlením. Rostliny měly 5cm, mimo osvětlení zhruba 4cm.
Proto jsem upravil nastavení LED na 35\% modrá, 45\% červená, 50\% rudá a 15\% dalece červená.

\begin{figure}[hbt]
\centering
\subfloat[Bez LED]{{\includegraphics[width=5.5cm]{obrazky-figures/day_4.jpg} }}
\subfloat[S LED]{{\includegraphics[width=5.5cm]{obrazky-figures/day_4_led.jpg} }}
\caption{4. den}
\label{fig_plant_day_4}
\end{figure}

Následně bylo spozorováno zvětšení plochy listů 6. dnem růstu vůči rostlině bez LED osvětlení \ref{fig_plant_day_6}.

\begin{figure}[hbt]
\centering
\subfloat[Bez LED]{{\includegraphics[width=5.5cm]{obrazky-figures/day_6.jpg} }}
\subfloat[S LED]{{\includegraphics[width=5.5cm]{obrazky-figures/day_6_led.jpg} }}
\caption{6. den}
\label{fig_plant_day_6}
\end{figure}

Po 9--ti dnech měla rostlina pod LED větší listy a podobnou délku, jako rostlina, která rostla bez LED osvětlení po dobu jednoho měsíce \ref{fig_plant_final}. 

\begin{figure}[hbt]
\centering
\includegraphics[width=0.7\textwidth]{obrazky-figures/plant_final.jpg}
\caption{Levá: 30 dní bez LED | Pravá: 9 dní s~LED}
\label{fig_plant_final}
\end{figure}

\chapter{Možná rozšíření}
\label{chapter_future_extensions}
Co se týče rozšíření, tak jedno z~nejzásadnějších (když pominu přehlednější kabeláž u~LED diod) je rozdělení senzorického uzlu na moduly. Díky tomu by mohl mikrokontroler fungovat pouze na LiPo baterii a obsluhovat senzory s~vodní pumpou.
Osvětlení by byl další modul, který by již vyžadoval externí napájení, které nyní stejně používá. Takto by šlo pokrýt dočasné výpadky proudu a rozdělit produkt do dvou částí v~případě komerční výroby na~verzi se základní funkcionalitou nebo rozšířenou s~osvětlením.

Další možností je implementovat ESP-NOW / ESP-WiFi-Mesh. Díky tomu by mohly jednotlivé květináče komunikovat mezi sebou mimo dosah sítě WiFi. Toto by mělo využití například ve velkých sklenících. V~domech je většinou pokrytí sítí WiFi dostatečné, tak zde by byl benefit marginální nebo žádný. 

\chapter{Závěr}
Cílem této práce bylo implementovat květináč optimalizující růst rostliny. Což dle pozorování, si myslím, že se povedlo, neboť proces růstu rukoly byl znatelně rychlejší. Zároveň byla vytvořena webová aplikace, která umožňuje měnit parametry z~cloudu a obsahuje knihovnu přednastavení.
Detailní vyhodnocení výsledků je probráno již v~sekci \ref{section_observation}.

Jako přínos práce bych označil celkové řešení obsluhy chytrého květináče, kdy na webové aplikaci jsou definovány přednastavení pro různé rostliny -- i od jiných uživatelů, ne jen administrátorů -- a možnost modulovat osvětlení co se týče intenzity i vlnové délky podle potřeby rostliny.

Práci samozřejmě provázely i menší problémy -- blokující delay() v~Arduino IDE, kvůli kterému jsem se rozhodl na přechod pod ESP-IDF, kde byla ovšem absence knihoven pro dva použité senzory, nutnost zvětšení limitu hlavičky pro WebServer, jinak ESP32 padalo nebo rušení senzoru způsobené nepájivým polem.
Instalace a zprovoznění InfluxDB na VPS dělalo taky problémy, že bylo nutno několikrát opakovat tento proces.

Možná rozšíření byla již prodiskutována v~kapitole \ref{chapter_future_extensions}.

Tato práce mi taktéž dovolila se seznámit s~věcmi, ke kterým jsem se dříve moc nedostal -- ať už šlo o~komunikaci skrze MQTT, hlubší seznámení se s~programováním pro mikrokontrolery v~ESP-IDF, tvorba modelu pro 3D tiskárnu a obecně informace o~růstu rostlin.