diff --git a/src/contents/5-elozmenyek.tex b/src/contents/5-elozmenyek.tex index 87a699072bc97474762e29aa37b5fd9f762ef59f..a2007807f5bcef5fa9d96a94b25939d9b70715e5 100644 --- a/src/contents/5-elozmenyek.tex +++ b/src/contents/5-elozmenyek.tex @@ -613,13 +613,16 @@ kényelmet a biztonság elé helyezni. hiszen minden valaha létrejött szoftver életciklusában van emberi tényező. Az emberi tényező hozzájárul a szoftver helytelen működéséhez, az abban keletkező hibákhoz. A hibák akár sebezhetőséget is tudnak magukkal hordozni, melyek -kihasználásával harmadik fél számára adhatnak hozzáférést a rendszerhez. -A sebezhetőségek túlnyomórészt helytelen memóriakezelésből származnak -- -túlcsordulás, use-after-free, nem inicializált memória. \cite{software-vuln} -Ezek elkerülése végett be kell vezetni a helyesség ellenőrzésére alkalmas -eszközöket, vagy ha lehet, az ezt megelőző módszereket alkalmazni. Ez lehet -a szoftver tervezés-fejlesztés-validálás életciklusban változtatás, vagy a -fejlesztői környezetben. - +kihasználásával harmadik fél számára adhatnak hozzáférést a rendszerhez. A +Microsoft nemrég egy felmérést végzett a saját termékein, melyben a szofvteres +sebezhetőségekeket kiváltó okokat kereste. Az eremények magukért beszélnek: +a sebezhetőségekre kiadott biztonsági javítások $70 \%$-a memóriakezelési +hibákból származott a megállapításuk szerint. \cite{ms-rust} \cite{ms-vuln-70} +A sebezhetőségek sok forrásból keletkezhetnek, de túlnyomórészt helytelen +memóriakezelésből származnak -- túlcsordulás, use-after-free, nem inicializált +memória. \cite{software-vuln} Ezek elkerülése végett be kell vezetni a helyesség +ellenőrzésére alkalmas eszközöket, vagy ha lehet, az ezt megelőző módszereket +alkalmazni. Ez lehet a szoftver tervezés-fejlesztés-validálás életciklusban +változtatás, vagy a fejlesztői környezetben. \clearpage % Ez azért kell, hogy nehogy képek átcsússzanak a következő fejezethez diff --git a/src/contents/6-tervezes.tex b/src/contents/6-tervezes.tex index 4b37210c0af6deb2e4c8e9bb8cea53fa049a8af9..2bf16ce853da644ab5011e651825b89e0fa2c66c 100644 --- a/src/contents/6-tervezes.tex +++ b/src/contents/6-tervezes.tex @@ -100,7 +100,7 @@ szereztem tudást az adott technológiákról, megoldásokról. A következő fe részletesen adok ismertetést azokról. \begin{figure}[htbp!] - \includesvg[width=\columnwidth]{images/rendszer.drawio.svg} + \includesvg[width=\textwidth]{images/rendszer.drawio.svg} \caption{A teljes rendszer magas szintű vázlata} \label{diag:rendszer} \end{figure} @@ -109,9 +109,81 @@ részletesen adok ismertetést azokról. \subsection{ESP32 platform} +\paragraph{} Az Espressif más megközelítéssel tervezi a hardvereit, mint hasonló +platfomok. Egy alacsony fogyasztású beépített rendszer általában minimális számú +perifériával van ellátva, elterjedten a mikrokontroller tokozásában nincsenek +kiegészítő perifériák, csak a processzor, órajel vezérlés, debug interfész, +és egyéb alapvető komponensek. Ez jellemző például az STMicroelectronics +ARM mikroprocesszor alapú chipjeire. Ez ideális egy olyan rendszernél, +ahol a hardver tervezését is szeretnénk maximálisan magunk elvégezni minden +részletében. Ezzel a módszerrel a végeredmény nagyon optimalizált összetételt +fog eredményezni egy nagyon specifikus célra. Hátránya, hogy a későbbi +változtatás felmerülő igényével számolni nehezebb, és azt legtöbb esetben +nehezebb kivitelezni, ezért rugalmatlanabb, mint itt az ESP32 esetében. Az +analógia a következő: legyen egy komplett, jól megválasztott perifériákkal +ellátott alaprendszer a chipen (``Systen on a Chip'' -- SoC) a kezünknél. Ez a +hardver tervezésének fázisát segíti elő, illetve a később felmerülő bővítéssel +számolni legtöbb esetben triviális az integrált perifériák jelenlétében. Ez az +analógia jól illeszkedik IoT célú eszközök körében, hiszen beépített WiFi és +Bluetooth rádióval van ellátva, mellé a szoftveres támogatás is integrált, a +gyors tervezés és implementálást elősegítve. \cite{esp32-family} Ahogy láttuk +\aref{kereskedelmi}. fejezetben, egy hagyományos riasztórendszerhez az előbbi +megközelítés áll jobban, és a DIY rendszerekhez az ESP32 megközelítését tartom +ideálisabbnak. Ezért esett rá a választás, hiszen a dolgozat keretében egy +alapot tervezek készíteni egy bővíthető rendszer számára. + +Az ESP32 családjában több mikroprocesszor-architektúra is megtalálható, +nevezetesen: Xtensa, ARM és RISC-V. A legtöbb modell esetében Xtensa magok +találhatóak, mely kizárólag az ESP-k körében használatos manapság. 32 bites +ALU-val és 16 darab 32 bites általános célú regiszterrel rendelkezik, 16 +bites utasításkészlet mellett (ISA). Az alap ISA 82 RISC utasítást tartalmaz. +\cite{xtensa} Az általam választott ESP32 alapú fejlesztőpanel (ESP32-D1-MINI) +az ESP32-WROOM-32 chipet használja. A chip tartalmaz 4MB beépített SPI +flash memóriát, 520KB SRAM-ot. Megítélésem szerint ez elegendő erőforrás a +fehasználásunkra, hiszen nem fogjuk használni a beépített WiFi rádiót, ami +működtetése szignifikáns ROM és RAM-ot felhasználna. \cite{esp-wroom} A chip +tartalmaz egy beépített MAC interfészt (Media Access Controller), amely 17 +vezetéken (MII -- Media Independent Interface) vagy 9 (RMII -- Reduced Media +Independent Interface) vezetéken képes egy fizikai médium vezérlővel (PHY) +kommunikálni. \cite{esp} Ez esetünkben praktikus, mert csupán egy Ethernet +aljzat és PHY vezérlő elegendő Ethernet LAN hálózatokkal való integráláshoz. +Továbbá a chipen a MAC egyedi DMA (Direct Memory Access) vezérlővel működik +beépített adó és vevő oldali 512 szavas FIFO-val. Ezt alkalmazva az adatátvitel +akár $100\ Mbit/s$ sebességen tud működni. \cite{esp} Számunkra nem a sebesség +a fontos, hanem a stabilitás, megbízhatóság, melynek ezek a beépített perifériák +eleget tesznek. Az adatátvitel szoftveres kezelését a gyártó által fejlesztett +framework-ben implementált driver fogja végezni, mely kevésbé rizikósabb, mint +harmadik fél által fejlesztett megoldások. + +Az Espressif fenn tart ehhez az architektúrához készült fordítóprogramokat, +melyek az ESP-IDF (Espressif IoT Development Framework) szofverfejlesztői +csomagban használatosak. \cite{idf-tools} A framework alapvetően C/C++ nyelvekre +célzott. A Rust támogatás esete speciális, mely két különböző módon adott. +Az egyik mód keretében az ESP-IDF függvénykönyvtárának felhelhasználásával +implementált Rust standard library (std) segítségével tudunk fejleszteni +alkalmazást. Vagy a sokkal kisebb binárist eredményező és memóriahasználatú, +alacsonyabb szintű út: std és ESP-IDF nélkül (``\verb|no_std|''), úgynevezett +``baremetal Rust'' környezetben tudunk fejleszteni. \cite{esp-rust-approaches} +A dokumentáció jól szemlélteti a két megközelítés közötti különbségeket, +illetve mikor érdemes melyiket választani. A projektünkhöz az std használatát +választom az ESP-IDF kifejledt ökoszisztémája miatt, mellyel korábban pozitív +tapasztalataim voltak. Az eszköz szoftverében a működése óta nem találtam hibát, +ami hasonlóan egy ESP32-WROVER-32 alapú rendszer volt titkosított adatközléssel +WiFi hálozat felett. \cite{onlab} Az ESP-IDF több biztonságot garantál a program +stabilitása érdekében, mint a bare metal megoldás, hiszen ott futásidőben +nincsen operációs rendszer, ezért minden a fejlesztőre van bízva -- nincsen +heap, ezért a memóriakezelés visszaesik ránk. \cite{rust-nostd} \Aref{inf-bizt}. +fejezetben indokoltak miatt a projekt keretében a bare metal használata nem +ideális. Több minden van a fejlesztőre bízva, több befolyást ad a kezünkbe, +de ezzel egyben biztonság kárára optimalizálnánk a program memóriahasználatát +és bináris méretét. A bare metal megközelítést inkább elszigetelt, beágyazott +célhardverekhez tartom jobban igazodónak, nem magas szintű IoT-barát +megoldásoknak. + \subsection{Rust nyelv és környezet} -% Rövid ismertető a nyelvről, miért jó választás esetünkben. A nyelv körüli ekoszisztéma és a hardver integrációjáról ismertetés. +\paragraph{} A Rust nyelv ötlete egy Mozilla-nál dolgozó fejlesztő fejéből +pattant ki, amikor egy liftbe beszállt és az elromlott, hibás szoftver miatt. \subsection{MQTT protokoll} diff --git a/src/hivatkozasok.bib b/src/hivatkozasok.bib index 9a94428fe8235d14dfe9309f36aee3be74a2c2e3..7effb22970487a12af6cc38b88e32a510db6102f 100644 --- a/src/hivatkozasok.bib +++ b/src/hivatkozasok.bib @@ -1,5 +1,5 @@ @thesis{bizt-rendszerek, - author = {Török Krisztián Antal}, + author = {Török, Krisztián Antal}, title = {Biztonságtechnikai rendszerek üzemeltetése-karbantartása}, type = {szakdolgozat}, year = {2024}, @@ -435,3 +435,101 @@ urldate = {2025-04-22}, url = {https://www.home-assistant.io/integrations/mqtt/#setting-up-a-broker}, urldate = {2025-04-23}, } + +@manual{esp32-family, + title = {ESP32 Series - Datasheet}, + author = {{Espressif}}, + url = { + https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf + }, + urldate = {2025-04-24}, +} + +@online{idf-tools, + title = {List of ESP-IDF Tools - Downloadable IDF tools - ESP32}, + url = { + https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/tools/idf-tools.html#list-of-esp-idf-tools + }, + urldate = {2025-04-24}, +} + +@manual{xtensa, + title = {Xtensa Instruction Set Architecture (ISA)}, + type = {Reference Manual}, + author = {{Tensilica, Inc.}}, + url = {https://0x04.net/~mwk/doc/xtensa.pdf}, + urldate = {2025-04-24}, +} + +@manual{esp, + title = {ESP32 Series - Datasheet version 4.9}, + url = { + https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf + }, + urldate = {2025-04-24}, +} + +@manual{esp-wroom, + title = {ESP32-WROOM-32 - Datasheet}, + url = {https://www.hestore.hu/prod_getfile.php?id=13796}, + urldate = {2025-04-24}, +} + +@online{esp-rust-approaches, + title = {Overview of Development Approaches - The Rust on ESP Book}, + url = { + https://docs.esp-rs.org/book/overview/index.html#overview-of-development-approaches + }, + urldate = {2025-04-24}, +} + +@online{rust-nostd, + title = {A no{\_}std Rust Environment}, + url = { + https://docs.rust-embedded.org/book/intro/no-std.html#a-no_std-rust-environment + }, + urldate = {2025-04-24}, +} + +@book{rust-book, + title = {The Rust Programming Language (Covers Rust 2018)}, + author = {Klabnik, S. and Nichols, C.}, + isbn = {9781718500457}, + url = {https://doc.rust-lang.org/book}, + urldate = {2025-04-24}, + year = {2019}, + publisher = {No Starch Press}, +} + +@report{onlab, + author = {Nádudvari, Ákos}, + title = {ITK alkalmazás (ITKapp) fejlesztése modern, Web alapú + technológiákkal}, + type = "Önálló Laboratórium", + institution = {PPKE ITK}, + year = 2024, + month = {5}, + url = {https://users.itk.ppke.hu/~nadak/files/itkapp_onlab.pdf}, +} + +@online{ms-rust, + title = {Microsoft is Getting Rusty: A Review of Successes and Challenges}, + type = "presentation", + author = {Mark Russinovich}, + organization = {Rust Nation UK}, + date = {2025-02-26}, + url = {https://youtu.be/1VgptLwP588}, + urldate = {2025-04-24}, +} + +@online{ms-vuln-70, + title = {A proactive approach to more secure code}, + author = {Gavin Thomas}, + organization = {{Microsoft - MSRC}}, + type = "blog", + date = {2019-07-16}, + url = { + https://msrc.microsoft.com/blog/2019/07/a-proactive-approach-to-more-secure-code/ + }, + urldate = {2025-04-24}, +} diff --git a/src/images/rendszer.drawio.svg b/src/images/rendszer.drawio.svg index f7e97ab0d5d3ad3ef318105cfb281005349ce260..cc4cbb02f26ea5362c7746f21d533dcd3ece8d01 100644 --- a/src/images/rendszer.drawio.svg +++ b/src/images/rendszer.drawio.svg @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- Do not edit this file with editors other than draw.io --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent; color-scheme: light dark;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="432px" height="267px" viewBox="-0.5 -0.5 432 267" content="<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" version="26.2.12"> <diagram name="Page-1" id="lOt5DuucHZqO-FceC0Nk"> <mxGraphModel dx="598" dy="967" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> <root> <mxCell id="0" /> <mxCell id="1" parent="0" /> <mxCell id="fKnSCGM_49d5ayVgUhBN-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=none;startFill=0;dashed=1;startArrow=none;shadow=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fontFamily=monospace;" edge="1" parent="1" source="fKnSCGM_49d5ayVgUhBN-2" target="fKnSCGM_49d5ayVgUhBN-12"> <mxGeometry relative="1" as="geometry"> <mxPoint x="170" y="560" as="targetPoint" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-7" value="Ethernet, MQTT" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=monospace;" vertex="1" connectable="0" parent="fKnSCGM_49d5ayVgUhBN-6"> <mxGeometry x="-0.2238" y="-2" relative="1" as="geometry"> <mxPoint x="-16" y="-8" as="offset" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" edge="1" parent="1" source="fKnSCGM_49d5ayVgUhBN-2" target="fKnSCGM_49d5ayVgUhBN-8"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-2" value="Központi egység" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=monospace;" vertex="1" parent="1"> <mxGeometry x="280" y="515" width="180" height="90" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-8" value="PIR mozgásérzékelők" style="ellipse;whiteSpace=wrap;html=1;rounded=1;fontFamily=monospace;" vertex="1" parent="1"> <mxGeometry x="291.09" y="340" width="157.81" height="70" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-12" value="Home Assistant" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=monospace;" vertex="1" parent="1"> <mxGeometry x="30" y="530" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" edge="1" parent="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="390" y="515" as="sourcePoint" /> <mxPoint x="390" y="409" as="targetPoint" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" edge="1" parent="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="355" y="515" as="sourcePoint" /> <mxPoint x="355" y="410" as="targetPoint" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-20" value="..." style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1"> <mxGeometry x="365" y="448" width="30" height="30" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-21" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" edge="1" parent="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="340" y="515" as="sourcePoint" /> <mxPoint x="340" y="408" as="targetPoint" /> </mxGeometry> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> "><defs/><g><g data-cell-id="0"><g data-cell-id="1"><g data-cell-id="fKnSCGM_49d5ayVgUhBN-6"><g><path d="M 250 220 L 120 220" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-7"><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 210px; margin-left: 184px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "><div style="display: inline-block; font-size: 11px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; ">Ethernet, MQTT</div></div></div></foreignObject><text x="184" y="214" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="11px" text-anchor="middle">Ethernet, MQTT</text></switch></g></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-9"><g><path d="M 340 175 L 339.99 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-2"><g><rect x="250" y="175" width="180" height="90" rx="13.5" ry="13.5" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 220px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Központi egység</div></div></div></foreignObject><text x="340" y="224" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="12px" text-anchor="middle">Központi egység</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-8"><g><ellipse cx="339.99" cy="35" rx="78.905" ry="35" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 156px; height: 1px; padding-top: 35px; margin-left: 262px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">PIR mozgásérzékelők</div></div></div></foreignObject><text x="340" y="39" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="12px" text-anchor="middle">PIR mozgásérzékelők</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-12"><g><rect x="0" y="190" width="120" height="60" rx="9" ry="9" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Home Assistant</div></div></div></foreignObject><text x="60" y="224" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="12px" text-anchor="middle">Home Assistant</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-18"><g><path d="M 360 175 L 360 69" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-19"><g><path d="M 325 175 L 325 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-20"><g><rect x="335" y="108" width="30" height="30" fill="none" stroke="none" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 123px; margin-left: 350px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">...</div></div></div></foreignObject><text x="350" y="127" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">...</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-21"><g><path d="M 310 175 L 310 68" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent; color-scheme: light dark;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="431px" height="266px" viewBox="-0.5 -0.5 431 266" content="<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" version="26.2.13"> <diagram name="Page-1" id="lOt5DuucHZqO-FceC0Nk"> <mxGraphModel dx="718" dy="1160" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> <root> <mxCell id="0" /> <mxCell id="1" parent="0" /> <mxCell id="fKnSCGM_49d5ayVgUhBN-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=none;startFill=0;dashed=1;startArrow=none;shadow=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fontFamily=monospace;" parent="1" source="fKnSCGM_49d5ayVgUhBN-2" target="fKnSCGM_49d5ayVgUhBN-12" edge="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="170" y="560" as="targetPoint" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-7" value="Ethernet, MQTT" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=monospace;" parent="fKnSCGM_49d5ayVgUhBN-6" vertex="1" connectable="0"> <mxGeometry x="-0.2238" y="-2" relative="1" as="geometry"> <mxPoint x="-16" y="-8" as="offset" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" parent="1" source="fKnSCGM_49d5ayVgUhBN-2" target="fKnSCGM_49d5ayVgUhBN-8" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-2" value="Központi egység (ESP32)" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=monospace;" parent="1" vertex="1"> <mxGeometry x="280" y="515" width="180" height="90" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-8" value="PIR mozgásérzékelők" style="ellipse;whiteSpace=wrap;html=1;rounded=1;fontFamily=monospace;" parent="1" vertex="1"> <mxGeometry x="291.09" y="340" width="157.81" height="70" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-12" value="Home Assistant" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=monospace;" parent="1" vertex="1"> <mxGeometry x="30" y="530" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" parent="1" edge="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="390" y="515" as="sourcePoint" /> <mxPoint x="390" y="409" as="targetPoint" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" parent="1" edge="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="355" y="515" as="sourcePoint" /> <mxPoint x="355" y="410" as="targetPoint" /> </mxGeometry> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-20" value="..." style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1"> <mxGeometry x="365" y="448" width="30" height="30" as="geometry" /> </mxCell> <mxCell id="fKnSCGM_49d5ayVgUhBN-21" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;startFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=monospace;" parent="1" edge="1"> <mxGeometry relative="1" as="geometry"> <mxPoint x="340" y="515" as="sourcePoint" /> <mxPoint x="340" y="408" as="targetPoint" /> </mxGeometry> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> "><defs/><g><g data-cell-id="0"><g data-cell-id="1"><g data-cell-id="fKnSCGM_49d5ayVgUhBN-6"><g><path d="M 250 220 L 120 220" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-7"><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 211px; margin-left: 185px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "><div style="display: inline-block; font-size: 11px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; ">Ethernet, MQTT</div></div></div></foreignObject><text x="185" y="214" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="11px" text-anchor="middle">Ethernet, MQTT</text></switch></g></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-9"><g><path d="M 340 175 L 339.99 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-2"><g><rect x="250" y="175" width="180" height="90" rx="13.5" ry="13.5" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 220px; margin-left: 251px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Központi egység (ESP32)</div></div></div></foreignObject><text x="340" y="224" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="12px" text-anchor="middle">Központi egység (ESP32)</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-8"><g><ellipse cx="339.99" cy="35" rx="78.905" ry="35" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 156px; height: 1px; padding-top: 35px; margin-left: 262px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">PIR mozgásérzékelők</div></div></div></foreignObject><text x="340" y="39" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="12px" text-anchor="middle">PIR mozgásérzékelők</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-12"><g><rect x="0" y="190" width="120" height="60" rx="9" ry="9" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "monospace"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Home Assistant</div></div></div></foreignObject><text x="60" y="224" fill="light-dark(#000000, #ffffff)" font-family=""monospace"" font-size="12px" text-anchor="middle">Home Assistant</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-18"><g><path d="M 360 175 L 360 69" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-19"><g><path d="M 325 175 L 325 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-20"><g><rect x="335" y="108" width="30" height="30" fill="none" stroke="none" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 123px; margin-left: 350px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">...</div></div></div></foreignObject><text x="350" y="127" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">...</text></switch></g></g></g><g data-cell-id="fKnSCGM_49d5ayVgUhBN-21"><g><path d="M 310 175 L 310 68" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file