Pidgeon

Pidgeon je aplikacija bazirana na Raspberry Pi-u dizajnirana za prikupljanje i upravljanje podacima o električnom napajanju s različitih lokacija. To je ključna komponenta u mreži za distribuciju električne energije, koja omogućuje prikupljanje i prijenos podataka iz mjernih uređaja.

Ključne značajke

  • Otkriće mjernih uređaja: Pidgeon automatski otkriva mjerne uređaje koje prepoznaje na mreži lokacije.
  • Provjere stanja: Redoviti pingovi i provjere stanja osiguravaju ispravno funkcioniranje mjernih uređaja i samog Pidgeona.
  • Prikupljanje podataka: Pozadinski procesi započinju uzimanje električnih mjerenja visoke frekvencije kako bi osigurali točne i aktualne podatke.
  • Lokalno pohranjivanje: Mjerenja se pohranjuju u lokalno instaliranu PostgreSQL bazu podataka, koja služi kao buffer prije slanja podataka na poslužitelj.
  • Komunikacija s poslužiteljem: Pidgeon šalje mjerenja na poslužitelj i provjerava ima li ikakvih izmjena u konfiguraciji na poslužitelju.
  • Postavljanje tarifa: Pidgeon je također odgovoran za postavljanje dnevnih i noćnih tarifa mjernih uređaja.

Optimiziranjem frekvencije mjerenja, Pidgeon osigurava najtočnije i najnovije podatke. Ovi podaci su ključni za generiranje točnih informacija o naplati i pružanje vrijednih podataka za istraživanje i analizu.

Arhitektura

Arhitektura Pidgeona dizajnirana je za učinkovito prikupljanje i upravljanje podacima o električnom napajanju. Dijagram ispod pruža vizualni prikaz arhitekture sustava.

U kontekstu jedne lokacije postoje različiti tipovi brojila, kao što su Abb B2x brojilo i Schneider iEM3xxx brojilo, koji su povezani putem RS-485. Gateway, dostupan putem porta 502, služi kao posrednik za komunikaciju podataka.

Raspberry Pi pokreće Pidgeon aplikaciju, koja je podijeljena na tri glavna paketa: Konfiguracija, Usluge i Procesi.

  • Konfiguracija: Ovaj paket sadrži komponentu Manager, odgovornu za upravljanje konfiguracijom aplikacije.
  • Usluge: Ovaj paket sadrži nekoliko servisnih komponenti:
    • Hardware: Interagira s fizičkim hardverom Raspberry Pi-a.
    • Network: Upravljanje mrežnim komunikacijama.
    • Modbus: Upravljanje Modbus protokolom za komunikaciju s mjeriteljima.
    • Database: Upravljanje lokalnom PostgreSQL bazom podataka.
    • Cloud: Upravljanje komunikacijom s cloud serverom.
  • Procesi: Ovaj paket sadrži različite procese koje Pidgeon pokreće:
    • Discovery: Otkriva brojila na mreži.
    • Ping: Redovito provjerava stanje brojila.
    • Measure: Preuzima električna mjerenja s brojila.
    • Health: Provjerava stanje Pidgeona i pohranjuje ga u lokalnu bazu podataka.
    • Push: Šalje mjerenja na cloud server.
    • Poll: Provjerava cloud server za ažuriranja konfiguracije.
    • Update: Ažurira server o stanju brojila i Raspberry PI-a.
    • Daily: Postavlja dnevnu tarifu brojila.
    • Nightly: Postavlja noćnu tarifu brojila.

Dijagram za vizualni prikaz ovih komponenti i njihovih interakcija:

Instalacija

Instalacija Pidgeona uključuje nekoliko koraka, od kojih je svaki detaljno opisan na svojoj stranici. Evo pregleda procesa:

  1. Generiranje tajni: Skripta u repozitoriju koristi sops i openssl za generiranje tajni za određeni Raspberry Pi. Ovaj korak je ključan za osiguravanje komunikacije između uređaja i poslužitelja.

  2. Kreiranje ISO slike: Druga skripta u repozitoriju koristi nix build za kreiranje ISO slike za uređaj. Ova slika sadrži Pidgeon aplikaciju i sve njene ovisnosti.

  3. Umetanje tajnog ključa: Tajni ključ generiran u koraku 1 umeće se u sliku pomoću skripte u repozitoriju. Tajni ključ se koristi za dešifriranje tajni generiranih u koraku 1 tijekom pokretanja.

  4. Sastavljanje uređaja: ISO slika se zapisuje na 1TB SSD. SSD se zatim priključuje u USB port Raspberry Pi-a, a USB-C kabel za napajanje se priključuje.

