This shows you the differences between two versions of the page.
si:teme2022:tema2 [2023/12/10 23:28] florin.stancu |
si:teme2022:tema2 [2023/12/12 12:00] (current) florin.stancu old revision restored (2023/01/13 22:44) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Tema 2 - Home Weather Monitoring System ====== | + | ====== Tema 2 - Christmas LEDs ====== |
- | * **Publicare**: | + | * **Publicare**: |
- | * **11 Decembrie 2023** | + | * **11 Decembrie 2022 //17:50//** |
- | * **Termen de predare**: | + | * **Termen de predare**: |
- | * <color red>**13 Ianuarie 2024 23:55** - deadline HARD</color> | + | * <color red>**15 Ianuarie 2023 23:55** - deadline HARD</color> |
- | <hidden> | + | * **Changelog:** |
- | * **Changelog:** | + | * //**14 Ianuarie 2023 22:30**// - mărit deadline-ul până duminica ;) |
- | * //**05 Ianuarie 2023 HH:II**// - TODO; | + | * //**13 Ianuarie 2023 11:15**// - corectat numele fișierelor: ''url.txt'' + ''checksum.txt'' (CU extensie). |
- | </hidden> | + | * //**05 Ianuarie 2023 13:40**// - reparat RESTful endpoints din text să fie ca în scriptul de Python de demo. |
<note> | <note> | ||
**Obiective**: | **Obiective**: | ||
- | * construirea unei distribuții Linux minimaliste; | + | * construirea unei distribuții Linux complete, build folosind Yocto; |
+ | * creare layere + pachete Yocto; | ||
* configurări de bază Linux; | * configurări de bază Linux; | ||
* servicii de sistem Linux; | * servicii de sistem Linux; | ||
- | * dezvoltare aplicații IoT; | + | * dezvoltare aplicații RESTful; |
- | * utilizare interfață serială (UART & TTY) pe Linux; | + | * dezvoltare aplicații Terminal UI; |
+ | * interfață GPIO Linux; | ||
* optimizări de spațiu; | * optimizări de spațiu; | ||
</note> | </note> | ||
<note important> | <note important> | ||
- | Pentru a rezolva tema, este recomandat să folosiți [[https://github.com/cs-pub-ro/SI-Lab-VM/releases/|mașina virtuală SI 2023]] cu toate uneltele necesare gata instalate! | + | Pentru a rezolva tema, este recomandat să folosiți [[https://github.com/cs-pub-ro/SI-Lab-VM/releases/|mașina virtuală Yocto 2022 (~22GB)]] cu distribuția Yocto gata compilată și cache-uită, altfel timpul de compilare pe un laptop modest poate fi chiar și de 10 ore! |
+ | Puteți lucra în paralel cu laboratorul pe aceiași mașină (veți folosi descriptori de ''kas'' (în format ''yml'') din fișiere diferite + layere separate). | ||
</note> | </note> | ||
- | |||
- | //TODO// | ||
<ifauth @si> | <ifauth @si> | ||
- | <color red>CINE VEDE RESTUL E ASISTENT ;) </color> | + | <color red>CINE VEDE ASTA E ASISTENT ;) </color> |
+ | </ifauth> | ||
+ | |||
+ | ===== Storyline / Enunț ===== | ||
- | ===== Enunț ===== | + | A venit Crăciunul! Ca viitori ingineri ai unei facultăți de renume din țară (//***ahem***//), dorim să impresionăm familia / rudele / pisica / vecinii construind o instalație de pom controlabilă din Internet of Things! |
- | Dorim să realizăm o aplicație IoT care primește date de la câțiva senzori meteo (temperatură, umiditate, ploaie -- datele vor fi emulate) și îi face disponibili pe o interfață web a unui Raspberry PI (de asemenea, emulat în qemu). | + | Așadar, ne apucăm de treabă: luăm o bandă cu LED-uri și începem prin dezvoltarea unei aplicații care să le poată controla de la distanță, printr-o interfață RESTful HTTP. |
+ | Însă intervine problema: pe ce o rulăm? Ne amintim ce am studiat la cursul și laboratoarele de S.I și ne dăm seama că avem un Raspberry PI mai vechi aruncat într-o cutie, deci mai rămâne doar de construit / configurat o distribuție lightweight de **Linux** ([[https://www.huffpost.com/archive/in/entry/bill-gates-best-secret-santa_a_21631414|sorry, Santa]]) ce se va interfața cu hardware-ul instalației de lumini și va oferi suport pentru rularea aplicației și conectarea la Internet. | ||
- | Ca și cerință principală, va trebui să realizați o imagine incorporabilă cu Linux ce va expune pe rețea un server HTTP cu o aplicație web de vizualizare a senzorilor, ce va prelua datele de pe interfață UART (formatul descris mai jos). | + | Ca și cerință principală, va trebui să realizați o imagine incorporabilă Linux folosind Yocto ce va expune pe rețea un server HTTP cu API REST-ful (detalii / specificație mai jos) pentru primirea de comenzi de control al LED-urilor. |
- | Aveți în imaginea următoare un exemplu de pagină web ce va fi afișată (însă aspectul nu prea contează): | + | De asemenea, dorim să vedem, în consolă, o simulare grafică (ASCII Art) a bradului de Crăciun cu luminițele aprinse în starea actuală. |
+ | Un exemplu de pom luminat poate fi văzut în captura de mai jos (asciinema): | ||
- | TODO | + | <html> |
+ | <a href="https://asciinema.org/a/YIEhjwqJlYsYrWdD2nsIn4OX7" target="_blank"><img style="max-width: 300px;" src="https://asciinema.org/a/YIEhjwqJlYsYrWdD2nsIn4OX7.svg" /></a> | ||
+ | </html> | ||
===== Cerințe ===== | ===== Cerințe ===== | ||
Line 45: | Line 53: | ||
=== Imaginea Linux de bază: === | === Imaginea Linux de bază: === | ||
- | Pas inițial: realizarea unei imagini de bază de Linux (kernel + rootfs) ce va fi folosită ca punct de plecare / suport pentru programele & serviciile cerute de restul cerințelor: | + | * Imaginea sistemului trebuie generată cu Yocto, pornind de la instrucțiunile prezente în [[:si:laboratoare:06]]; |
+ | * Sistemul trebuie să ruleze în QEMU ARM, folosind un kernel Yocto pentru machine type ''qemuarm''; | ||
+ | * Sistemul trebuie să aibă un utilizator ''root'' cu parola ''tema2'' (obligatoriu!!); | ||
+ | * Sistemul trebuie să aibă hostname-ul ''tema2''; | ||
+ | * Sistemul trebuie să-și preia automat IP-ul folosind DHCP pe singura interfață disponibilă; | ||
+ | * Sistemul trebuie să ruleze SSH pe portul 22; | ||
+ | * Sistemul trebuie să ruleze daemon-ul Avahi/mDNS și să răspundă la numele ''tema2.local''. | ||
- | * Imaginea trebuie construită din componente de la zero: kernel compilat + generat rootfs; | + | === RESTful HTTP endpoint: === |
- | * **Rootfs**-ul să ocupe cât mai puțin posibil (vedeți mai jos punctajele); se poate folosi orice distribuție & abordare de generat ''rootfs'' (atât printre cele studiate la laborator, cât și celelalte populare în industrie): | + | |
- | * [[https://buildroot.org/|Buildroot]] -- recomandat, puteți obține cele mai reduse dimensiuni! | + | |
- | * [[https://www.debian.org/|Debian]], prin [[https://ocw.cs.pub.ro/courses/si/laboratoare/08|qemu + debootstrap]] -- nerecomandat (se vor obține dimensiuni destul de mari, ''500MB ~ 1GB'') și nu vor fi ușor depunctate (10%); | + | |
- | * [[https://alpinelinux.org/|Alpine Linux]] bootstrapuit folosind [[https://wiki.alpinelinux.org/wiki/Bootstrapping_Alpine_Linux|apk.static]] -- procedură similară cu ''debootstrap'', însă se vor obține imagini mult mai mici (recomandat, însă va trebui [[https://github.com/alpinelinux/alpine-chroot-install|să vă documentați]] bine înainte)! | + | |
- | * [[https://www.yoctoproject.org/|Yocto Linux]] - pentru experți ;) | + | |
- | * **NU se acceptă**: rootfs gata construit / descărcabil (e.g., arhivă cu //favorite distro// de pe site-ul oficial sau third-party); | + | |
- | * Sistemul (rootfs + kernel) să fie compilat pe ''AArch64'' (i.e.: ''arm64'') și să poată fi rulat în ''qemu'' folosind machine type ''raspi3b'' (vedeți mai jos config-uri de kernel testate deja pentru compatibilitate + script de rulare recomandat); | + | |
- | * Imaginea trebuie împachetată într-un fișier disk SD (a cărui dimensiune trebuie să fie o putere a lui 2, cum [[https://interrupt.memfault.com/blog/emulating-raspberry-pi-in-qemu#running-qemu|găsiți precizat prin tutoriale]]) -- alegeți, însă, o dimensiune cât mai mică posibil (e.g., dacă imaginea voastră ocupă ''70MB'', creați imaginea de ''128MB''). | + | |
- | Sistemul trebuie să conțină următoarele configurații de bază (ne ajută pe noi, în special, să automatizăm partea de testare): | + | * Sistemul va trebui să ruleze un server http ce va asculta după cereri HTTP (pe portul 80) pentru controlul luminilor (definite mai jos); |
+ | * Puteți folosi orice limbaj de programare / scripting / framework pentru a construi acest endpoint; exemple: | ||
+ | * **Python**: [[https://flask.palletsprojects.com|flask]] / [[https://docs.cherrypy.dev|CherryPy]] / [[https://fastapi.tiangolo.com/|FastAPI]] (pick any); | ||
+ | * **NodeJS**: [[https://expressjs.com/|ExpressJS]] / [[https://loopback.io/|Loopback]] / other 1000s of libraries; | ||
+ | * **PHP** (//+ Apache / Nginx / Lighttpd etc.//): well... cam e făcut pentru așa ceva, dar va trebui să configurați URL rewriting pe serverul http :P ; | ||
+ | * **Golang**: [[https://pkg.go.dev/net/http|net/http]] (aici nu se justifică să descărcați altceva); | ||
+ | * **Rust**: [[https://docs.rs/http/latest/http/|http]] (built in, baby!); | ||
+ | * **C (for hardcore developers)**: [[https://facil.io/|Facil]] / [[https://github.com/babelouest/ulfius|Ulfius]] | ||
+ | * **//Hint://** alegeți ori ceva ce doriți să învățați sau pe cel cu care sunteți familiar și căutați-i layer / pachet pentru Yocto ;) | ||
- | * utilizator ''root'' cu parola ''tema2'' (obligatoriu: să ne putem autentifica în consola emulată); | + | <note> |
- | * hostname-ul ''tema2''; | + | Serverul trebuie să pornească automat la boot (ca daemon). În Yocto [[https://docs.yoctoproject.org/dev-manual/common-tasks.html#enabling-system-services|aveți două opțiuni de bază]]: **SysVInit** (aka ''rc.d''/''runlevels'', instalat implicit -- nu trebuie să mai compilați nimic) și **SystemD** (mai ușor de definit serviciile, însă trebuie compilat și poate dura //~1h//, depinde de puterea de calcul a sistemului). |
- | * să-și preia automat IP-ul folosind DHCP pe prima interfață disponibilă (recomandat: folosiți la rulare parametrul de kernel ''net.ifnames=0'', astfel încât numele primei interfețe să fie ''eth0'' pentru o configurație portabilă); | + | </note> |
- | * să ruleze SSH pe portul 22 (la fel, să fie activată autentificarea cu ''root'' + parolă!); | + | |
- | * să ruleze Avahi mDNS daemon și să răspundă la numele ''tema2.local'' (opțional, dar ne ajută la testare; setupul pe host se face mai dificil, însă pe mașina emulată, însă este suficient să fie compilat/instalat pachetul ''avahi-daemon'' - sau echivalentul în distribuția aleasă - și testa cu ''ping tema2.local''). | + | |
- | Rezolvarea acestei cerințe este OBLIGATORIE pentru obținerea oricărui fel de punctaj (altfel nu avem ce testa => ''0p'')! | + | === Terminal UI program: === |
- | <note warning> | + | * Pe lângă serviciul web, va trebui să dezvoltați un program (numit ''christmas-tree'') rulabil ca ''root'' care să afișeze la stdout un ASCII ART (pe consolă, folosind [[https://chrisyeh96.github.io/2020/03/28/terminal-colors.html|secvențe escape ANSI]]); |
- | Inb4: veți avea de customizat //rootfs-ul//. După cum va trebui să separați fișierele / codul / scripturile sursă de imaginea binară obținută ca rezultat al procesului de build (care poate fi semi-manual sau complet automatizat -- ce preferați), recomandăm organizarea unui **overlay** -- subdirector al temei unde includeți DOAR fișierele de configurație / surse ce doriți să apară în imaginea finală ce le vor suprascrie pe cele implicite. | + | * Programul va afișa, în mod dinamic (actualizare timp real, cu latența de preferat de ordinul secundelor), un pom de Crăciun frumos luminat / colorat după ultima stare configurată prin API-ul RESTful (serverul HTTP). |
+ | * La fel ca la serviciul web, puteți folosi orice limbaj + biblioteci de desenare pe consolă doriți, exemple: | ||
+ | * **Python**: [[https://docs.python.org/3/howto/curses.html|curses (built-in)]] / [[https://github.com/Textualize/rich|Rich]] / [[https://pypi.org/project/urwid/|urwid]]; | ||
+ | * **NodeJS**: [[https://github.com/chjj/blessed|blessed]] / [[https://github.com/cronvel/terminal-kit|Terminal Kit]]; | ||
+ | * **PHP**: [[https://climate.thephpleague.com/|Climate]]; | ||
+ | * **Golang**: [[https://github.com/gdamore/tcell|TCell]] / [[https://github.com/rthornton128/goncurses|goncurses]]; | ||
+ | * **Rust**: [[https://github.com/jeaye/ncurses-rs|ncurses-rs]] / [[https://github.com/gyscos/cursive|cursive]]; | ||
+ | * **C**: [[https://invisible-island.net/ncurses/|ncurses (the OG)]]; | ||
+ | * Puteți face comunicarea între cele 2 procese (program TUI + server HTTP) prin orice mecanism vă pune Linux / limbajul la dispoziție (unix pipes, sockeți, RPC framework al limbajului, sistem de fișiere -- însă aici veți avea de furcă la notificarea schimbărilor :P); | ||
+ | * Acest program trebuie **OBLIGATORIU** să se numească ''christmas-tree'' și să fie în ''PATH'' (rulabil direct prin acest nume într-un terminal)! Acesta va fi pornit automat, prin ''ssh'', pentru testare facilă! | ||
+ | * Cât despre design-ul pomului / elementelor afișate, aveți libertate deplină (cât timp se înțelege ce este și luminițele au culori :D); | ||
- | Pentru rootfs-ul construite prin tehnică de //package-based bootstrapping//, puteți copia ulterior acest overlay folosind ''cp -ar'' sau ''rsync -a''. | ||
- | Pentru BuildRoot, citiți [[https://buildroot.org/downloads/manual/manual.html#rootfs-custom|recomandările oficiale de customizare]]. | + | === Bonus task: GPIO === |
- | + citiți enunțul până la capăt pentru a vedea cerințele finale! | + | Dorim să trimitem comenzile primite de serverul HTTP către instalația hardware de leduri. |
- | </note> | + | Astfel: |
- | === HTTP Server / Web UI: === | + | * Mașina de qemu dispune de un [[https://www.qemu.org/docs/master/system/arm/virt.html?highlight=pl061|controller de GPIO PL061]] pe care îl vom folosi să simulăm această interacțiune. |
+ | * Pe partea de Linux, aveți API de [[https://blog.lxsang.me/post/id/33|userspace pentru dispozitivele GPIO]] bazat pe sistemul de fișiere virtual ''/sys'' (API vechi) sau ''/dev'' + eventual, puteți găsi biblioteci în limbajul ales; | ||
+ | * Va trebui, însă, să [[https://docs.yoctoproject.org/kernel-dev/common.html|re-configurați kernelul Yocto]] și să activați driverul [[https://www.kernelconfig.io/config_gpio_pl061|PL061]] al dispozitivului GPIO emulat de qemu; | ||
+ | * Puteți folosi orice mapare grup / led la pini GPIO doriți, singura cerință este ca, la schimbarea stării (sau culorilor) acestora, și GPIO-urile asociate să-și modifice starea aferentă! | ||
- | Dorim ca sistemul să expună un server HTTP pe portul 80 o interfață web minimalistă care să prezinte datele de la senzorii primiți prin UART: | ||
- | * Sistemul va trebui să ruleze un server http ce va asculta după cereri HTTP (pe portul 80) pentru controlul luminilor (definite mai jos); | + | === Contract (API) === |
- | * Puteți folosi orice limbaj de programare / scripting / framework pentru a construi acest endpoint; exemple: | + | |
- | * **Python**: [[https://docs.python.org/3/library/http.server.html|http.server]] / [[https://flask.palletsprojects.com|flask]] / [[https://djangoproject.com/|Django]] / etc.; | + | |
- | * **NodeJS**: [[https://nodejs.org/api/http.html|http]] / [[https://expressjs.com/|ExpressJS]] / other 1000s of libraries; | + | |
- | * **PHP** (//+ Apache / Nginx / Lighttpd etc.//): cu sau fără framework (recomandat); | + | |
- | * **Golang**: [[https://pkg.go.dev/net/http|net/http]] (bonus: dimensiuni mici ale aplicațiilor!); | + | |
- | * **Rust**: [[https://docs.rs/http/latest/http/|http]] (built in libraries + dimensiuni ff. mici, la fel ca la GoLang!); | + | |
- | * **C/C++ (for hardcore developers)**: [[https://facil.io/|Facil]] / [[https://github.com/oatpp/oatpp|Oat++]] / etc. -- ''performanță++ && dimensiuni%--%'' ;) | + | |
- | * **//Atenție://** Dacă alegeți să compilați //rootfs// prin Buildroot, veți avea de scris/făcut rost de scripturi de compilare + împachetare atât pentru codul vostru + toate dependințele necesare (e.g., la Python PIP / VirtualEnv, pachete ''npm'' pentru NodeJS etc.)! Se poate, desigur, face cross compiling, însă trebuie folosit compilatorul de la Buildroot (same thing for Yocto)! | + | |
- | <note> | + | Sistemul va reprezenta un pom de Crăciun cu o serie de //luminițe// organizate în ''NG'' //grupuri// de câte ''1..n'' LED-uri fiecare (fiecare grup poate conține număr diferit de luminițe). |
- | Serverul trebuie să pornească automat la boot (ca daemon). Majoritatea distribuțiilor folosesc [[https://www.digitalocean.com/community/tutorials/systemd-essentials-working-with-services-units-and-the-journal|systemd]] ca ''init'' și manager de servicii, deci va trebui să creați un astfel de descriptor pentru aplicația web. | + | Parametrii aceștia puteți să-i alegeți la liber și să-i hardcodați (în funcție de câte luminițe aveți loc să reprezentați în ASCII Art-ul din terminal), însă ar fi drăguț să aveți minim 3 grupuri (e.g., pentru fiecare etaj al bradului sau pe diagonală). |
- | În ''BuildRoot'' și ''Yocto'' aveți mai multe opțiuni de init system-uri, la alegere: **Busybox** (cel mai light dintre toate, se scriu scripturi ''sh''), **SysVInit** (aka ''rc.d''/''runlevels'') sau **SystemD** (mai popular și bine documentat, însă trebuie compilat și poate adăuga //~1-2h// în plus la timpul de compilare, depinde de puterea de calcul a sistemului). | + | Fiecare grup are ca identificator unic (unde numerotarea începe de la ''1''!) este un vector de LED-uri (de dimensiune statică). |
- | </note> | + | |
- | Datele de la senzori le veți prelua de la un alt serviciu, descris în subsecțiune următoare. | + | Valoarea fiecărui LED dintr-un grup va fi ID-ul numeric al culorii acestuia, folosind [[https://chrisyeh96.github.io/2020/03/28/terminal-colors.html|culorile clasice din terminal]]: |
- | Dacă nu rezolvați acest task, puteți să prezentați pur și simplu câteva date de test în interfața Web. | + | * ''0'' (//black//) (echivalent al LED-ului stins); |
+ | * ''1'' (<color red/black>//red//</color>); | ||
+ | * ''2'' (<color green/black>//green//</color>); | ||
+ | * ''3'' (<color yellow/black>//yellow//</color>); | ||
+ | * ''4'' (<color blue/black>//blue//</color>); | ||
+ | * ''5'' (<color magenta/black>//magenta//</color>); | ||
+ | * ''6'' (<color cyan/black>//cyan//</color>); | ||
+ | * ''7'' (<color white/black>//white//</color>); | ||
+ | Astfel, se definesc următoarele endpointuri RESTful HTTP (atenție: API-ul este strict!): | ||
+ | * ''GET /api/groups'': va întoarce un obiect JSON cu proprietatea ''NG'' (numărul de grupuri disponibile), e.g.: ''{"NG": 3}''; | ||
+ | * ''GET /api/group/<G>/state'': va întoarce un obiect JSON cu cheila ''NL'': numărul de leduri din grupul curent, și ''LC'': lista actuală de culori ale LED-urilor grupului ''<G>'' (fără caracterele ''<>'', sunt doar pentru a denota o variabilă), e.g., ''{"NL": 8, "LC": [0, 0, 0, 1, 4, 2, 0, 0]}''; | ||
+ | * ''POST /api/group/<G>/static'': va primi un obiect JSON cu o singură cheie: ''LC'' cu valoarea: o listă (JSON Array) de culori pentru fiecare LED din grupul ''<G>'', și va întoarce OK (HTTP 200); desigur, aceste noi setări trebuiesc propagate către aplicația de terminal ce redă ASCII Art-ul; | ||
+ | * ''POST /api/group/<G>/animate'' [**BONUS**]: va primi un obiect cu o cheie, ''MC'' care conține o matrice de culori pentru fiecare pas al animației, apoi pentru fiecare LED din grupul ''<G>'' și va întoarce OK (HTTP 200); tranzițiile vor fi făcute la fiecare secundă și va fi repetată automat până la revenirea la cazul simplu (cererea de mai sus); exemplu de mutare a culorilor asupra tuturor pozițiilor dintr-un grup: <code> | ||
+ | [ | ||
+ | [1, 2, 3, 0, 0, 0, 0, 0], | ||
+ | [0, 1, 2, 3, 0, 0, 0, 0], | ||
+ | [0, 0, 1, 2, 3, 0, 0, 0], | ||
+ | [0, 0, 0, 1, 2, 3, 0, 0], | ||
+ | [0, 0, 0, 0, 1, 2, 3, 0], | ||
+ | [0, 0, 0, 0, 0, 1, 2, 3], | ||
+ | [3, 0, 0, 0, 0, 0, 1, 2], | ||
+ | [2, 3, 0, 0, 0, 0, 0, 1], | ||
+ | ] | ||
+ | </code> | ||
- | === Sensor data acquisition daemon: === | + | Toate cererile vor folosi formatul ''Content-Type: application/json'' atât la input (pentru cererile ''POST''), cât și la răspuns. |
- | Pe lângă serviciul web, va trebui să dezvoltați un daemon de achiziție a datelor de pe un dispozitiv serial (emulat prin QEmu ca ''usb-serial'', vizibil în guest Linux ca ''/dev/ttyUSB0''); | + | Vedeți exemple de utilizare în fișierul ''test.py'' din schelet. |
- | * Programul va rula într-o buclă de citire de la dispozitiv, parsare și trimitere date către . | + | <note important> |
- | * La fel ca la serviciul web, puteți folosi orice limbaj / biblioteci de conectare pe dispozitivul serial (chiar și ''bash'' :D ): | + | Tema va fi testată în QEMU (''v6.2+'' pe Ubuntu 22.04) pentru placa [[https://qemu.readthedocs.io/en/latest/system/arm/virt.html|virt]] (este deja tipul implicit pentru build-urile Yocto ale ''qemuarm'', cel folosit la laborator). |
- | * **Python**: [[https://pypi.org/project/pyserial/|pyserial]]; | + | </note> |
- | * **NodeJS**: [[https://www.npmjs.com/package/serialport|serialport]]; | + | |
- | * **PHP**: [[https://www.php.net/manual/en/book.dio.php|DirectIO]]; | + | |
- | * **Golang**: [[https://pkg.go.dev/go.bug.st/serial|goserial]] sau alte biblioteci similare (sunt multe cu același nume); | + | |
- | * **Rust**: [[https://docs.rs/serialport/latest/serialport/|serialport]]; | + | |
- | * **C**: [[https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/|POSIX + termios]]; | + | |
- | * Puteți face comunicarea între cele 2 procese (de la daemonul de achiziție date seriale la server HTTP) prin orice mecanism vă pune Linux / limbajul la dispoziție (unix pipes, sockeți, RPC framework al limbajului, chiar și sistem de fișiere pentru o implementare rudimentară); | + | |
- | * Acest program trebuie **OBLIGATORIU** să se numească ''iotsensord'' și să pornească automat cu sistemul! | + | |
- | + | ||
- | ==== Format date seriale ==== | + | |
- | + | ||
- | Dispozitivul serial emulat va trimite informații codificate în text (ASCII), câte o linie per senzor, un mesaj fiind terminat printr-un caracter simplu ''LF'' (''\n''). | + | |
- | + | ||
- | Formatul folosit va fi similar CSV-ului, însă câmpurile vor fi separate prin caracterul '';'', având sintaxa generală: <code> | + | |
- | TIMESTAMP; LOCATION; SENSOR_NAME; SENSOR_VALUE; FLAGS (optional) | + | |
- | </code> | + | |
- | + | ||
- | Unde: | + | |
- | * ''TIMESTAMP'' este o valoare intreagă, Unix Timestamp, exprimată în secunde de la Unix Epoch (''01.01.1970 00:00''); | ||
- | * ''LOCATION'' va reprezenta locația senzorului și va avea următoarele valori: ''ext'' -- exterior (i.e., afară), ''int'' interior (i.e., în casă); | ||
- | * ''SENSOR_NAME'': este denumirea senzorului; vor fi definiți senzorii: ''humidity'' (relative humidity, procentaj), ''temp'' (temperatură, în grade Celsius) și ''rain'' (boolean, ''0 / 1''); | ||
- | * ''SENSOR_VALUE'': valoarea senzorului; număr întreg, de obicei, însă la valorile de temperatură pot apărea și cu virgulă mobilă (e.g., ''23.5''); **nu apare** nicio unitate de măsură, acestea fiind implicit cele de mai sus; | ||
- | * ''FLAGS'': câmp opțional (poate să lipsească), poate avea valoarea ''ERROR'' pentru a alerta (din interfața web) faptul că a apărut o eroare la senzorul fizic și datele nu sunt valide (se va citi valoarea ''0'' la câmpul ''VALUE''). | ||
- | ===== Instrucțiuni pentru rularea imaginii folosind QEmu ===== | + | ===== Helpers + Mașină virtuală ===== |
- | Ca și punct de pornire, puteți descărca un {{si:teme2023:TODO-skel.tar.gz|schelet inițial cu scripturi + structură recomandată}} (**v0.1**). | + | Ca și punct de pornire, puteți descărca un {{si:teme2022:si-tema2-skel-2022-0-1.tar.gz|schelet inițial cu scripturi + structură recomandată}} (**v0.1**). |
Aceasta conține: | Aceasta conține: | ||
+ | * Makefile pentru generarea arhivelor cerute (înlocuiți-l pe cel de acum din VM, este inutil :D); | ||
+ | * script de rulare qemu pe host (folosit pentru rularea directă a imaginii de distribuit, fără Yocto); | ||
+ | * un fișier descriptor pentru //kas// diferit de cel din laborator (numit ''tema2.yml''); | ||
+ | * un script de testat endpointul RESTful (+ exemplu utilizare API) folosind python (''test.py''); | ||
+ | * un README.skel.txt pe care ar fi util să-l citiți ;) | ||
+ | * **Important:** citiți codul sursă al scripturilor și verificați (e.g., căile) să fie adecvate setup-ului vostru! | ||
- | * script de testare ''launch-tema2.sh'' pe sistemul gazdă (va rula ''qemu'' cu fișierele kernel+imagine, vedeți mai jos, la conținutul arhivei, ce denumiri folosește); | + | Recomandarea de co-existență pentru tema2 + laborator folosind același VM cu Yocto: fișierele kas cu denumiri diferite (''tema2.yml'' vs ''kas.yml'') ce vor importa seturi diferite de layere (desigur, cele de bază vor rămâne, însă se recomandă crearea unui layer numit ''meta-tema2'' și să creați în interiorul lui configurațiile / pachetele necesare tuturor task-urilor). |
- | * un script Python ''sensors-emu.py'' ce emulează datele de la senzori, integrat cu ''launch-tema2.sh'' (vedeți cod sursă / help); | + | |
- | Aceste scripturi au fost testate în VM-ul oficial folosit la laborator. | + | <note> |
- | Dacă aveți setup propriu, puteți cere ajutor pe Teams / Forum dacă apar probleme. | + | Nu uitați să inspectați configurația de resurse a VM-ului (și să le ajustați pentru PC-ul vostru). |
+ | Compilarea unor pachete poate eșua dacă nu aveți suficient RAM (''8GB'' ar trebui să fie OK pentru majoritatea cazurilor). | ||
+ | </note> | ||
===== Trimitere ===== | ===== Trimitere ===== | ||
Soluția temei va fi trimisă în două moduri (vă rugăm să respectați convențiile de denumire cu exactitate!): | Soluția temei va fi trimisă în două moduri (vă rugăm să respectați convențiile de denumire cu exactitate!): | ||
- | * **arhivă cu codul sursă** + Readme + hash și alte metainformații (vedeți mai jos) -> [[TODO|pe Moodle]] | + | * **arhivă cu codul sursă** + Readme + hash și alte metainformații (vedeți mai jos) -> [[https://curs.upb.ro/2022/mod/assign/view.php?id=102647|pe Moodle]] |
- | * **arhivă cu binarele / imaginea rulabilă** -> le urcați pe [[https://ctipub-my.sharepoint.com|Sharepoint-ul contului Microsoft de student]] și dați share prin Link Public (pe care ni-l trimiteți doar nouă în fișierul ''url.txt''). | + | * **arhivă cu binarele / imaginea rulabilă** -> le urcați pe [[https://ctipub-my.sharepoint.com|OneDrive / Sharepoint-ul UPB]] și dați share prin Link Public (pe care ni-l trimiteți doar nouă în fișierul ''url.txt''). |
- | **Arhiva cu binarele** (''.tar.*z'' pls; se acceptă ''gz'' și ''xz'') trebuie să conțină (**obligatoriu: să folosiți strict aceste denumiri de fișiere**): | + | **Arhiva cu binarele** (''.tar.gz'' pls) trebuie să conțină (de preferat să folosiți strict aceste denumiri de fișiere): |
- | * ''tema2.img'': imaginea finală (format ''raw''!); poate conține sau nu partiții (dar va trebui să adaptați scriptul de rulare). | + | * ''rootfs.img'': imaginea partiției rootfs în format RAW utilizabil de qemu (ori partiția ext4, ori disk image); |
- | * ''vmlinuz-tema2'': imaginea kernel-ului compatibil cu QEMU; | + | * ''kernel'': binarul kernel-ului compatibil cu QEMU (scheletul îl copiază automat din cache-ul Yocto); |
- | * ''launch-tema2.sh'': script de pornire QEMU (vedeți scheletul dat); | + | * ''launch_bin.sh'': script de pornire QEMU (vedeți scheletul dat); |
- | * includeți și scripturile suplimentare necesare pentru rulare (e.g., simulatorul de senzori în Python); | + | * Dacă doriți să ne prezentați alt scenariu demonstrativ (decât cel inclus în schelet), includeți un script numit ''test.py''. |
- | * **NU INCLUDEȚI**: cache-ul de build al Buildroot / Yocto (poate avea ''6-20 GB''!), DOAR artefactele finale! | + | * **NU INCLUDEȚI**: directorul build cache al yocto (yep, acela de > 20GB!); |
- | * Această arhivă nu ar trebui să depășească ''500MB'' ([[https://stackoverflow.com/questions/18855850/create-a-tar-xz-in-one-commandfolosiți tar.xz]] pentru rată de compresie bună). | + | * Această arhivă nu ar trebui să depășească ''500MB'' (și asta în cazuri extreme). |
- | **Arhiva cu fișierele sursă** (''.zip'' pls) OBLIGATORIU să conțină: | + | **Arhiva cu fișierele sursă** (''.zip'' pls) este OBLIGATORIU să conțină: |
- | * sursele aplicației (în orice limbaje ați ales), scripturi custom folosite pentru build și/sau overlay-ul copiat pe ''rootfs'' (orice ați inclus extra peste sistemul de bază -- de preferat, organizat într-o structură Unix-like: ''./etc/'', ''./usr/bin'', ''./opt/*'' etc.); **NU COPIAȚI ROOTFS-UL GENERAT!** | + | * scripturile proprii de Yocto (layer, rețete, fișier ''yml'' pentru ''kas'') + sursele aplicației (în orice limbaje ați ales); |
- | * fișierele de configurație (''.config'') ale kernel și/sau buildroot -- **obligatoriu** dacă unde e cazul! folosiți numele ''kernel_config'' și ''buildroot_config'' în arhiva cu sursele (în niciun caz nu le lăsați hidden!); | + | * fișier ''README.txt'' cu explicații referitoare la funcționarea soluției, configurații speciale de optimizare folosite etc. |
- | * fișier ''README.txt'' cu explicații referitoare la modul de construire al imaginii, arhitectura soluției, configurații speciale de optimizare folosite etc. | + | * fișier ''url.txt'' cu URL către arhiva **.tar.gz** a binarelor; |
- | * fișier ''url.txt'' cu URL către arhiva **.tar.*z** a binarelor **PE Sharepoint!**; | + | |
* fișier ''checksum.txt'' care să conțină hash-ul SHA256 al arhivei cu binarele (obținut cu ''sha256sum''); **ATENȚIE**: verificați și re-verificați (de încă 2 ori) conținutul fișierului la încărcare pe Moodle cu hash-ul real deoarece tema nu va fi punctată dacă diferă! | * fișier ''checksum.txt'' care să conțină hash-ul SHA256 al arhivei cu binarele (obținut cu ''sha256sum''); **ATENȚIE**: verificați și re-verificați (de încă 2 ori) conținutul fișierului la încărcare pe Moodle cu hash-ul real deoarece tema nu va fi punctată dacă diferă! | ||
- | * **NU INCLUDEȚI**: fișiere sursă ale Buildroot / Yocto / biblioteci / frameworkuri / VirtualEnv descărcabile de pe Internet (menționați în Readme ce ați folosit); | + | * **NU INCLUDEȚI**: fișiere sursă ale Poky / alte layere Yocto / biblioteci / frameworkuri descărcabile de pe Internet (menționați în Readme ce ați folosit); puteți include bblayers.conf și local.conf dacă le-ați modificat manual (în afara ''kas''). |
* **Hint**: pentru a include un fișier la crearea automată a arhivei prin ''make source_archive'', pur și simplu copiați-l pe rădăcină (sau într-un director care nu este ignorat -- verificați Makefile-ul din schelet)! | * **Hint**: pentru a include un fișier la crearea automată a arhivei prin ''make source_archive'', pur și simplu copiați-l pe rădăcină (sau într-un director care nu este ignorat -- verificați Makefile-ul din schelet)! | ||
* Această arhivă nu ar trebui să depășească ''1MB'' (aveți restricție pe Moodle). | * Această arhivă nu ar trebui să depășească ''1MB'' (aveți restricție pe Moodle). | ||
Line 179: | Line 200: | ||
Din 100p total, aveți: | Din 100p total, aveți: | ||
* (30p) Imaginea și funcționalitățile de bază (trebuie să ruleze în qemu!); | * (30p) Imaginea și funcționalitățile de bază (trebuie să ruleze în qemu!); | ||
- | * ''-10p'' depunctare pentru imagini rootfs ce depășesc 200MB (disk usage al partiției ''ext4''); | + | * (30p) Endpoindul web RESTful așa cum este el descris mai sus (API-ul este strict!); |
- | * (30p) Serviciul web de prezentare a; | + | * (30p) Programul care randează ASCII art-ul cerut la consolă; |
- | * (30p) Daemonul care achiziționaează datele pe UART; | + | |
* (10p) Readme scris clar și care descrie complet arhitectura și implementarea funcționalităților cerute. | * (10p) Readme scris clar și care descrie complet arhitectura și implementarea funcționalităților cerute. | ||
Bonus: | Bonus: | ||
- | * (10p) Aspect / funcționalitate deosebită (e.g., grafice în timp ale datelor, implementări tehnice eficiente etc.); | + | * (10p) GPIO writing (necesar să compilați driverul ''PL061'' în kernel); |
* (10p) Optimizări deosebite de spațiu ale imaginii finale (cele mai mici 10 imagini primite, însă doar dintre cele care implementează toate task-urile!); | * (10p) Optimizări deosebite de spațiu ale imaginii finale (cele mai mici 10 imagini primite, însă doar dintre cele care implementează toate task-urile!); | ||
<note important> | <note important> | ||
- | Imaginile care nu au au fost construite de la zero sau nu rulează deloc (cu excepția unor greșeli minore) nu vor fi punctate! | + | Soluțiile care nu au folosit Yocto sau nu rulează deloc (cu excepția unor greșeli minore) nu vor fi punctate! |
</note> | </note> | ||
Line 195: | Line 215: | ||
* Tema are deadline **HARD** (nu mai sunt admise soluții după expirare), așadar se recomandă să vă apucați din timp de rezolvarea acesteia! | * Tema are deadline **HARD** (nu mai sunt admise soluții după expirare), așadar se recomandă să vă apucați din timp de rezolvarea acesteia! | ||
- | * :!: **ATENȚIE**: orice formă de plagiat nu va fi permisă și va duce la depunctare totală / restanță + //avertisment oficial la decanat//! | + | * :!: **ATENȚIE**: orice formă de plagiat nu va fi permisă și va duce la depunctare totală / restanță / //that which must not be named, the E-word//! |
- | * Pe Moodle găsiți și [[TODO|un forum]] ;) La fel pe Teams, avem un canal de discuții. | + | * Pe Moodle găsiți și [[https://curs.upb.ro/2022/mod/forum/view.php?id=102648|un forum]] ;) La fel pe Teams, avem un canal de discuții. |
===== Resurse ===== | ===== Resurse ===== | ||
- | * [[:si:laboratoare:04]] | ||
* [[:si:laboratoare:06]] | * [[:si:laboratoare:06]] | ||
* [[:si:laboratoare:07]] | * [[:si:laboratoare:07]] | ||
- | * [[:si:laboratoare:08]] | + | * [[https://asciinema.org/a/YIEhjwqJlYsYrWdD2nsIn4OX7|Exemplu de pom ASCII]] |
- | * [[:si:laboratoare:08]] | + | |
- | * [[https://buildroot.org/downloads/manual/manual.html|Buildroot manual]] | + | |
- | </ifauth> | ||