\chapter{A madárhang azonosító és riasztó felhő-natív rendszer ismertetése} A rendszer tervezését olyan alapvető felelősségekkel kezdtük, mint adatok fogadása, ezek tárolása, valamint továbbítása. A fejlesztési folyamat során ezektől haladtunk az egyre specifikusabbak fele, mint a mesterséges intelligencia által használt modellek tárolása és dinamikus frissítése. Ennek a folyamatnak eredményeképp készítettük el a \aref{fig:cloud-arch-redesigned} ábrán látható architektúrát. A rendszer minden komponense egy-egy mikroszolgáltatás. Ezt a tervezési folyamat egy korai lépésében döntöttük el. E döntés mögött két indokunk volt. Az első a fejlesztés során a kooperáció könnyebbsége, hiszen a mikroszolgáltatások interfészeinek egyeztetése után azok egymástól függetlenül fejleszthetők, ezzel a kooperációt is elősegítve. Emellett ettől a döntéstől azt vártuk, hogy amennyiben a rendszer tervezése során követjük a korábban leírt ajánlásokat, a komponensek skálázhatósága jobb lesz, így a nagyobb terhelés esetén nem lesz érzékelhető növekedés a válaszidőben. Ebben a fejezetben szeretnénk bemutatni a hasonló, már létező ilyen megoldásokat és az általunk tervezett architektúrát a beérkező adatok útját bejárva. \section{Felhő-natív IoT rendszerek áttekintése} Számos a piacon is elérhető felhő alapú IoT szolgáltatás érhető el. Ezek közül egy az Azure IoT Hub \cite{iot-hub-azure}, ami biztonságos kommunikációt biztosít az eszközök és a felhőben futó komponensek között. Ezek lehetnek saját fejlesztésű szoftverkomponensek vagy más Azure szolgáltatások, például Azure Stream Analytics \cite{stream-hub-azure}, ami adatfolyamok gyors feldolgozására képes szolgáltatás, de számos más lehetőség van. Gyakorlatilag minden népszerű publikus felhőszolgáltatónál léteznek hasonló tudású szolgáltatások, ezek működése is tipikusan igen hasonlít egymásra. Ilyen előre elkészített szolgáltatások használatának előnye, hogy a fejlesztői és az ehhez tartozó mérnöki munkát már elvégezték és a szolgáltatás teljesítményével szemben bizonyos garanciát is gyakran vállalnak. Fontos figyelembe venni viszont azt is, hogy az ilyen szolgáltatások használata esetén gyakran igen nehéz szolgáltatók között mozogni, különböző szolgáltatóktól keverni szolgáltatásokat pedig ennél is nehezebb. Ezt a jelenséget, amikor a szolgáltató a saját termékcsaládjában próbálja tartani az előfizetőit vendor lock-innek hívjuk, ami az egyik legnagyobb visszatartó ereje a felhő alapú technológiák adopciójának az adatbiztonság és a kontroll elvesztése után \cite{Opara-Martins2016}. Ezt elkerülhetjük nyílt forráskódú, valamint saját fejlesztésű komponensek használatával, viszont ennek a megközelítésnek hátránya, hogy a rendszert üzemeltetni, támogatni a fejlesztőnek kell. Egy ilyen nyílt forráskódú platform a Kubernetes is. Kubernetes segítségével olyan IoT eszközöket támogató rendszerek \cite{8875447} készíthetők, amik tradicionális alkalmazásoknál jobban skálázódnak, költséghatékonyabbak. Mesterséges intelligencia alkalmazása egy ilyen rendszerben egy újszerű, érdekes probléma, aminek nem egyértelmű a megoldása. Dolgozatunkban erre teszünk kísérletet. \section{Felhő-natív rendszerelemek ismertetése} \begin{figure}[!ht] \centering \includegraphics[width=120mm, keepaspectratio]{figures/cloud-arch-redesigned.pdf} \caption{A felhő-natív rendszer architektúrája} \label{fig:cloud-arch-redesigned} \end{figure} A rendszerbe két típusú adat érkezhet. A kihelyezett eszközök által felvett hangadatok a felhő rendszerbe az Input Service-hez kerülnek be, ahol a beérkezett hangfájl és az azt kísérő üzenet formátumának validálása után az alapvető metaadatok – többek között a küldő eszköz azonosítója, beérkezés dátuma, valamint az egész felhő rendszerben használt egyedi azonosító – eltárolódnak. Ezt követően az állomány továbbításra kerül a Storage Service-nek, ahol egy objektumtárban kerül eltárolásra. Ez azért előnyös, mert ha egy mintát szeretnénk többször is feldolgozni, a feldolgozott mintákat meghallgatni validálás céljából, vagy az AI Service-ben használt modellt a rendszer felhasználója pontosítani szeretné a rendelkezésre álló valós mintákkal, akkor lehetőség van azt lekérni egyéb metaadatai mellett az egyedi azonosító segítségével. Erre viszont csak limitált ideig van lehetőség, ugyanis az eltárolt hangfájlok beállítható idő múlva – alapértelmezés szerint egy hét – törlésre kerülnek, hogy a beérkezett minták által elfoglalt lemezterületet kordában tartsuk. A fájl sikeres tárolását követően az Input Service egy üzenetsorra beküldi a minta azonosítóját, ezzel jelezve a feldolgozó komponensnek az új minta beérkezését és azt, hogy milyen azonosítót használhat a Storage Service-től lekérdezéskor. Az üzenetsoron az AI Service példányai fogadják az üzenetet, ezen komponens felelőssége a minták klasszifikálása többek között seregély, traktor és egyéb zaj kategóriákba. Még mielőtt megkezdhetné a feldolgozást, a Model Service-nél ellenőrzi, hogy elérhető-e újabb modell, amivel dolgozni tud. A Model Service képes több különböző típusú – beleértve a felhő rendszerben és az IoT eszközön található mesterséges intelligenciák által használtakat – modellt tárolni, a modellek verzióját követni, valamint visszaadni REST API-n keresztül. Az éppen használt modell friss állapotának eldöntésére lekéri az alapértelmezett modell metaadatait, amiket összevet a lokálisan meglévő modell metaadataival. Amennyiben valóban elérhető újabb modell, letölti azt és onnan betölti további használatra. E mechanizmus által lehetőség van a rendszer által használt modellek dinamikus frissítésére és cseréjére, valamint a Model Service-ben az alapértelmezett modell korábbira visszaállításával akár korábbira visszatérés is könnyedén lehetséges. A modell ellenőrzése után az AI Service-ben található mesterséges intelligencia elvégzi a hangfájl klasszifikációját. Ennek eredményét a minta azonosítójával egyetemben egy másik üzenetsoron publikálja. Az üzenetsorra érkező adatokat három mikroszolgáltatás fogadja, de az üzenetsornak hála újabb ilyen komponens illesztése a meglévő a rendszerhez könnyedén lehetséges. A Results Service feladata eltárolni minden egyes minta adatait úgy, hogy azok egyesével lekérdezhetők legyenek. Ennek a mikroszolgáltatásnak a segítségével lehetséges harmadik fél által gyártott szoftverekhez csatolni az általunk fejlesztett rendszert. A Metrics Service felelőssége idősoros adatbázisba illeszteni az eredményeket. Az idősor adatbázisból statisztikai lekérdezések segítségével betekintést nyerhetünk a szőlőben a seregélyek mozgásába, tendenciáiba akár egy harmadik fél által fejlesztett dashboarddal. Az utolsó mikroszolgáltatás, ami megkapja a klasszifikációk eredményeit a Guard Service. Ez a mikroszolgáltatás üzenetsoron küld egy riasztási parancsot annak az eszköznek, ahonnan seregélyként detektált minta érkezett. Az egyes komponensek közötti kommunikáció alapvetően HTTP feletti REST API-k segítségével történik, kivéve az előzőekben említett helyeken, ahol üzenetsorral. Előbbit olyan esetekben alkalmaztuk, amikor az adott interfész külső alkalmazások felé elérhető, nagy mennyiségű adat átvitele történik, vagy fontos a szinkron kommunikáció. Jó példa a Storage Service interfésze, ugyanis itt fontos tudni, hogy mikor áll készen a mikroszolgáltatás a minta kiszolgálására, valamint egy tipikus JSON formátumú üzenethez képest nagy mennyiségű, bináris adat átvitelét jelenti. Természetesen üzenetsorra is megvalósítható lenne ez a viselkedés, viszont jelentősen bonyolultabb üzleti logikát igényelt volna a megvalósítás, jelentősebb előnyt viszont nem hozna. Az egyes mikroszolgáltatások közötti üzenetsorok AMQP (Advanced Message Queuing Protocol) felett zajlanak. Emellett akkor döntöttünk, amikor több komponensnek is szüksége van egy művelet eredményére – mint például az AI Service kimenetére reagáló három mikroszolgáltatás –, vagy nem szükséges az adott üzenetre válasznak érkeznie. Ilyen az Input Service által az AI Service-nek küldött értesítés is. Az interfészek és üzenetek tervezése során kiemelten figyeltünk arra, hogy minden üzenetsoron és REST API-n átvitt adat lehetőleg minél kisebb legyen, csak a szükséges adatok kerüljenek továbbításra. Ezzel is növelve a kommunikáció hatékonyságát és kihasználva a HTTP és üzenetsor előnyeit minimális többletköltség mellett. A minták fogadásában nem vesz részt a Command and Control Service, felelőssége az egyes eszközök és azok szenzorainak állapot vezérlése, nyomon követése. A kihelyezett IoT eszközök az állapotukat üzenetsoron jelzik. Egy ilyen üzenet például lehet jelzés, hogy az eszköz valamilyen hibás állapotba került és javítást vagy cserét igényel, esetleg egy szenzorról nem képes adatot olvasni, kikapcsolni készül vagy épp most kapcsolt be. Egy másik üzenetsoron hallgatják a parancsokat és végrehajtják azokat. Ilyen parancs lehet a mesterséges intelligencia által használt modell frissítése és a szenzor vagy eszköz kikapcsolása. Az irányító üzenetek küldését REST API segítségével lehet kiváltani. A Command and Control Service indulásakor nem ismeri a rendszerben futó eszközöket, azokat az első üzenetük fogadásakor jegyzi fel egy saját relációs adatbázisba, ahol követi az állapotukat. Azokat az eszközöket, amik öt perce nem küldtek státusz üzenetet, a mikroszolgáltatás hibás állapotba lépteti a belső állapotreprezentációjában. Az egy hétnél tovább el nem érhető eszközöket automatikusan kikerülnek az adatbázisból kivéve, ha a felhasználó API hívás segítségével permanensnek nem jelölte azt. Az eszközök és a felhőben lévő komponensek közti üzenetsoros kommunikáció MQTT (Message Queue Telemetry Transport) protokollon történik, ami mellett annak flexibilis téma (topic) architektúrája miatt döntöttünk. Lehetőség van az egyes üzenetsorok, vagy másnéven témák, struktúrálására és ezáltal egyszere több témára üzenet küldésére, valamint feliratkozásra. Ezt a Command and Control Service esetében ki is használtuk, ugyanis az egyszere iratkozik fel minden eszköz státuszüzeneteire, valamint a struktúrált témáknak köszönhetően minden vezérlőüzenetet csak a céleszköz kap meg, ami csökkenti a szükséges hálózati forgalmat és az eszközök által feldolgozandó üzenetek számát. \section{Internet of Things eszköz ismertetése} Az IoT eszköz architektúrájának tervezése során a legfontosabb szempont az új szenzorok bevezetése volt. Emiatt úgy döntöttünk, hogy az egyes szenzorokat teljesen külön kezeljük. Három alapvető lépést határoztunk meg egy mért adat útja során. Az első a szenzor általi mérés elvégzése, amit az opcionális előfeldolgozás követ. Végezetül, a szoftvernek döntést kell hoznia, hogy az eredményt tovább küldje-e felhőbe, majd a döntést végre is kell hajtsa. Azért, hogy ez a folyamat minél flexibilisebb legyen, egy külön osztály fogja össze és indítja az egyes lépéseket, valamint a mintavételezéseket egy központi, belső óra vezérli. Itt konkrét, hardveres implementációval nem foglalkoztunk, azt a szoftver tervezése és fejlesztése során elabsztracháltnak tekintettük. \begin{figure}[!ht] \centering \includegraphics[width=120mm, keepaspectratio]{figures/cloud-arch-class.pdf} \caption{Az IoT eszközön futó szoftver osztálydiagrammja} \label{fig:cloud-arch-class} \end{figure} A felvázolt koncepciót a fenti osztálydiagramon valósítottuk meg. Új szenzor felvétele esetén az ISensor, IPreProcessor, ISender interfészek implementálásával és SignalProcessor osztályból leszármazással, valamint ezek az Application osztályba regisztrálásával lehetséges. Új riasztásra képes forgatókönyv esetében az IActuator interfész implementálásával van lehetőségünk a riasztás elvégzésére. Az Application osztály tartalmazza az eszközök eseményhurkát, ami lehetővé teszi a szenzorok ismételt mintavételét, előfeldolgozását és a minta felhőbe küldését. Az általunk megvalósított viselkedés során egy ütemben a SoundProcessor vezényli a hangminták kezelését. Az ütem elején egy másodperc hosszú hangmintát vesz az előre bekonfigurált mikrofonról, amit egy mesterséges intelligencia bekategorizál többek között traktor, emberhang, méhek és madárcsicsergés kategóriákba. A madárcsiripelés kategóriába sorolt mintákat továbbítja a felhőbe a SoundSender, ahol az előbbiekben leírt folyamat kerül végrehajtásra. Ez a forgatókönyv \aref{fig:cloud-arch-sequence} ábrán látható. Minden harmadik ütem végén küld az eszköz státusz frissítést a felhőnek. \begin{figure}[!ht] \centering \includegraphics[width=150mm, keepaspectratio]{figures/cloud-arch-sequence.pdf} \caption{Az IoT eszköz egy futásának szekvenciája} \label{fig:cloud-arch-sequence} \end{figure} Az eszköz indulásakor az Application osztály a beállított üzenetsoron elküldi, hogy éppen bekapcsolt, hamarosan elkezd adatokat küldeni és képes parancsok végrehajtására. Utóbbi külön szálon történik, emiatt szükség volt a szenzorok offline és online állapotainak szálbiztos kezelésére a SignalProcessor leszármazottjaiban és az ezeket nyilvántartó listának is hasonlóan szálbiztosnak kell lennie. Az offline szenzorok forgatókönyve kikerül az ütemezett forgatókönyvek közül, viszont futó forgatókönyvet az alkalmazás nem szakít meg.