Generiranje tajni

Pomoću naredbe:

scripts/mksecrets <cloud_domain> <network_ip_range_start> <network_ip_range_end>

, ova skripta generira set tajni za specifični uređaj Raspberry Pi koristeći OpenSSL i SOPS, te ih priprema za umetanje u ISO sliku.

Koraci

  1. Skripta uzima tri argumenta: cloud_domain, network_ip_range_start i network_ip_range_end. Provjerava jesu li ti argumenti osigurani, inače izlazi s porukom o pogrešci.

  2. Postavlja direktorije za pohranu tajni i privremenih tajni.

  3. Generira jedinstveni ID za uređaj i provjerava postoje li već tajne za taj ID. Ako postoje, izlazi s porukom o pogrešci.

  4. Definira nekoliko pomoćnih funkcija za generiranje različitih vrsta tajni (ID-ovi, ključevi, lozinke, age ključevi, SSH ključevi, SSL certifikati). Te tajne se generiraju koristeći OpenSSL, age-keygen, ssh-keygen i mkpasswd.

  5. Generira tajne za različite komponente (altibiz, api, pidgeon, secrets, postgres) koristeći te pomoćne funkcije.

  6. Stvara PostgreSQL skriptu za postavljanje baze podataka i korisnika s njihovim pripadajućim lozinkama.

  7. Stvara datoteku okruženja (pidgeon.env) s raznim postavkama konfiguracije, uključujući URL baze podataka, cloud domenu, API ključ, mrežni IP raspon itd.

  8. Stvara YAML datoteku (secrets.yaml) s generiranim tajnama.

  9. Šifrira datoteku secrets.yaml koristeći SOPS i javne age ključeve altibiz, pidgeon i secrets. Šifrirana datoteka (secrets.enc.yaml) zatim se kopira u direktorij src/flake/enc s jedinstvenim ID-om uređaja kao njenim imenom.

Nakon što skripta završi, generirane tajne mogu se umetnuti u ISO sliku za uređaj Raspberry Pi.

Generiranje slike

Pomoću naredbe:

scripts/image <id>

, ova skripta generira ISO sliku za specifični uređaj Raspberry Pi koristeći skriptu image iz repozitorija.

Preduvjeti

Prije nego što započnete, provjerite jeste li generirali tajne ključeve za uređaj koristeći skriptu mksecrets. Skripta image zahtijeva šifriranu datoteku s tajnim ključevima za uređaj.

Upotreba

Skripta image uzima jedan argument: id, koji je jedinstveni identifikator za uređaj. Skripta provjerava postoji li šifrirana datoteka s tajnim ključevima za ovaj ID u direktoriju src/flake/enc. Ako ne postoji, skripta izlazi s porukom o pogrešci.

Sastavljanje

Ovo poglavlje opisuje završne korake procesa instalacije, koji uključuju zapisivanje ISO slike na 1TB SSD i sastavljanje uređaja Raspberry Pi.

Zapisivanje ISO slike

Da biste zapisali ISO sliku na SSD, možete koristiti naredbu dd na Linuxu ili program kao što je Rufus na Windowsu.

Linux

Na Linuxu možete koristiti naredbu dd za zapisivanje ISO slike na SSD. Prvo, identificirajte put uređaja SSD-a pokretanjem naredbe lsblk. Kada dobijete put uređaja, možete zapisati ISO sliku sljedećom naredbom:

sudo dd if=<iso> of=<device> bs=4M status=progress && sync

Zamijenite <iso> s putanjom do ISO slike i <device> s putanjom uređaja SSD-a. Ova naredba zapisuje ISO sliku na SSD blok po blok i prikazuje informacije o napretku. Naredba sync se koristi za osiguranje da su svi podaci ispravno zapisani na uređaj.

Windows

Na Windowsu možete koristiti program kao što je Rufus za zapisivanje ISO slike na SSD. Evo koraka:

  1. Preuzmite i instalirajte Rufus s službene web stranice.
  2. Priključite SSD u USB port vašeg računala.
  3. Otvorite Rufus i odaberite SSD u padajućem izborniku 'Device'.
  4. U padajućem izborniku 'Boot selection' odaberite 'Disk or ISO image' i kliknite gumb 'Select' kako biste odabrali vaš ISO file.
  5. Kliknite 'Start' za početak procesa. Rufus će formatirati SSD i zapisati ISO sliku na njega. Imajte na umu da će svi postojeći podaci na SSD-u biti izbrisani.

Sastavljanje uređaja

Nakon zapisivanja ISO slike na SSD, možete sastaviti uređaj Raspberry Pi.

Odspojite SSD s računala. Priključite SSD u USB port Raspberry Pi-a. Priključite USB-C kabel za napajanje kako biste uključili Raspberry Pi. Uređaj bi sada trebao podići sustav s SSD-a i pokrenuti pidgeon.

Umetanje tajnog ključa

Pomoću naredbe:

./inject <iso> <key>

ova skripta umeće tajni ključ u ISO sliku za specifični uređaj Raspberry Pi koristeći skriptu inject iz repozitorija.

Preduvjeti

Prije nego što započnete, provjerite jeste li generirali ISO sliku za uređaj koristeći skriptu image. Skripta inject zahtijeva ISO sliku i datoteku s tajnim ključem.

Upotreba

Skripta inject uzima dva argumenta: iso, koji je put do ISO slike, i key, koji je put do datoteke s tajnim ključem. Skripta provjerava postoje li te datoteke. Ako ne postoje, izlazi s porukom o pogrešci.

Ovo je važno jer želimo da skripte koriste programi na uređaju koristeći nix, što zahtijeva da tajni ključevi budu šifrirani u repozitoriju i dešifrirani na uređaju prilikom pokretanja.

Okruženje

Što se tiče razvojnog okruženja potrebno je opisati razvojne ovisnosti i razvojni proces. Ove ovisnosti su potrebne za izvršavanje naredbi definiranih u justfile koji opisuje razvojni proces pobliže.

Ovisnosti

  • Rust: Projekt koristi Rust, a naredba cargo se koristi za izgradnju, testiranje i pokretanje Rust koda. Također se koristi za generiranje dokumentacije i formatiranje Rust koda.
  • Docker: Docker se koristi za upravljanje uslugama o kojima aplikacija ovisi. Naredba docker compose up -d se koristi za pokretanje tih usluga, a docker compose down -v se koristi za njihovo zaustavljanje.

Opcionalne ovisnosti

Sljedeći alati su opcionalni za neke razvojne procese, ali se preporučuju za razvoj:

Probe

  • Python: Python se koristi za probe skriptu. Trebate imati instaliran Python kako biste pokrenuli ovu skriptu.
  • Poetry: Poetry se koristi za upravljanje Python ovisnostima.

Formatiranje

  • Yapf: Yapf se koristi za formatiranje Python koda u projektu.
  • Prettier: Prettier se koristi za formatiranje i provjeru formata koda u projektu.
  • shfmt: shfmt se koristi za formatiranje shell skripti u projektu.

Provjera koda

  • ShellCheck: ShellCheck se koristi za provjeru shell skripti.
  • cspell: cspell se koristi za provjeru pravopisa u projektu.
  • Ruff: Ruff se koristi za provjeru Rust koda u projektu.
  • Clippy: Clippy je Rust linter koji se koristi u projektu.
  • Pyright: Pyright se koristi za provjeru tipova Python koda.

Dokumentacija

  • mdbook: mdbook se koristi za izradu dokumentacije u docs direktoriju.

Stress testiranje

  • GNS3: GNS3 se koristi za simuliranje mreže.

Razvojni proces

Razvojni proces upravlja se pomoću just, upravitelja naredbama sličnog make. justfile definira različite naredbe za izgradnju, testiranje, pokretanje i upravljanje projektom.

Evo koraka za postavljanje razvojnog okruženja i korištenje just:

  1. Instalirajte ovisnosti: Instalirajte sve potrebne alate navedene u ovom poglavlju.

  2. Pripremite okruženje: Pokrenite just prepare za instalaciju Python ovisnosti, pokretanje Docker usluga i pokretanje migracija baze podataka.

  3. Pokrenite aplikaciju: Koristite just run za pokretanje aplikacije. Možete proslijediti argumente aplikaciji dodavanjem uz naredbu, poput just run --arg.

  4. Pokrenite Probe skriptu: Koristite just probe za pokretanje probe skripte. Možete proslijediti argumente skripti na isti način kao i za run naredbu.

  5. Formatirajte kod: Koristite just format za formatiranje koda u projektu pomoću raznih formatera.

  6. Provjerite kod: Koristite just lint za provjeru koda u projektu pomoću raznih lint alata.

  7. Testirajte kod: Koristite just test za pokretanje testova za projekt.

  8. Izgradite projekt: Koristite just build za izgradnju projekta. Ovo će stvoriti release build projekta i premjestiti rezultat u artifacts direktorij.

  9. Generirajte dokumentaciju: Koristite just docs za generiranje dokumentacije projekta. Ovo će izgraditi dokumentaciju i premjestiti rezultat u artifacts direktorij.

Zapamtite da pokrenete just prepare svaki put kada povučete nove promjene iz repozitorija kako biste osigurali da je vaše okruženje ažurirano.

Database

Testiranje

Ovaj odjeljak je posvećen testiranju.

Unit testovi nisu dokumentirani na wiki jer su previše detaljni, ali neki E2E testovi koji su vitalni za projekt su dokumentirani ovdje.

Push

Prema arhitekturi, s gledišta Pidgeona, postoje višestruke točke s kojih mogu nastati greške. Počevši od gatewaya pa sve do servera, možemo očekivati greške u sljedećim područjima:

  • Gateway -> Pidgeon: Gatewayi su odgovorni za prijenos mjerenja s mjerača na Pidgeon putem pull mehanizma. Postoji mali milijun načina na koji bi ovo moglo poći po zlu, ali s gledišta Pidgeona, relevantne su samo dvije kategorije scenarija: gateway ne šalje podatke ili gateway šalje netočne podatke.

  • Pidgeon: Pidgeon sam po sebi može prestati raditi ili imati grešku koja uzrokuje prestanak povlačenja podataka s gatewaya.

  • Pidgeon -> Server: Pidgeon šalje mjerenja na server. Ako je server isključen ili nema veze sa serverom ili postoje problemi s zahtjevima, server neće moći pohraniti podatke.

Greške

Evo popisa grešaka koje se mogu dogoditi u push procesu podijeljenih po područjima:

  • Gateway -> Pidgeon:

    • Gateway ne šalje podatke
    • Gateway šalje netočne podatke
  • Pidgeon:

    • Pidgeon nije povezan na mrežu
    • Pidgeon baca iznimku (softverska greška)
  • Pidgeon -> Server:

    • Server nije povezan na mrežu
    • Server baca iznimku (softverska greška)

Testiranje

Za testiranje otpornosti u push procesu, možemo simulirati greške na sljedeće načine:

  • Gateway ne šalje podatke: Isključite gateway i ponovno ga uključite. Pidgeon ne bi trebao biti pogođen.

  • Gateway šalje netočne podatke: Promijenite podatke koje gateway šalje. Pidgeon bi trebao biti sposoban otkriti netočne podatke i ignorirati ih.

  • Pidgeon nije povezan na mrežu: Isključite Pidgeon s mreže i ponovno ga spojite. Pidgeon bi trebao moći otkriti mrežni kvar i pokušati ponovno poslati podatke.

  • Pidgeon baca iznimku: Uvedite grešku u Pidgeon koja uzrokuje da baci iznimku. Pidgeon bi trebao biti sposoban uhvatiti iznimku, zabilježiti je i nastaviti raditi.

  • Server nije povezan na mrežu: Isključite server s mreže i ponovno ga spojite. Pidgeon bi trebao moći otkriti mrežni kvar i pokušati ponovno poslati podatke.

  • Server baca iznimku: Uvedite grešku u server koja uzrokuje da baci iznimku. Pidgeon bi trebao biti sposoban uhvatiti iznimku, zabilježiti je i nastaviti raditi.