Sistem integrat de monitorizare și prevenție a situațiilor de urgență [622612]
Universitatea “Politehnica” din București
Facultatea de Electronică, Telecomunicații și Tehnologia Informației
Sistem integrat de monitorizare și prevenție a situațiilor de urgență
folosind tehnologia LoRa
Proiect de diplomă
prezentat ca cerință parția lă pentru obținerea titlulu i de
Inginer în domeniul Inginerie electronică, telecomunicații și tehnologii
informaționale
programul de studii de licență Electronică Aplicată
Conducător științific Absolvent
Ș. L. Dr. Ing. Mădălin FRUNZETE Mihai -Valentin BĂ NICĂ
Anul 2019
CUPRINS
LISTA FIGURILOR ………………………….. ………………………….. ………………………….. ………………………….. . 9
LISTA TABELELOR ………………………….. ………………………….. ………………………….. ……………………….. 11
INTRODUCERE ………………………….. ………………………….. ………………………….. ………………………….. …. 13
MOTIVAȚIA LUCRĂRII ………………………….. ………………………….. ………………………….. …………………. 14
CAPITOLUL 1 – TEHNOLOGIILE UTILIZATE ÎN REALIZAREA PROIECTULUI …………………. 15
1.1 Internet of Things ………………………….. ………………………….. ………………………….. …………………….. 15
1.2 Tehnologia LoRa ………………………….. ………………………….. ………………………….. …………………….. 17
1.2.1 LPWAN ………………………….. ………………………….. ………………………….. ………………………….. . 17
1.2.2 Modulația LoRa ………………………….. ………………………….. ………………………….. ………………… 19
1.2.3 Protocolul LoRaWAN ………………………….. ………………………….. ………………………….. ……….. 20
1.3 The Things Network ………………………….. ………………………….. ………………………….. ………………… 22
1.3.1 Securitatea LoRaWAN ………………………….. ………………………….. ………………………….. ………. 22
1.3.2 Spațiul de adresă LoRaWAN ………………………….. ………………………….. ………………………….. . 23
1.3.3 Ciclul de funcționare al dispozitivelor LoRaWAN ………………………….. …………………………. 24
1.3.4 Limitările protocolului LoRaWAN ………………………….. ………………………….. …………………… 25
CAPITOLUL 2 – DESCRIEREA COMPONENTELOR HARDWARE ………………………….. ………….. 27
2.1 Placa de dezvoltare Raspberry Pi 3 Model B+ ………………………….. ………………………….. …………. 27
2.2 Raspberry Pi LoRa/GPS HAT ………………………….. ………………………….. ………………………….. …… 28
2.3 Modulul SX1276 ………………………….. ………………………….. ………………………….. ……………………… 30
2.4 Placa de dezvoltare Arduino ………………………….. ………………………….. ………………………….. ……… 30
2.5 Dragino LoRa Shield pentru Arduino ………………………….. ………………………….. ……………………… 32
2.6 Senzori ambientali utilizați ………………………….. ………………………….. ………………………….. ……….. 33
CAPITOLUL 3 – REALIZAREA PRACTICĂ A SISTEMULUI ………………………….. ……………………. 37
3.1 Schema Bloc ………………………….. ………………………….. ………………………….. ………………………….. . 37
3.2 Descrierea funcționalității sistemului ………………………….. ………………………….. ……………………… 38
3.3 Integrarea proiectului practic într -o aplicație TTN ………………………….. ………………………….. ……. 38
3.4 Realizarea nodurilor de trasmisie ………………………….. ………………………….. ………………………….. .. 40
3.4.1 Schema electri că a unui nod ………………………….. ………………………….. ………………………….. .. 40
3.4.2 Mediul de dezvoltare integrat Arduino ………………………….. ………………………….. ……………… 42
3.4.3 Biblioteca Arduino -LMIC ………………………….. ………………………….. ………………………….. ….. 43
3.4.4 Programarea nodurilor ………………………….. ………………………….. ………………………….. ……….. 45
3.5 Realizarea stației de bază ………………………….. ………………………….. ………………………….. ………….. 48
CAPITOLUL 4 – APLICAȚIA WEB ȘI INTERACȚIUNEA CU UTILIZATORUL …………………….. 53
4.1 Tehnologiile software folosite ………………………….. ………………………….. ………………………….. …… 53
4.1.1 Limbajul JavaScript ………………………….. ………………………….. ………………………….. …………… 53
4.1.2 Node.js ………………………….. ………………………….. ………………………….. ………………………….. … 54
4.1.3 Framework -ul Express ………………………….. ………………………….. ………………………….. ……….. 55
4.1.4 Protocolul HTTP ………………………….. ………………………….. ………………………….. ……………….. 55
4.1.5 Stilul Arhitectural – REST ………………………….. ………………………….. ………………………….. ….. 57
4.1.6 MongoDB ………………………….. ………………………….. ………………………….. ………………………… 57
4.1.7 Modelul Arhitectural Model -View -Contro ller ………………………….. ………………………….. …… 58
4.1.8 HTML ………………………….. ………………………….. ………………………….. ………………………….. …. 59
4.1.9 CSS ………………………….. ………………………….. ………………………….. ………………………….. …….. 59
4.1.10 EJS – Embedded Javascript Templates ………………………….. ………………………….. ……………. 60
4.2 Descrierea aplicației dezvoltate ………………………….. ………………………….. ………………………….. …. 61
4.2.1 Configurarea inițială ………………………….. ………………………….. ………………………….. ………….. 61
4.2.2 Recepționarea datelor din TTN via protocolul HTTP ………………………….. ……………………… 62
4.2.3 Integrarea bazei de date MongoDB ………………………….. ………………………….. ………………….. 63
4.2.4 Afișarea datelor folosind Șablonul EJS ………………………….. ………………………….. …………….. 64
4.2.5 Integrarea graficelor în aplicație ………………………….. ………………………….. ………………………. 65
4.3 In teracțiunea cu utilizatorul ………………………….. ………………………….. ………………………….. ………. 66
REZULTATE ………………………….. ………………………….. ………………………….. ………………………….. ……… 71
CONCLUZII ȘI PERSPECTIVE ………………………….. ………………………….. ………………………….. ……….. 72
BIBLIOGRAFIE ………………………….. ………………………….. ………………………….. ………………………….. ….. 73
ANEXA 1 – Codul sursă pentru transmiterea pachetului de date de la nodul 1, folosind tehnologia
LoRa ………………………….. ………………………….. ………………………….. ………………………….. …………………… 75
ANEXA 2 – Codurile sursă ale aplicației Web ………………………….. ………………………….. ………………….. 79
ANEXA 3 – Codul sursă pentru gateway (stația de bază) ………………………….. ………………………….. …. 101
LISTA FIGURILOR
Figura 1. 1 Ecosistemul IoT [2] ………………………….. ………………………….. ………………………….. ………….. 15
Figura 1. 2 Predicția numărului de dispozitive conectate prin IoT [3] ………………………….. ………………. 16
Figura 1. 3 Arhitectura de bază IoT [5] ………………………….. ………………………….. ………………………….. .. 17
Figura 1. 4 Rețea tipică LPWAN [6] ………………………….. ………………………….. ………………………….. …… 18
Figura 1. 5 Ferestrele de recepție pentru dispozitivele de clasă A [6] ………………………….. ……………….. 19
Figura 1. 6 Arhitectura TTN [8] ………………………….. ………………………….. ………………………….. …………. 22
Figura 1. 7 Securitatea LoRaWAN [9] ………………………….. ………………………….. ………………………….. … 23
Figura 1. 8 Ciclu de funcționare – single channel [8] ………………………….. ………………………….. …………. 24
Figura 1. 9 Ciclu de funcționare – multiple channels [8] ………………………….. ………………………….. ……. 24
Figura 1. 10 Ciclu de funcționare – multi -band [8] ………………………….. ………………………….. ……………. 25
Figura 1. 11 Compromisul pentru comunicațiile fără fir [10] ………………………….. ………………………….. 26
Figura 2. 1 Structura unui Raspberry Pi Model 3 [11] ………………………….. ………………………….. ……….. 28
Figura 2. 2 Raspberry Pi LoRa/GPS HAT [12] ………………………….. ………………………….. ………………… 29
Figura 2. 3 Diagrama bloc a SX1276 [13] ………………………….. ………………………….. ………………………… 30
Figura 2 . 4 Structura plăcii de dezvoltare Arduino Uno [14] ………………………….. ………………………….. . 31
Figura 2. 5 Shield Dragino LoRa compatibil Arduino [15] ………………………….. ………………………….. …. 32
Figura 2. 6 Senzor de temperatură și umiditate DHT11 ………………………….. ………………………….. ……… 33
Figura 2. 7 Senzor ultrasonic HC -SR04 ………………………….. ………………………….. ………………………….. . 35
Figura 2. 8 Senzor de nivel al apei ………………………….. ………………………….. ………………………….. ………. 36
Figura 3. 1 Schema bloc a sistemului ………………………….. ………………………….. ………………………….. ….. 37
Figura 3. 2 Consola aplicației TTN ………………………….. ………………………….. ………………………….. ……… 39
Figura 3. 3 Schema ele ctrică a unui nod LoRa ………………………….. ………………………….. ………………….. 40
Figura 3. 4 Nod LoRa fizic ………………………….. ………………………….. ………………………….. ………………… 41
Figura 3. 5 Configurarea nodului LoRa în TTN ………………………….. ………………………….. ………………… 42
Figura 3. 6 Mapare pinilor pe shield -ul Dragino LoRa ………………………….. ………………………….. ………. 44
Figura 3. 7 Definirea cheilor de acces și adresa dizpozitivului ………………………….. ………………………… 45
Figura 3. 8 Definirea intervalului de transmisiune ………………………….. ………………………….. …………….. 45
Figura 3. 9 Inițializare LMIC ………………………….. ………………………….. ………………………….. ……………… 45
Figura 3. 10 Păstrarea unui singur canal de frecvență ………………………….. ………………………….. ………… 46
Figura 3. 11 Apelarea funcțiilor de citire a datelor de la senzori ………………………….. ………………………. 46
Figura 3. 12 Funcțiile de citire a datelor de la senzori ………………………….. ………………………….. ………… 46
Figura 3. 13 Transmiterea payload -ului către gateway ………………………….. ………………………….. ……….. 47
Figura 3. 14 Decodare payload forma hexaze cimală ………………………….. ………………………….. ………….. 47
Figura 3. 15 Conectare la Raspberry Pi prin VNC ………………………….. ………………………….. …………….. 49
Figura 3. 16 Activare interfață serială pe Raspberry Pi ………………………….. ………………………….. ………. 49
Figura 3. 17 Configurea stației de bază implementată pe Raspberry Pi ………………………….. …………….. 50
Figura 3. 18 Funcționarea Gateway -ului ………………………….. ………………………….. ………………………….. 51
Figura 3. 19 Consolă Gateway ………………………….. ………………………….. ………………………….. ……………. 52
Figura 3. 20 Traficul recepționat de Gateway ………………………….. ………………………….. …………………… 52
Figura 4. 1 Cerere și răspuns în protocolul HTTP [26] ………………………….. ………………………….. ………. 56
Figura 4. 2 Cererile HTTP [25] ………………………….. ………………………….. ………………………….. …………… 56
Figura 4. 3 Modelul Structural Model -View -Controller[30] ………………………….. ………………………….. .. 58
Figura 4. 4 Configurarea aplicației web ………………………….. ………………………….. ………………………….. .. 61
Figura 4. 5 Inițializare server web ………………………….. ………………………….. ………………………….. ………. 62
Figura 4. 6 Lansarea aplicației și configurarea portului ………………………….. ………………………….. ……… 62
Figura 4. 7 Recepționarea datelor din TTN via HTTP ………………………….. ………………………….. ……….. 63
Figura 4. 8 Conexiunea la MongoDB ………………………….. ………………………….. ………………………….. ….. 63
Figura 4. 9 Declarea schemei în MongoDB ………………………….. ………………………….. ………………………. 64
Figura 4. 10 Stocarea unui pachet complet în baza de date ………………………….. ………………………….. …. 64
Figura 4. 11 Listarea documentelor utilizând metoda GET ………………………….. ………………………….. …. 64
Figura 4. 12 Randarea variabilelor în interfața WEB ………………………….. ………………………….. …………. 65
Figura 4. 13 Integrarea codului EJS în HTML ………………………….. ………………………….. ………………….. 65
Figura 4. 14 Trasarea graficului folosind Plotly.JS ………………………….. ………………………….. ……………. 66
Figura 4. 15 Pagina principală a aplicației web ………………………….. ………………………….. …………………. 67
Figura 4. 16 Istoricul Nodului 1 ………………………….. ………………………….. ………………………….. ………….. 68
Figura 4. 17 Exemplu de grafic implementat în aplicație ………………………….. ………………………….. ……. 69
Figura 4. 18 Alertă în caz de urgență ………………………….. ………………………….. ………………………….. …… 70
Figura 4. 19 Descrierea proiectului în aplicația web ………………………….. ………………………….. ………….. 70
LISTA TABELELOR
Tabel 1. 1 Setările LoRaWAN privind ratele datelor și factorul de împrăștiere [6] …………………………. 20
Tabel 1. 2 Reglementările privind și canalele LoRaWAN în banda UE 863 -873 MHz [6] ………………. 21
Tabel 1. 3 Cantitatea maximă de date pentru un canal LoRaWAN și un nod [6] ………………………….. .. 21
LISTA ACRONIMELOR
IoT – Internet of Things
LPWAN – Low-Power Wide -Area Network
LoRa – Long Range
WAN – Wide Area Network
LTE – Long -Term Evolution
BLE – Bluetooth Low Energy
ED – End Device
BS – Base Station
SF – Sprea ding Factor
ToA – Time on Air
IP – Internet Protocol
CCA – Clear Channel Assessment
TTN – The Things Network
OTAA – Over -the-Air Activation
ABP – Activation by Personalization
GPRS – General Packet Radio Service
JSON – JavaScript Object Notation
BW- Bandwi dth
ADR – Adaptive Data R ate
PC – Personal Computer
GPS – Global Positioning System
IDE – Integrated Development Environment
USB – Universal Serial Bus
NTC – Negative Temperature Coefficient
WEB – World Wide Web
API – Application Programming Interface
SDK – Software Development Ki t
AES – Advanced Encryption Standard
VNC – Virtual Network Computing
HTTP – Hypertext Transfer Protocol
REST – Representational State Transfer
MVC – Model -View -Controller
HTML – HyperText Markup Language
CSS – Cascading Style Sheet s
EJS – Embedded Javascri pt
13
INTRODUCERE
Lucrarea de față descrie crearea unui sistem integrat de monitorizarea și prevenție a situațiilor de
urgență folosind tehnologia LoRa. Acest sistem poate fi implementat în diverse arii ce țin de pericole
datora te dezastrelor naturale ș i nu numai, exemple ar fi : preven ția inundațiilor, atenționarea si prevenția
în cazul posibilelor incendii, situații ce țin de contaminarea aerului și lista poate continua.
Sistemul va fi alcătuit dintr -o rețea propriu -zisă, cât și o interfață sub forma unei pagini WEB,
aceasta fiind in teracțiunea cu utilizatorul. Rețeaua va fi compusă din noduri LoRa, cât și un gateway la
care se vor conecta și vor transmite date nodurile aferente . De asemenea, aceste date pot fi monitorizate
oricând folosind interfața c reată.
Structura acestei lucrări este o rganizată după cum urmează:
Capitolul 1 prezintă o descriere generală a tehnologiilor utilizate pentru realizarea proiectului.
În acest capitol sunt tratate conceptele generale privind o var ietate de tehnologii util izate , ce țin în special
de comunicația între diverse dispozitive , cum ar fi Internet of Things, tehnologia LoRa și The Things
Network.
Capitolul 2 va prezenta o descriere a componentelor hardware utilizate în realizarea acestui
proiect, de la plăcile de dezvoltare până la senzor ii utilizați.
Capitolul 3 își propune descrierea proiectării sistemului precum realizarea nodurilor de
transmisie, a gateway -ului, implicit a rețelei complete de comunicație . De asemenea se vor prezenta
constrângerile și soluțiil e pentru rezolvarea proble melor.
Capitolul 4 va descrie aplicația web dezvoltată atât pe partea de backend, cât și frontend, și
implicit interacțiunea cu utilizatorul. În prima parte se va realiza o scurtă descriere a tehnologiil or
software utilizate, ur mată de descrierea aplicaț iei dezvoltate și în final scenariile ce țin de interacțiunea
cu utilizatorul.
14
MOTIVAȚIA LUCRĂRII
Motivația ce a stat la bază în realizarea acest proiect vine în primul rând din dorința de a crea o
aplicație utilă s ocietății în sensul în care sistemele de monitorizare și prevenție pot fi folosite în diferite
arii, de la zone izolate unde este nevoie de o monitorizare a unor parametrii până la zone cu întindere
mare unde pot fi prevăzute event ualele dezastre naturale și astfel acest proiect chiar poate fi utilizat in
realitate într -un cadru potrivit, ca de exemplu pentru prevenția t impurie a inundațiilor . În repetate rânduri,
istoria ne -a demonstrat că natura cât și omul pot distruge și, ironic , o pot face cu o eficien ță mult ridicată.
Situațiile de urgență sunt rare, dar atunci c ând se int âmplă, fac pagube colosale at ât în rândul vie ților
omenesti, c ât și de ordin material prin potențialele lor distructive.
Gestionarea situațiilor de urgență a devenit un subiect de ce rcetare în ultimele decenii.
Managementul de urgență poate fi definit ca o disciplină care să aibă ca prim scop evitarea unor astfel
de sit uații critice, în care astfel de situații reprezintă o gamă largă de probleme, inclusiv deza strele
menținonate anteri or. Abordarea științifică a gestionării situațiilor de urgență are un rol extrem de
important. Pentru a îmbunătăți st andardizarea și automa tizarea situațiilor critice , o nouă metodă de
management al situațiilor de urgență bazată pe o rețea LoRaWAN este pre zentată în această lucrare.
În al doilea rând motivația vine din dorința de a acumula cât mai multe cunoștințe despre
tehnologiile de actu alitate care prezintă un interes major , precum LoRa , și de a le pune în funcțiune pentru
a forma un sistem ușor de ut ilizat. Prin soluția ce urmează să o propun urmăresc realizarea unui sistem
integrat cu o aplicație propriu -zisă care mai apoi poate fi adaptat în funcție de cerințele care apar.
15
CAPITOLUL 1 – TEHNOLOGIILE UTILIZATE Î N
REALIZAREA PROIECTULUI
Capitolul 1 își propune prezentarea informațiilor generale ale tehnologiilor utilizate în realizarea
acestui proiect.
1.1 Internet of Things
Prin conceptul de Internet of Things (I oT) înțelegem conectarea mai multor dispozi tive la Internet
și folos ind această conexiune putem furniza un sistem de monit orizare sau control al acestor dispozitive.
IoT creează o rețea inteligentă, invizibilă care poate fi controlată și programată. Produsele pregătite
pentru Internet of Things fol osesc tehnologii integrat e care le permit să comunice direct sau indirect între
ele sau cu Internetul. [1]
Figura 1. 1 Ecosistemul Io T [2]
Se așteaptă ca IoT să tran sfome mediul în care trăim și lucrăm. De la automatizarea fabricilor și
conectivit atea între automobile la senzori corporali și aparate electrocasnice , Iot este pregătit să facă parte
din fiecare aspect al vieții noastre. Rețelele din jurul nostru se vor schimba constant și vor evolua în
funcție de mediul înconj urător și din datele din alte sistem e. Totodată, scopul acestei tehnologii este de
a ne face viața mai sigură. [1]
16
Având în vedere cererea din piață si ritmul de expansiune al IoT putem spune că în viitor va fi
principalul concept în jurul căruia se vor co nstrui noile echipamente electronice , după cum se poate
observa în Figura 1.2. Se estimează că in 202 5 vor exista 75 de miliarde de dispozitive conectate .
Figura 1. 2 Predicția numărului de dispozitive conectate prin IoT [3]
Există o gamă largă de tehnologii disponibile pentru IoT, cum ar fi cele tradiționale celulare
(2G/3G/4G), rețelele cu o arie largă de putere redusă (LPWAN), WiFi, Bluetooth și multe altele. Fiecare
caz de aplicare are nevoi specifice, ceea ce se traduc e în anumite cerințe tehn ologice car e determină
alegerea celei mai potrivite tehnologii.
Pentru implementare IoT în zone îndepărtate, cu un control de la distanță, LoRa , NB-IoT și LTE –
M sunt soluții bune și împreună vor aborda o marea parte din această pi ață. Ecosistemul dinamic deschis
al sistemului LoRa este ideal pentru rețelele private cu implementare personalizată, în timp ce rețelel e
NB-IoT și LTE -M sunt susținute d e operatori majori care oferă o conectivitate standardizată cu acoperire
globală.
Alte tehnologii complementa re, cum ar fi Sigfox, se pot adresa unor anumite segmente de nișă,
dar fiabilitatea lor trebuie testată în timp. Pentru aplicațiile care necesită o viteză ridicată de transfer a
datelor, cele mai potrivite opțiuni tehnologice sunt fie LTE, WiFi sau BLE, în funcție de domeniul de
aplicare al implementărilor IoT.
Pentru aplicațiile care necesită o rază mică de acoperire, alegerea tehnologică este ma i puțin
evidentă și adesea interfața și punerea în aplicare a platformei devin mai imp ortante. Începând cu anul
2020, rețelele 5G vor începe, de asemenea, să fie disponibile în comerț, oferind capabilități îmbunătățite
pentru a aborda atât cazuri de utiliz are a comunicației masive, cât și critice. [4]
Arhitectura de bază a IoT este exprima tă în Figura 1.3.
17
Figura 1. 3 Arhitectura de bază IoT [5]
1.2 Tehnologia LoRa
1.2.1 LPWAN
Rețelele cu o arie largă de putere redusă (LPWAN) reprezintă o nouă tendință în evoluția
tehnologiilor de comunicații fără fir. S pre deosebire de banda la rgă tradițională, aceste sisteme nu se
concentrează pe transmiterea unei rate ridicate a datelor pe dispozitiv. În schimb, perform anțele cheie ale
acestor sisteme sunt eficiența energetică, scalabilitatea și acoperirea.
LPWAN -urile de astăzi sunt în mod o bișnuit văzute ca rețele celulare co mpuse din dispozitive
finale (ED) și stațiile de bază (BS). Dispozitivele finale sunt conectat e și asociate cu stațiile de bază,
formând astfel o rețea cu o tipologie de tip stea cum este ilustra t în Figura 1. 4. De obice i, un dispozitiv
final comunică numai cu stația de bază, și nu cu alte dispozitive. Spre deosebire de rețelele celulare
tradiționa le pentru care cantitatea de trafic de tip downlink o depășește pe cea de tip uplink, pentru
LPWAN -uri traficul uplink este do minant.
18
Figura 1. 4 Rețea tipică LPWAN [6]
În ziua de astăzi există mai multe tehnologii LPWAN co ncurente pe piață. Prima opțiune este
banda ultra -îngustă Sigfox care funcționează în banda radio de 868/902 Mhz (ISM), fără a fi nevoie de
licență. Compan ia acționează atât ca tehnologie, cât și ca furnizor de servicii implementând deja prin
Europa stații de bază. Cea de -a doua opțiune este LoRa care se bazează pe tehnica de spectru larg, cât și
pe modul ația GFSK (FSK Gaussian). [6]
Cele trei provocări tipice majore pentru LPWAN -uri sunt:
• Dispozitivele finale trebuie să fie ieftine ;
• Dispozitivele finale trebuie să aibă o durată de viață de până la 10 ani dac ă sunt alimentate de o
baterie (~2500 mAh) ;
• Distanța dintre stațiile de b ază și noduri (dispozitive fi nale) să depășească 10 km .
Dintre aceste obiective, probabil primele două sun t cel mai ușor de atins. Prezența unei stații de
bază staționare permite o mișcare a întregii complexități spre partea sa, f ăcând astfel nodurile suf icient
de simple și ieftine în producția de masă. Timpul de viață de zece ani poate fi atins prin limitarea
numărului de mesaje trimise de fiecare nod pe zi, deși acest lucru limitează în mod natural domeniul de
aplicații.
Prin urm are, ne vom concentra asu pra celei de a treia probleme, și anume asupra ariei de
acoperire. Pentru aceasta lucrare am ales tehnologi a LoRa. [7]
19
1.2.2 Modula ția LoRa
Din punct de vedere tehnic, soluția LPWAN LoRa include 2 componente majore. Prima
componentă este modula ția LoRa, care se bazează pe schema de spectru împraștiat care utilizează
impulsuri modulate de frecvență de bandă largă a căror frecvență crește sau scade pe baza informațiilor
codificate. Utilizarea semnalelor cu un produs bandă -timp mare (BT>1) ar trebu i să facă semnalele radio
rezistente atât interferențelor în bandă, cât și în afara benzii. Aces tip de modulație ajută pentru
propagarea în special în mediile urbane.
Ca rezultat, puterea maximă pentru LoRa care funcționează în Euro pa pe frecevența de 868 M hz
poate depăși 150 dB, permițând astfel obținerea unor distanțe mari de comunicare sau reducerea puterii
de transmisie, economisind astfel energie nodurilor. În cele din urmă, schema de modulare utilizată se
așteaptă a fi robustă împotriva efectului Doppl er, îmbunătățind astfel performața comunicării cu obiectele
mobile. În plus, modula ția LoRa include o schemă de corectare ciclică de eroare variabilă, care
îmbunătățește comunicarea prin adăugarea unor redundanțe.
Pentru a îmbunătă ți eficiența spec trală și a spori capacitatea rețelei, modulația LoRa prezintă șase
factori de împrăștiere (SF), rezultând diferite rate ale datelor, cum sunt prezentate în Tabelul 1. 1.
Aceasta permite transmiterea în același timp a mai multor semnale pe a celași canal de frecvență fără a
degrada performațele comunicației și a lua în considerare timpul în aer al semnalului (ToA) . [6]
Versiunea 1.0 a LoRaWAN definește trei clase de dispozitive finale numite A, B și C.
Implementarea funcționalității de clasă A este obligatorie, în t imp ce clasele B și C sunt opționale. Pentru
dispozitivele finale de clasă A, fiecare transmisie de „uplink” este urmată de două ferestre de recepție
(RX1 și RX2) așa cum este prezentat în figura 1.5. Oricare dintre aceste ferestre pot fi utilizate de staț ia
de bază pentru transferul datelor către dispozitivele finale. Ferestrele de recepție pot avea canalul de
frecvență și factorul de împrăștiere diferite de cele utilizate pentru transmiterea pachetului „uplink”. În
cazul în care d ispozitivul final primeșt e un răspuns în RX1, RX2 poate fi omis .
Figura 1. 5 Ferestrele de recepție pentru dispozitivele de clasă A [6]
Dispozitivele din clasa B, pe lângă RX1 și RX2, au de asemenea ferestre speciale de rec epție la
intervale de tim p programate. Pentru menținerea sincronzizării și furnizarea secvenței de timpla
dispozitivele finale, stația de bază transmite periodic semnale. În cele din urmă, dispozitivele finale de
clasa C rămân în starea de recepție aproape tot timp ul. În cazul pro iectului nostru, ne -am concentrat pe
dispozitivele finale de clasa A. [6]
20
Tabel 1. 1 Setările LoRaWAN privind ratele datelor și factorul de împrăștiere [ 6]
1.2.3 Protocolul LoRaWAN
A doua componentă a LPWAN este protocolul de rețea LoRaWAN, care est e optimizat în mod
special pentru dispozitive finale cu un consum redus de energie. Dupa cum s -a specificat mai devreme,
LPWAN are în mod o bișnuit o tipologie de tip stea și constă din stații de bază care transmit mesaje între
noduri și un server, implicit o aplicație. Stațiile de bază pot fi conectate la serverul central prin
intermediul pro tocolului internet (IP), iar comunicația fără fir b azată pe modulație LoRa sau GFSK este
utilizată pentru transferul de date între noduri și stațiile de bază. Comunicația este distribuită pe diferite
canale de frecvență sub -GHz (433 și/sau 780/868/915 MHz) , în func ție de reglementările locale.
Fiecare nod poate începe să transmită datele sale în orice moment de timp utilizând orice rată de
date disponibilă, cu excepția cazului în care stația de bază specifică instrucțiuni speciale. De reținut este
faptul c ă protocolul LoRaWAN nu utilizează mecan isme de eva luare clară a canalalelor (CCA) și se
bazează exclusiv pe mecanismul de acces al canalelor bazate pe ciclul de funcționare al nodurilor. Pentru
aceasta, fiecare nod urmărește timpul petrecut pentru a trans mite în fiecare canal de frecvență și împiedică
transmisia în acest canal dac ă sunt impuse restricții. Nodul selectează canalul de frecvență utilizat în mod
pseudo -aleator pentru fiecare pachet care urmează să fie transmis.
Un factor important care limite ază performanțele LoRaWAN este reprezentat de restr icțiile
impuse de reglementările privind frecvența. Din moment ce LoRaWAN nu utilizează CCA, trebuie să
facă față restricțiilor privin d ciclul de funcționare . Canalele și resctricțiile bazate pe reglementă rile
Uniunii Europene sun t rezumate în Tabelul 1.2. În plus, tabelul oferă o estimare a numărului total de
canale de fiecare tip disponibile pentru LoRaWAN. [6]
Data
rate
(DR) SF Band
width,
kHz Modu-
lation Maxim um
MACPayload
size, bytes Maximum
FRMP ayload
size, bytes Shortest
downlink
frame ToA, s Longest
downl ink
frame ToA, s Shortest
uplink frame
ToA, s Longest
uplink frame
ToA, s
0 12 125 LoRa 59 51 0.991 2.793 1.155 2.793
1 11 125 LoRa 59 51 0.578 1.479 0.578 1.561
2 10 125 LoRa 59 51 0.289 0.698 0.289 0.698
3 9 125 LoRa 123 115 0.144 0.677 0.144 0.677
4 8 125 LoRa 250 242 0.072 0.697 0.082 0.707
5 7 125 LoRa 250 242 0.041 0.394 0.041 0.400
6 7 250 LoRa 250 242 0.021 0.197 0.021 0.200
7 n/a 150 GFSK 250 242 0.0032 0.0421 0.0035 0.0424
21
Frequency band, MHz Duty cycle,
% Maximum
power,
mW ERP LoRa WAN
obligatory
channels, MHz LoRaW AN
join request
channels, MHz Max 125
kHz LoRa
channels Max 250
kHz LoRa
channels Max 150
kHz
GFSK
channels
863–868.6,8 68.7–869.2,869.4 –
869.65,869. 7–870 0.1 25 – 864.1,864.3,864.5 32 19 37
868.0 –868.6 1 25 868.1,868.3,868.5 868.1,868.3,868.5 3 2 4
868.7–869.2 0.1 25 – – 2 1 3
869.4 –869.65 10 500 – – 1 0 1
869.7 –870.0 1 25 – – 1 0 2
870.0 –873.0 1 25 – – 15 10 20
Total 47 29 57
Tabel 1. 2 Reglementările privind și canalele LoRaWAN în banda UE 863 -873 MHz [6]
Cantitățile maxime de date ce po t fi transferat e pentru fiecare canal disponibil și pentru un singur
dispozitiv final pentru diferite valori ale ciclului de funcționare sunt rezumate în Tabelul 1.3.
După transmiterea unui cadru pe un sub -canal, acest sub -canal nu mai poate fi u tilizat pentru următoarele
Toff subband = ToA(1/DutyCycle subband – 1) secunde, unde ToA este timpul petrecut în aer pentru pachetul
transmis și DutyCycle subband este ciclul de funcționare maxim permis, care se regăsește și in Tabelul 1.2
de mai sus. [6]
Data rate
(DR)
Bandwidth,
kHz Maximum APP
throughput per
channel, bit/s Maximum APP throughput per ED per channel,
bit/s
10% duty
cycle
1% duty cycle
0.1% duty cycle
0 125 146.1 14.61 1.46 0.15
1 125 261.4 26.14 2.61 0.26
2 125 584.2 58.42 5.84 0.58
3 125 1 359.2 135.92 13.59 1.36
4 125 2 738.1 273.81 27.38 2.74
5 125 4 844.7 484.47 48.45 4.84
0-5 cumulative 125 9 933.6 n/a n/a n/a
6 250 9 689.3 968.93 96.89 9.69
7 150 45 660.4 1 851.6 456.6 45.66
Tabel 1. 3 Cantitatea maximă de date pentru un canal LoRaWAN și un nod [6]
22
1.3 The Things Network
The Things Network, cunoscută sub numele de TTN, este o infrastructură open source, care
urmărește să asigure o acoperirea gratuită a rețelei LoRaWAN. Acest proiect este dezvoltat de o
comunitate în creștere din întreaga lume și se bazează pe contribuții voluntare la proiect.
Figura 1. 6 Arhitectura TTN [8]
1.3.1 Securitatea LoRaWAN
Protocolul LoRaWAN specifică un număr de chei de se curitate: NwkSKey, AppSKey și AppKey.
Toate aceste c hei au o lungime de 128 de biți.
Cheia sesiunii de rețea (Network Session Key – NwkSKey) este utilizată pentru interacțiunea
dintre nod și serverul de rețea. Aceast ă cheie are rolul de a verifica validita tea mesajelor (verificarea
23
MIC). În rețeaua The Things Network, această validitate este utilizată pentru a mapa o adresă non -unică
a dispozitivului (DevAddr) la un unic DevEUI și AppE UI.
Cheia sesiunii de aplicație (Application Session Key – AppSKey) este utilizată pentru criptarea
și decriptarea pachetului transmis. Pachet ul este complet criptat între nod și aplicația de tip server din
The Things Network (care poate fi rulată pe propr iul server). Aceasta înseamnă că nimeni din afara rețelei
nu poate citi c onținutul mesajelor, atât trimise, cât și recepționate.
Aceste două chei (NwkSKey și AppSKey) sunt unice pentru fiecare dispozitiv, pentru fiecare
sesiune. Dacă un dispoizitiv se act ivează dinamic (OTAA), aceste chei sunt regenerate la fiecare activare.
Daca un dispoitiv este activat static (ABP), aceste chei rămân aceleași pâ nă când se doreste schimbarea
lor. [ 8]
Figura 1. 7 Securitatea LoRaWAN [9]
1.3.2 Spațiul de adresă LoRaWAN
LoRaWAN cunoaște un număr de identificator i pentru dispozitive, aplicații și stații de bază:
• DevEUI – identificator al dispozitivului pe 64 de biți, unic
• DevAddr – adresa dispozitivului pe 32 de biți, non -unic
24
• AppEUI – identificator al aplicației pe 64 de biți, unic
• GatewayEUI – identificator al s tației de bază pe 64 de biți, unic
Dispozitivele LoRaWAN au un identificator unic pe 64 de biți (DevEUI) atribuit dispozitivului
de către producător. Cu toate acestea, toată c omunicația se face cu o adresă dinamică pe 32 de biți a
dispozitivului, din car e 7 biți sunt fixați pentru rețeaua The Things Network, lăsând 25 de biți care pot fi
atribuiți dispozitivelor individuale, procedură numită Activare. Cele două tipuri de activa re sunt
prezentate mai jos.
Activarea în aer (OTAA) este modalitatea preferată și cea mai sigură de conectare la TTN.
Dispozitivele efectu ează o procedură de aderare la rețea, în timpul căreia este alocată o adresă dinamică
DevAddr și cheile de securitate sunt negociate cu dispozitivul.
În unele cazuri, este posibil să se aleagă adre sa dispozitivului, precum și cheile de securitate ale
acestuia. Aceasta înseamnă activarea unui dispozitiv prin personalizare (ABP). Această strategie ar putea
părea mai simplă, dar are unele dezavantaje legate de securitate. [8]
1.3.3 Ciclul de funcționa re al dispozitivelor LoRaWAN
Ciclul de funcționare indică fracțiunea de timp când o resursă este ocupată. Când un singur
dispozitiv transmite pe un canal pentru 2 unități de timp l a fiecare 10 unități de timp, acest dispozitiv are
un ciclu de funcționare de 20%, cum este prezentat si în figura 1. 8 a).
Figura 1. 8 Ciclu de funcționare – single channel [8]
Cu toate acestea, dacă luăm în considerare și canale le de transmisiune, lucrurile devin un pic mai
complicate. Când avem un dispozitiv care transmite pe 3 cananel în loc de unul, fiecare canal individual
este încă ocupat pentru 2 unități de timp, la fiecare 10 unități de timp (deci 20%). Cu toate acestea,
dispozitivul transmite acum 6 unități de timp la fiecare 10 unități de t imp, dâ nd un ciclu de funcționare
de 60%.
Figura 1. 9 Ciclu de funcționare – multiple channels [8]
25
În Europa , avem canale disponibile în diferite sub-benzi, deci atunci când luăm în considerare
ciclul de funcționare, trebuie sa ținem cont de acestea. Să spunem că cele 3 canale pe care le -am folosit
înainte, sunt în 2 sub -benzi diferit e. Fiecare canal separat încă are un ciclu de funcționare de 20%,
respectiv dispozitivul 60%, dar acum observăm ca banda 1 este utilizată pentru 2 unități de tim p la fiecare
10, în timp ce banda 2 este utilizată pentru 4 unități de timp la fiecare 10 (40%) . [8]
Figura 1. 10 Ciclu de funcționare – multi -band [8]
În spațiul european, ciclurile de funcționare sunt regle mentate de secțiunea 7.2 .3. ale standardului
ETSI EN300.220. Acest standard definește următoarele sub -benzi, cu factorul de umplere maxim
disponibil:
• g (863.0 – 868.0 MHz): 1%
• g1 (868.0 – 868.6 MHz): 1%
• g2 (868.7 – 869.2 MHz): 0.1%
• g3 (869.4 – 869.65 MHz): 10%
• g4 (869.7 – 870.0 M Hz): 1%
1.3.4 Limitările protocolului LoRaWAN
LoRaWAN nu este potrivit pentru fiecare caz de utilizare, deci este important sa menționăm
limitările.
Cazuri de utilizare adecvate:
• Rază lungă – mai mulți kilometri
• Putere mică – poate fi alimentat ani d e la o baterie
• Costuri mici – de ordinul zecilor de RON per nod
• Lățime de bandă redusă – între 250 bit/s și 11 kbit/s în Europa utilizănd modulația LoRa
(în funcție de factorul de împrășstiere)
• Acoperire peste tot – în funcție de numărul de stații de bază insta late
• Securitate – criptare de la cap la cap pe 128 de biți :
26
Cazuri nefavorabile pentru LoRaWAN:
• Apeluri telefonice – utilizare tehnologiilor GPRS/3G/LTE este mai potrivită în acest caz
• Controlul dispozitivelor într -un spațiu de ti p SMART – utilizarea Blu eTooth sau ZigBee
este potrivită în acest caz
• Trimiterea unor fișiere mari precum poze/video – adecvată este utilizarea WiFi
• Streaming audio/video – iarăși adecvată este utilizare WiFi
• Date multiple în timp real – în general se poat e trimite un pachet de d ate la câteva minute
Recomandările TTN pentru ca aplicația construită sa fie cât mai eficientă din toate punctele de
vedere, inclusiv consumul de energie, sunt următoarele:
1. Volumul util de date transmise ar trebui să fie cât mai mi c posibil. Aceasta însea mnă că
nu trebuie să trimitem pachetete de tip JSON sau text simplu ASCII, ci să c odificăm datele
ca date binare.
2. Intervalul dintre mesaje ar trebui sa fie la câteva minute. Se poate, de exemplu, să
transmitem un pachet de tipu l min |avg|max la fiecare 5 mi nute, sau să transmitem când
valoarea unui senzor a fost modificată mai mult decât un anumit prag sau dacă a fost
declanșat un eveniment.
3. Rata de transmisie a datelor ar trebui sa fie cât mai rapidă posibil pentru a minimiza timpul
de stat în aer. SF7BW125 este, de obicei, un punct bun de plecare deoarece consumă cea
mai mică putere și are cel mai mic timp de stat în aer. De asemenea, se poate activa o rată
a datelor adaptivă (ADR), astfel încât rețeaua va putea să optimizeze automat rata de
transfer a date lor. [8]
În concluzie, pentru fiecare comunicație fără fir, există un compromis între raza de tranmisie
mare, puterea con sumată redusă și lățimea de bandă. Putem avea doar două dintre acestea, dar este
întodeauna în detrimentul cel ui de -al treilea , cum se poa te observa și în Figura 1. 9.
Figura 1. 11 Compromisul pentru comunicațiile fără fir [ 10]
27
CAPITOLUL 2 – DESCRIEREA COMPONENTELOR
HARDWARE
2.1 Placa de dezvoltare Raspberry Pi 3 Model B+
Raspbe rry Pi este un SBC (Single -Board-Computer) de dimensiunile unui card de credit, produs
in UK de către Raspberry Pi Foundation cu scopul de a promova învățarea noțiunilor de bază din
domeniul informaticii în școli.
Chiar dacă are dimensiuni reduse (85mm x 5 6mm), Raspberry Pi este un ca lculator complet
permițând funcționalități obișnuite precum rularea unu i sistem de operare (Linux sau Windows) ș i rularea
de aplicații utilizator (jocuri, editoare de text, medii de programare, redarea de muzică și filme, aplic ații
de teleconferință, aplic ații Internet).
Diferențele între o placă Raspberry Pi și un calculator personal (PC) sau laptop constau atât în
dimensiunea redusă a plăcii cât și în puterea mai mică de calcul a acesteia – nu are aceleași performanțe
de calc ul precum un PC desktop care are un cost și o dimensiune de câteva ori mai mari. Putem compara
placa Raspberry Pi cu o tabletă sau cu u n sistem de tip NetBook dar fără a dispune de ecran și tastatură.
În plus, placa Raspberry Pi oferă posibilitatea de a co necta diverse componente elec tronice specifice
sistemelor embedded: senzori, butoane, ecrane LCD sau pe 7 segmente, drivere de motoare, relee etc.
Posibilitatea de a personaliza sistemele de programe (sistemul de operare, aplicațiile) și posibilitatea de
interconectare cu alte compone nte electronice fac din placa Raspberry Pi un sistem de calcul ce poate sta
la baza unor proiecte personal e extrem de interesante și de puternice – un calculator ce poate fi integrat
în sisteme electronice și mecanice proiectat e și realizate de utilizator. [11]
În ciuda dimensiunii reduse placa Raspberry Pi 3 Model B+ dispune de periferice integrate
numeroase acope rind complet funcționalitatea unui sistem de calcul (audio, video, porturi USB,
conectivitate de rețea):
• Procesor So C pe 64 de biți din familia ARMv8 -A, Broadcom BCM2837, ce lucrează la o
frecven ță de 1. 4GHz și dispune de 4 nuclee de tip ARM Cortex -A53;
• 1GB de memorie RAM (folosită și ca memorie video, partajată cu procesorul grafic);
• Procesor grafic Broadcoam VideoCore IV 3D integrat pe aceeași pastilă de siliciu ca și
procesorul principal;
• Ieșire digitală video / audio HDMI;
• Ieșire analogică video (compos ite video) / audio mixtă prin intermediul unei mufe jack
3.5mm;
• Mufă de rețea RJ45 Ethernet 10/100 Mbit/s;
• Conectivi tate WiFi 802.11n;
• Conectivitate B luetooth 4.1 / BLE;
• 4 porturi USB 2.0;
• 40 de pini de intrare / ieșire (GPIO);
28
• Slot card de memorie microSD (utilizat pentru instalarea sistemului de operare);
• Conectori dedicați pentru cameră video (CSI) și afișaj (DSI);
• Power over Ethernet (placa poate fi alimentat ă la distan ță folosind cablul de conectare
Ethernet – cu conditia s ă ai în rețea un device de al imentare POE)
Figura 2. 1 Structura unui Raspberry Pi Model 3 [11]
2.2 Raspberry P i LoRa/GPS HAT
HAT Dragino Lora / GPS -ul este un modul de expansiune pentru Raspberry Pi. Acest produs este
destinat celor interesați în dezvoltarea de soluții LoRaWAN. Lora HAT / GPS se bazează pe transceiver
SX1276 / SX1278. Modulul este proiectat pentr u aplicații car e utilizează GPS conectat prin porturile
seriale la Ra spberry Pi.
Aceast ă placă poate calcula și anticipa orbitele automat folosind date le stocate în memoria flash
internă, astfel încât HAT poate fixa poziția rapid, chiar la nivele de semnal de interior sl abe, cu un consum
redus de energie. Cu tehnologia AlwaysLocate ™, Lora / GPS HAT poate ajusta adaptativ timpul de
pornir e / oprire pentr u a atinge echilibrul si precizia pozitionarii și consumul de energie în funcție de
condițiile de mediu ș i de mișcare. G PS-ul suportă, de asemenea, funcția automată de comutare antenă.
Ea poate realiza comutarea între antena interna si cea externa. De asem enea păstrează poziționarea în
timpul procesului de comutare. [12]
29
Caracter istici:
• Frecventa: 868 MHZ/433 MHZ/915 MHZ(pre configurata in fabr ica)
• Compatibil cu Raspberry Pi 2 Model B/Raspberry Pi 3.
• LoRa™ Modem
• Modulatie FSK, GFSK, MSK, GMSK, LoRa™and OOK
• Rata de transfer conf igurabila
• Senzor de temperatura si baterie incorporat
• Support DGPS, SBAS(WAAS/EGNOS/ MSAS/GAGAN)
• Comutare automata intre antena GPS interna si cea externa
• PPS VS. NMEA poate fi folosit in timpul functionarii
• Support pentru comenzi SDK
• Comenzi LNA incorporate
• EASY™, tehnologie AGPS
• AlwaysLocate™
• GPS FLP mode, consum redus de energie cu 50%
• Protectie la scurt circuit pentru GP S
Figura 2. 2 Raspberry Pi LoRa/GPS HAT [12]
Vom utiliza acest shield ca modul de expansiune la Raspberry Pi pentru a crea stația de bază a
proiectului. Aceasta stație de bază o vom conect a la The Things Netw ork. De menționat este faptul că
această stație de bază este una functională pe un singur can al, și de aceea, fiecare transmisiune se va face
pe o singură frecvență selectată atât d e stația de bază, cât și de noduri. În acest proiect nu vom folosi
modulul GPS integrat.
30
2.3 Modulul SX1276
Tramsmițătoarele SX1276/77/78/ 79 sunt dotate cu modemul LoRa, care oferă comunicații pe o rază
lungă și o imunitate ridicată la interferențe, reducând în același timp consumul de curent.
Folosind t ehnica de modulație patentantă LoRa a firmei Semtech, SX1276 poate atinge o
senzitivitate de peste -148 dBm având costuri scăzute și o listă simplă de componente folosite.
Senzitivitatea ridicată, combinată cu amplif icatorul de putere integrat de +20 dBm, face acest
transmițător optim pentru orice aplicație care necesită o rază lungă de acțiune și un consum redus de
energie.
LoRa oferă avantaje semnificative în ceea ce privește blocarea, cât și selectivitatea față de
tehnicile de modulație convenționale, r ezultând u n compromis de proiectare între raza de acțiune,
imunitatea la interferențe și consumul de energie.
Transmițătorul SX1276 oferă opțiuni de lățime de bandă variind de la 7.8 kHz până la 500 kHz
cu factori de imprăștiere cuprinși între 6 și 12 și acoperind toate benzile de frevență disponibile. De
menționat este și consumul redus de curent la o tran smisiune ș i anume 9.9 mA. [13]
Figura 2. 3 Diagrama bloc a SX1276 [13]
2.4 Placa de dezvoltare Arduino
Arduino este o platformă cu microcontroler foarte simplă de utilizat. Arduino poate fi folosit
pentru dezvoltarea de aplicații interactive. Practic, informa ția este preluată de la o gamă variată de
elemente de intrare (senzori și comutatoare), se proceseaz ă în interior ul microcontr olerului și este
transmisă către o gamă la fel de variată de elemente de ieșire: leduri, motoare, actuatoare, etc.
Avantajele pe care le are Arduino față de alte sisteme bazate pe microcontroler sunt:
31
• costuri de achiziție reduse ;
• poate fi f olosit pe orice sistem de operare (Linux, Windows sau MacOS). Majoritatea
plăcilor de dezvoltare fiind limitate la sistemul de operare Windows ;
• un mediu de programare simplu și ușor de învățat.
Exista mai multe variante de pl ăci de dezvoltar e Arduino, cum ar fi: Mega, Diecimila,
Duemilanove, Mini, Nano și chiar Bluetooth Arduino, cele mai noi produse fiind Arduino Uno și Arduino
Mega 2560. În proiectul nostru vom utiliza două plăci de dezvoltare Arduino Uno.
Plăcile de dezvoltare Arduino seamănă foarte mul t între ele, având elementele comune:
intrările/ ieșirile digitale, intrările analogice, microcontrolerul, etc. O platformă Arduino este compus ă
dintr -un microcontroler Atmel AVR de 8, 16 sau 32 biți în specia l ATmega8, ATmega168, ATmega328,
ATmega1280 și A Tmega2560 precum și componente complementare car e facilitează programarea și
încorporarea în alte circuite. Din 2015 platformele Arduino conți n microcontrolere de la alți producători.
Un microcontroler insta lat pe platforma Arduino vine preprogramat cu un bootloader care
simplifică încărcarea programelor pe memoria flash a cipului, în comparație cu alte dispozitive care
necesită programatoare e xtern ă. Acest aspect face Arduino o soluție simplă, permițând prog ramarea de
pe orice calculator.
Programele Ardu ino pot fi scrise în orice limbaj de programare cu un compilator capabil să
producă un cod mașină binar. Pentru programare se utilizează softw are-ul Arduino IDE (Integrated
Development Environment) care supor tă limbajele de programare C și C++ folosind reg uli speciale de
organizare a codului.
Arduino Uno este o placa de dezvoltare bazată pe microcontrolerul ATmega328P, având 6 intrări
analogice, 14 de intrări digitale/pini de ieșire (din care 6 pot fi utilizat e ca ieșiri PWM), un oscilator cu
quart de 20 MH z, o conexiune USB, o muf ă de alimentare, și un buton de resetare. [14]
Figura 2. 4 Structura plăcii de dezvoltare A rduino Uno [14]
32
Intrările analogice sunt folosit e pentru citirea semnalelor analogice (nondigitale) de la se nzori de
temperatură, senzori de lumină, senzori de presiune, umiditate, etc. Un pin analogic de intrare poate
măsura un curent sau semnal cu tensiune cuprinsă într e 0-5 V. Intrările/ieșirile digitale: permit citirea
stări unui element de intrare/ieșire sa u comanda elementelor care au două stări: închis adică 0 (valori
LOW) sau deschis adică 1 (v alori HIGH).
Pinii c u funcția PWM (Pulse – width modulation), adică modu lația în durată a impulsurilor, pot
fi utilizați pentru a îndeplinii o varietate foarte mare de sarcini, de la iluminarea ledurilor până la controlul
turației motoarelor electrice. Por tul USB are doua rol uri: de alimentare a platformei Arduino și de a
furniza date sistemului. Alimentare cu energie electrică a platformei Arduino de poate face de l a un
alimentator ac -dc cu tensiunea recomandată între 7 -12 V prin mufa de alimentare.
Plăcile Arduino și Arduino – compatibile pot utiliz a diferite scuturi (shield) – plăci imprimate de
extensie care se conectează la Arduino furniz ând astfel posibilitatea extinderii capabilit ăților pl ăcii de
dezvoltare. Shieldurile pot permite controlul motoarelor, GPS, ethernet, display -uri LCD, sau
bread boarding (prototipuri). [14]
2.5 Dragino Lo Ra Shield pentru Arduino
Shield -ul LoRa este un transmițător cu rază lun gă de acțiune compattibil cu platforma Arduino și
bazat pe o bibliotecă open -source. Acest shield permite utilizatorului să trimită date pe di stanțe foarte
mari a unui pachet de date de dimensiuni reduse. Oferă comunicații cu spectru larg de acțiune și imu nitate
ridicată la interferențe, având în același timp un consum redus de curent.
Shield ul este bazat pe modulul Semtech SX1276/SX1278 si se adreseaz ă aplica țiilor profesionale
care imp lică rețele de senzori, cum ar fi sisteme de irigare, ora șe inteligent e, masur ători inteligente, etc.
[15]
Figura 2. 5 Shield Dragino LoRa compatibil Arduino [15]
Specifica ții:
33
• Compatibil cu platforme Arduino de 3.3v si 5v
• Frecven ța de operare: 868 MHz / 433 MHz
• Consum re dus de energie
• Anten ă extern ă prin conectorul I -Pex
• Maxim 168 dB
• +20dBm – 100mW iesire cons tantă
• +14dBm eficienta
• Bit Rate programabil p ână la 300 kbps
• Sensibilitate p ână la -148dBm
• Senzor de temperatur ă si nivel al bateriei inclus.
2.6 Senzori ambientali utilizați
În cazul proiectului nostru și anume în ap licația concretă exemplificată ce ține de un sistem
integrat de monitorizare și p revenție a inundațiilor, din acest nod vor face parte și anumiți senzori:
1) Senzor de temperatură și umiditate DHT11
Figura 2. 6 Senzor de temperatură și umiditate DHT11
DHT11 este un senzor de umiditate și temperatură de înaltă performanță asigurând o bună
fiabilitate și stabilitate.
34
Temperatura este măsurată de un NTC, iar umiditatea relativă este măsurată fo losind un senzor
capacit iv. Aceste elemente sunt pre -calibrate, iar ieșirea este oferită ca semnal digital. Acest senzor este
compatibil cu cele mai p opulare plăcuțe de dezvoltare, precum Arduino.
Senzorul de temperatură și umiditate DHT11 este foarte conv enabil, oferind precizie bună,
simplitate în utilizare și dimensiuni reduse la un preț mic. Senzorul poate măsura umiditatea în intervalul
20% – 90% c u o precizie de 5% și temperatura în intervalul 0 – 50 ˚C cu o precizie de 2 ˚C.
Caracteristici tehnice:
• Tensiune de alimentare: 3 .3V – 5V;
• Curent: 2.5mA (maxim);
• Gama de măsurare a umidității: 20% – 95% RH;
• Acuratețea măsurării umidității: ±5% RH;
• Gama de măsurare a temperaturii: 0 oC – 60 °C;
• Acuratetea măsurării temperaturii: ±2 oC;
• Nu funcționează sub 0°C;
• Dimensiuni: 32mm x 14mm.
Senzorul are inclus un rezistor de pull -up astfel încât nu mai este nevoie de componente
adiționale.
Schema de conectare este următoarea:
• Pin-ul marcat cu "+" se conectează la pin -ul de 5 V sau 3.3V al plăcii de dezvoltare.
• Pin-ul marcat cu "OUT" se conectează la un pin digital.
• Pin-ul marcat cu " -" se conectează la un pin GND al plăcii de dezvoltare.
Pentru a facilita util izarea senzorului DHT11, în proiect am utilizat o bibliotecă special creată
pentru acest produs și anume b iblioteca „DHT11”. P entru a o adăuga această bibliotecă în mediul de
dezvoltare Arduino IDE se selectează tabul Sketch -> Include Library -> Manage li braries. [16]
2) Senzor ultrasonic HC -SR04
În aplicația concretă exemplificată ce ține de un sistem integra t de monitorizare și prevenție a
inundațiilor, am utilizat acest senzor pentru a determina distanța până la nivelul apei, astfel pot detecta
fiecare diferență de nivel, fapt ce duce la o monitorizare concretă a nivelului apei.
Senzorii ultrasonici funcțion ează dupa următorul principiu: Acesția emit pulsații acustice scurte,
de înaltă frecvență, la intervale de timp regulate. Acestea se propagă prin aer cu viteza su netului. Dacă
lovesc un obiect, acestea sunt reflectate înapoi ca semnale ecou la senzor, care calculează distanța pănă
la obiect pe baza intervalului de timp dintre emiterea semnalului și receptarea ecoului.
Deoarece distanța până la obiect este determina tă prin măsurarea timpului de deplasare a undel or
și nu prin intensitatea sunetului, senzorii ultrasonici sunt exc elenți pentru eliminarea interferențelor de
fundal. În principiu, toate materialele care reflectă sunetul pot fi detectate, indiferent de culo area lor.
Chiar și materialele transparente sau folii subtiri nu reprezintă nicio problemă pen tru un senzor ultras onic.
35
Senzorii ultrasonici pot să vadă prin aer plin de praf si prin vapori de cerneală. Chiar și depuneri subțiri
pe membrana senzorului nu a fectează funcționarea acestuia. [17]
În cadrul acestui proiect am decis să utilizez senzorul u ltrasonic HC -SR04, care este unul din tre
cei mai populari și ușor de utilizat senzori de distanță. Este compatibil cu Arduino și pr ezintă câteva
avanta je față de senzorii de distanță analogici: necesită doar pini I/O digitali, are imunitate mai mare la
zgomot.
Figura 2. 7 Senzor ultrasonic HC -SR04
Acesta are o precizie de 3mm și măsoară la un unghi de 15˚. Este ușor de fol osit și consumă
puțină energie, principalul dezavantaj fiind distanța relativ mică de măsurare: 2 cm – 4 m. Senzorul este
foarte ușor de folos it, având doar 4 pini: VCC și GND, care sunt folosiți pentru alimentare și doi pini
digitali, utilizați pentru und a emisă (trigger) și unda recepționată (echo).
Măsurarea distanței se bazează pe diferența dintre momentu l de timp la care s -a transmis trigge r-
ul și momentul la care acesta se detectează înapoi. [18]
Caracteristici tehnice:
• Tensiune de alimentare: 5V;
• Curent c onsumat: 15mA;
• Distanță de funcționare: 2cm – 4m;
• Unghiu de măsurare: 15o;
• Eroare de doar 3mm;
• Durat ă semnal input: 10us;
• Dimensiuni: 45mm x 2 0mm x 15mm.
36
3) Senzor de nivel al apei
Acest senzor de nivel al apei es te un dispozit iv cu consum redus, cu eficiență ridicată. Acest
senzor poate fi utilizat cu microcontrolere și plăci de dezvoltare.
Figura 2. 8 Senzor de nivel al apei
Senzorul poate fi utilizat pentru a detecta nivelul apei pe o distanță de 40mm. Acesta este de o
eficiență foarte bună și are un consum foarte mic. Output -ul este analogic, dând o tensiune în funcție de
nivelul apei. Senzorul poate fi folosit împreună cu microcontrollere și plăcuțe de dezvoltare, precum
Arduino. [19]
Specificații:
• Tensiunea de funcționare: 3 VDC până la 5 VDC;
• Curent de operare: <20 mA;
• Suprafață de detecție: 40 mm x 16 mm;
• Temperatura de operare: 10 ˚C până la 30 ˚C;
• Umiditate: 10% până la 90%;
• Dimensiune: 62 x 20 x 8 mm .
37
CAPITOLUL 3 – REALIZAREA PRACTICĂ A SISTEMULUI
3.1 Schema Bloc
Figura 3. 1 Schema bloc a sistemului
Nodurile LoRa: Placa de dezvoltare Arduino Uno va primi datele de la senzori și va trimite
aceste date utilizând shield -ul LoRa către stația de bază formată dintr -un Raspberry Pi și un modul LoRa
compatibil prin intermediul p rotocolului fără fir LoRaWAN.
Stația de bază ( Gateway): Stația de bază va recepționa aceste date și le va trimite către rețeaua
TTN (The Things Network) prin Internet.
Serverul TTN: Acesta va primi pachetele de date de la stația de bază și datele vor fi s tocate într –
un spațiu corespunzător, astfel înc ât acestea să fie accesibile pentru eventualele integrări în diferite
aplicații.
38
Aplicația WEB: Putem folosi această aplicație pentru diverse implement ări, având acces la
datele transmise de la nodurile LoRa.
3.2 Descrierea funcționalității sistemului
Lucrarea are ca scop realizarea unui sistem de detecție a unor situații de urgență, cât și o
prevenție a acestora, proiectul fiind bazat pe o comunica re într -o rețea LoRaWAN.
Rețeaua va fi compusă din nodur i LoRa, cât și o stație de bază la care se vor conecta și vor
transmite date nodurile aferente . O aplicație a acestui sistem constă în prevenirea inundațiilor folosindu –
se de datele achiziționate pri vind volumul de apă/nivelul acestuia.
Un nod va fi compus dintr -o placă de dezvoltare, un modul de trans misie LoRa, o antenă, cât și
senzori ce țin de aplicația vizată (prevenirea inundațiilor) precum senzor de detecție al apei, senzor cu
ultrasunete pentr u observarea nivelului de apă, senzor de umiditate. Se va realiza o achiziție la nivel
local a datelor d e la senzori, care urmează să fie prelucrate, ș i transmise folosind modulul LoRa către
stația de bază. În final, se va realiza o decodare și o analiză a pachetului de date transmis.
Întregul sistem integrat va cuprinde și o aplicație WEB unde se pot monito riza toți parametrii ce
ne interesează de la ce le 2 noduri, cu un istoric complet, cât și avertiz ări în caz de eventualele pericole
detectate. Această a plicație face subiectul capitolului următor.
3.3 Integrarea proiectului practic într -o aplicație TTN
Înainte de a putea comunica cu dispozitivele noastre, trebuie să se creeze o aplicație in rețeaua
The Things Network și să înregistrăm dispozitivele în această rețea. Există mai multe opțiuni de a
integrare a aplicațiilor în rețeaua TTN, de la lucrul di rect cu API -uri, prin intermediul SDK -urilor sa u
prin integrarea platformelor Click -and-run.
Dispozitivele pot comunica cu aplicațiile la care au fost înregistrate. Pentru a înregistra un
dispozitiv, va trebu i mai întâi să adăugăm aplicația noastră. Pentr u aceasta trebuie să avem un cont în
rețeaua The Things Network.
Pentru crearea aplicației, în consolă avem tab -ul de Adăugare a unei apl icații . Se va alege un ID
unic al aplicației format din caractere fără majuscule și fără caractere speciale. Apoi se va completa o
scurtă descriere a aplicației și se va alege automat regiunea în care va fi creată aplicația respectiv ttn-
handler -eu. Imediat ce aplicația a fost creată, vom fi redirecționați către o pagină und e putem găsi
identificatorul unic al aplicației App EUI, cât și cheile de acces. Consola aplicației va arăta ca în figura
3.2 de mai jos.
39
Figura 3. 2 Consola aplicației TTN
40
3.4 Realizare a nodurilor de tras misie
3.4.1 Schema electrică a unui nod
Figura 3. 3 Schema electrică a unui nod LoRa
Un nod de tran smisie va fi compus, la bază, dintr -o placă de dezvoltare Arduino Uno, un shield
LoRa Dragino, si o antenă funcțională p e frecvența de 868 MHz. În cazul proiectului no stru și anume în
aplicația concretă exemplifica tă ce ține de un sistem integrat de monitorizare și prevenție a in undațiilor,
din acest nod vor face parte și anumiți senzori:
• Senzor de temperatură și umiditate DHT11
• Senzor ultrasonic HC -SR04
• Senzor de nive l al apei
41
Figura 3. 4 Nod Lo Ra fizic
Aplicația fiind creată și cele 2 noduri asamblate, putem înregistra dispozitivele în The Things
Network. Pentru aceasta , am ales metoda de activare prin personalizare (ABP). În mod norm al, am utiliza
metoda de activare prin aer (OTAA) pentru a negocia cheile sesiunii automat pentru comuni cațiile
ulterioare. Însă, am ales opțiunea de a personaliza integral dispozitivele, ceea ce înseamnă că v oi genera
sau atribui manual cheile de sesiune și vom folosi aceste chei în programarea dispozitivelor. După ce
completăm câmpurile de Device ID și Dev ice EUI ni se v or atribui cheia de rețea, respectiv cea de seiune.
Vom exemplifica totul pentru nodul 1 al sistemului nostru, deoarece intregrarea nod ului 2 este
similară, diferă doar adresa dispozitivului, cheia de rețea si cheia de sesiune. În final, c onfigurarea
nodului nostru va arăta ca în figura de mai jos.
42
Figura 3. 5 Configurarea nodului LoRa în TTN
3.4.2 Mediul de dezvoltare integrat Arduino
Mediul de dezvoltare integrat Arduino este distribuit cu titlu gratuit și există variante pentru cele
mai uzuale sisteme de operare: Windows, Mac OS și Linux .
Mediul de dezvo ltare integrat Arduino reprezint ă o aplica ție scrisă în Java și include un editor de
cod cu caracteristici, alinierea automat ă și conectarea leg ăturilor. Programele Arduino sunt scrise în C
sau C++, iar utilizatorii trebuie să defineasc ă functiile de execu tie astfel încât să fie permis ă rularea
programu lui.
„Programele scrise pentru platformele Arduino poartă denumirea de „sketch” . Acestea sunt
alcătuite din două funcții importante:
void setup () {
// instrucțiunile de aici se execută o singură dată, la pornire
// se utilizează pentru setări și iniț ializări
43
}
void loop() {
// instrucțiunile de aici se execută în buclă, de la ultima instrucțiune se reia bucla
// cu prima instrucțiune din această funcție, aici e programul principal
// se execută în mo d repetat până la oprirea alimentării cu energi e a sistemului
}
După cum a u fost descrise pe scurt, prima funcție este utilizată pentru inițializarea variabilelor, a
comunicației seriale (de exemplu baud rate), pentru declararea pinilor ca fiind de ieșire sau de intrare,
diverse funcții pentru inițial izarea unor senzori, etc. Ac eastă funcție este executată la pornirea (imediat
după alimentarea sau după reset) sistemului de dezvoltare Arduino Uno, fiind rulată o singură dată. A
doua funcție (loop();), este funcția similară cu „main()” din limbajul de pr ogramare C, este rulată în
buclă, adică la sfârșitul execuției ultimei instrucțiuni din cadrul funcției este continuată cu execuția primei
instrucțiuni din această funcție, totul fiind un ciclu care se repet ă continuu. ” [20]
Pentru programare nodurilor, vo m folosi mediul de lucru Arduino IDE. Vom conecta nodul 1
asamblat la calcultator printr -un cablu USB.
De aici, folosim mediul de dezvoltare integrat Arduino și trebuie să instalăm pachetul Arduino –
LMIC. Acest pachet conține biblioteca IBM LMIC (LoraMAC -in-C), ușor modificată pentru a funcționa
în mediul Arduino, permițând utilizarea transmițătoarelor SX1272, SX1276 și a modulelor co mpatibile .
[21]
3.4.3 Biblioteca Arduino -LMIC
Biblioteca Arduino -LMIC expune funcțiile definite de LMIC, nu face nicio înc ercare de a le
împacheta într -un nivel superior API, care este mai mult spre partea de Arduino. Această bibliotecă
necesită Ardui no IDE versiunea 1.6.6 sau mai recentă, deoarece necesită standardul C99 să fie activat în
mod implicit. Biblioteca LMIC oferă o implementare destul d e completă pentru Clasele A și B
LoRaWAN, suportând benzile EU -868 și US -915.
Această bibliotecă este dest inată a fi utilizată cu transmițătoare de LoRa, conectate folosind
interfața serială SPI. În special sunt suportate familiile S X1272 și SX1276, ambele fiind testate utilizând
placa Se mtech SX1272 și plăcile HopeRF RFM92 și RFM95 (care de asemenea conțin ch ip-urile
SX1272, respectiv SX1276).
Biblioteca aceasta este destul de m are, în special dacă este folosit microcontrolerul Atmeg a 328p
(cum ar fi Arduino Uno). În configurația implicit ă, spațiul disponibil de 32K este aproape plin (acesta
incluzând și unele ieșiri ce țin de depanare). Dezactivând unele funcții din config.h (cu m ar fi sloturi de
urmărire sau sloturi de ping, care nu sunt de obicei necesare), poate fi eliberat mai mult sp ațiu. Unele
lucruri sunt în curs de desfășurare pentru a înlocui implemen tarea de criptare AES, care ar trebui să
elibereze alți 8K din memoria flash în viitor, făcând aceasta bibliotecă fezabilă în î ntregime pentru a rula
pe un microcontroler de 328p.
Modul principal de comunicare cu trasmițătorul este prin SPI (Interfața Seri ală Periferică).
Aceasta utilizează patru pini: MOSI, MISO, SCK și SS. Primii trei trebuie conectați direct: MOSI la
44
MOSI, MISO la MISO și SCK la SCK. Pinul SS (Slave Select) este puțin mai flexibil. Pe partea de slave
SPI (transmițătorul), acesta trebuie să fie conectat în mod obișnuit la pinul NSS. Pe partea de master a
SPI (Arduino), acest pin se poate conecta la orice pin I/O.
Conexiunile DIO de pe placă pot fi configurate pentru diferite funcții. Biblioteca LMIC le
folosește pentru a obține informații instantanee despre starea de funcționare de la transmițător. De
exemplu , atunci când începe o transmisie LoRa, pinul DIO0 este configurat ca ieșire TxDone. Când
transmisia este completă, pinul DIO0 este setat pe „high” de către transmițător, care poate fi detectat de
biblioteca LMIC. Biblioteca LMIC necesită doar acces la DIO 0, DIO1 și DIO2, ceilalți pini DIOx pot fi
lăsați decone ctați. Pe parte de Arduino, se pot conecta la orice pin I/O, deoarece implementarea actuală
nu utilizează întreruperi sau alte ca racteristici hardware speciale. [21]
În modul LoRa, pinii DIO sunt utilizați în felul următor:
• DIO0: TxDone și RxDone
• DIO1: RxT imeout
În modul FSK, pinii DIO sunt utilizați în felul următor:
• DIO0: PayloadReady și PacketSent
• DIO2: TimeOut
Ambele moduri au nevoie doar de doi pini, dar transmițătorul nu permite maparea astfe l încât
întreruperile necesare să corespundă acelorași doi pini. Deci, dacă se utilizează ambele moduri LoRa și
FSK, toți cei trei pini trebuie conectați .
Transmițătorul are, de asemenea, un pin de resetare care poate fi utilizat pentru resetarea explicită
a acestuia. Biblioteca LMIC folosește acest lucru pentru a se asigura că cipul este într -o stare bună la
pornire. În practică, a cest pin poate fi lăsat deconectat, deoarece transmițătorul va fi deja într -o stare de
bună funcționare la pornire, da r conectarea acestuia ar putea împiedica probleme în unele cazuri. Pe
partea de Arduino, orice pin I/O poate fi folosit pentru resetare.
Transmițătorul conține două conexiuni separate pentru antenă: una pentru RX și una pentru TX.
O placă tipică de emisie -recepție conține un cip de comutare a antenei, care permite comutarea unei
singure antene între aceste conexiuni RX și TX. Cea mai ușoară modalitate de a controla comutatorul
antenei este utilizarea pinu lui RXTX de pe transmițătorul SX127x. Acest pin este automat setat pe „high”
în timpul TX și „low” în timpul RX. [21]
Maparea pinilor pe shield -ul Dragino LoRa se face în felul următor:
Figura 3. 6 Mapare pinilor pe shield -ul Dragino LoRa
45
3.4.4 Programarea nodurilor
Vom exemplifica totul pentru Nodul 1 de transmisie.
În primul rând trebuie să definim cheia sesiunii de rețea, cheia sesiunii de aplicație, cât și adresa
dispozitivului, generate de setările făcute în TTN. Această operațiune am făcut -o în felul următor:
Figura 3. 7 Definirea cheilor de acces și adres a dizpozitivului
Apoi, am definit intervalul dintre fiecare transmisiune în variabila TX_INTERVAL. Am ales
valoarea de 297 secunde, ceea ce în realitatea înseamnă 5 minute, deorece fiecare transmisiune este
întârziată cu aproximativ 3 secunde.
Figura 3 . 8 Definirea intervalului de tran smisiune
În funcția setup(), inițializăm mediul LMIC și setăm parametrii sesiunii în felul următor:
Figura 3. 9 Inițializare LMIC
De asemenea, fiindcă stația no astră de bază este funcți onală pe un singur canal de frecvență , și în
mod normal in rețeaua TTN se face o ciclare între frecvențele 868.1, 868.3 și 868.5 MHz, am hardcodat
canalul 0 ca fiind frecvența de 868.3 MHz, și am dezactivat toate celelalte canale astfel:
46
Figura 3. 10 Păstrarea unui singur canal de frecvență
Totodată, am configurat rata de transmisie a datelor cât și factorul de împrăștiere pentru o distanță
cât mai mare posibilă astfel: LMIC_setDrTxpow(DR_SF12,14); .
Am creat o variabil ă de t ipul byte denumită payload în care vom stoca pachetul de date efectiv
ce v-a fi trimis prin intermediul LoRa. Aceasta variabilă conține cele 4 date de la senzorii integrați pe
placa de dezvoltare Arduino.
Figura 3. 11 Apel area funcțiilor de citire a datelor de la senzori
Am creat cele 4 funcții respectiv readTemp, readHum, readWater și readDistance() și returnăm
rezultatele acestora în cele 4 variabile declarate în figura de mai sus.
Figura 3. 12 Funcțiile de citire a datelor de la senzori
47
Pachetul de date efectiv ce va fi trimis și anume variabila payload conține doar 7 octeți și anume:
primii 2 pentru valoarea temperaturii, următorii 2 pentru valoarea umidității, un s ingur octet pentr u
valore a de la senzorul de nivel al apei care returnează valori doar între 0 și 3 și de aceea este suficient un
octet, iar ultimii 2 pentru distanța față de apă. Transmite pachetul de date către gateway -urile disponibile
și implicit TTN, în felul următor :
Figura 3. 13 Transmiterea payload -ului către gateway
Datele de la aceste noduri pot fi accesibile prin orice stație de bază compatibilă ca și canal de
frecvență din rețeaua The Things Network. Cu toate ac estea, ca sistemu l nostru să fie complet intregrat,
am realizat o stație de bază specială pentru recepționarea datelor de la aceste noduri.
Datele utile (payload -ul) transmise în platforma TTN, sunt sub formă hexa zecimală și pentru o
extragere mai explicit ă a acestor, am utilizat un decodor aplicat acestui pachet și anume:
Figura 3. 14 Decodare payload forma hexa zecimală
48
3.5 Realizare a stației de bază
Vom realiza o stație de bază utilizând o placă de dezvoltare Raspberry Pi Model 3 B+ și un LoRa
Hat compatibil Raspberry Pi.
Primul pas, necesar înainte de punerea în funcțiune a plăcii Raspberry Pi 3, este pregătirea
cardului microSD pentru instalarea sistemului de operare. Placa Raspberry Pi 3 poate rula diverse
distribuț ii ale si stemului de oper are Linux și o versiune minimală a sistemului de operare Microsoft
Windows 10 (prin versiune minimală înțelegem o variantă ce nu poate fi folosită ca platformă desktop ci
doar ca platformă pentru aplicații – Windows 10 IoT Core). Î n cadrul acestui proiect am instalat
distribuția Linux Raspbian, sistemul de operare oficial al plăcii Raspberry Pi, sistem de operare foarte
ușor de utilizat și recomandat pentru diverse proiecte.
Pentru aceasta, putem utiliza un card microSD de calitate pe care să copiem utilit arul NOOBS ce
facilitează instalarea diverselor sisteme de operare specifice plăcii Raspberry Pi. Pentru pornirea instalării
sistemului de operare se inserează cardul în slotul microSD al plăcii și se pornește sistemul (to ate
echip amentele trebuie conectat e corect: tastatură, mouse, cablu HDMI). După inițializare , utilitarul
NOOBS v a permite alegerea sistemului de operare dorit în etapa de instalare, în cazul de față acesta fiind
Raspbian.
După configurarea inițială, un pa s importa nt ce trebuie făcut este Utilizarea plăcii Raspberry Pi 3
de la distanță. De multe ori este mai comod sau pur și simplu natura proiectului impune accesul la distanță
pentru utilizarea plăcii Raspberry Pi. Prin acces la distanță nu se înțelege neap ărat fapt ul că pla ca se află
la ma re distanță ci că nu este accesată de la o tastatură și un monitor direct conectate. În acest fel putem
utiliza placa fără a bloca un set de periferice dedicate. Pentru a putea să ne conectăm la placa Raspberry
Pi prin int ermediul rețelei este necesar să c unoaștem adresa IP a acesteia. Dacă alocarea adreselor IP în
rețeaua locală în care se utilizează placa se realizează în mod static este suficient să ne notăm adresa
alocată după instalarea sistemului de operare utilizând comanda ifconfig în aplicația Term inal. Pentru
accesul la distanță în linie de comandă se utilizează programul ssh ce permite deschiderea unei sesiuni
de tip terminal de pe un alt sistem de calcul. Este necesară instalarea unui client ssh pe sistemul de pe
care se va face accesul. Cel mai cunoscut client ssh pentru Windows este putty, sistemele Linux au
clientul ssh instalat implicit.
Însă, Pentru accesul la distanță beneficiind de interfața grafică pusă la dispoziție de sistemul de
operare vom utiliza pro gramul VN C. La fel ca și în cazul ssh este necesară instalarea pe sistemul de pe
care se face accesul a unui client specific. Unul dintre cei mai cunoscuți clienți VNC este VNC
Viewer. [11]
49
Figura 3. 15 Conectare la Raspberry Pi prin V NC
Pentru ca shield -ul LoRa Hat să fie vizibil de către Raspberry trebuie să activăm interfața ser ială
a acestuia. Acest lucru se poate realiza utilizând comanda „sudo raspi -config” în Terminal și urmând
pașii în urma rulării comenzii.
Figura 3. 16 Activare interfață serială pe Raspberry Pi
Totodată, trebuie instalat și pachetul WiringPi folosind comanda „sudo apt -get install wiringpi”.
WiringPi este o bibliotecă de acces GPIO, scrisă în limbajul C pentru dispozitivele SoC BCM2835,
BCM2836 și BCM2837 folosite în toate versiuni le de Raspberry Pi. Această bibiliotecă se af lă sub
licența GNU LGPLv3 și este utilizabilă în limbajele C, C++, precum și în alte limbaje compatibile. Acest
50
pachet este conceput pentru utilizatorii ca re au folosit sistemul de „cablare” Arduino și este dest inat
utilizării de către programtori C/C++ ex perimentați.
Inițial, am facut o copie de pe GitHub a pachetului [single_chan_pkt_fwd
https://github.com/tftelkamp/single_chan_pkt_fwd ], însă am avut probleme cu configurarea acestuia în
sensul că nu putea fi vizibilă stația de bază în platforma TTN.
După o depanare și un mic studiu am găsit soluția la această problemă. A m făcut o copie de pe
GitHub a pachetului [dual_chan_pkt_fwd https://github.com/bokse001/dual_chan_pkt_fwd ]. Acest
pachet conține o dovadă a implementării conceptului de Gateway cu două canale , însă eu m -am folosit
doar de implementarea cu un singur canal al acestuia. Am configurat acest pachet, în fișierul
„global _conf.json”, conform setărilor dorite privind pinii Hat -ului LoRa, cât și ca aceasta stație de bază
sa fie vizibilă pe platforma TTN, astfel:
Figura 3. 17 Configurea stației de bază implementată pe Raspberry Pi
51
Menționez că m-am folosit doar de prima frecvență din fișierul de configurare și anume 868.3
MHz. Cum am spus și mai sus, atât cele 2 noduri transm it pe frecvența de 86 8.3 Mhz, cât și stați a de
bază poate recepționa date tot pe această frecvență.
Utilizarea unui singu r canal de frecvență reprezintă o limitare hardware a unei stații de bază
implementate dintr -un Raspberry Pi și un Hat LoRa cu transmi țătorul SX1276. De as emenea, această
rețea poate lucra doar cu un singur factor de împrăștiere. Cel ales este SF12 pentru a avea o distanță cât
mai mare de comunicare între noduri și stația de bază.
Este de înțeles că stația de bază trebuie să aibe acces la internet pentru a transmite datele la rețeaua
TTN, dar acesta este marele beneficiu al acestui sistem integrat bazat pe o comunicație LoRa. Toate
nodurile pot comunica cu stația de bază prin modulația LoRa la distanțe de câțiva km, fără a avea acces
la internet. Doar stația de bază trebuie să a ibă acces la internet. Acest poate să fie prin cablu, prin WiFi
sau printr -un mo dul GSM cu 3G/LTE. În cazul de față, placa Raspberry Pi dispune de acces la internet
printr -o conexiune WiFi.
La rularea aplicației de gateway, în termin al va apărea configurația acesteia, fiecare pachet
recepționat, cât și un istoric la fiecare 30 de se cunde privind numărul de pachete recepționate , ca în Figura
3.18 de mai jos.
Figura 3. 18 Funcționarea Gateway -ului
Aceast ă stație de bază a fost înregistrată în rețeaua TTN cu „Gateway ID” -ul din figura de mai
sus. Consol a acestui gateway din platforma TTN arată în felul următor:
52
Figura 3. 19 Consolă Gateway
De asemenea, întreg traficul poate fi vizualizat:
Figura 3. 20 Traficul recepționat de Gateway
53
CAPITOLUL 4 – APLICAȚIA WEB ȘI INTERACȚIUNEA
CU UTILIZATORUL
4.1 Tehnologiile software folosite
4.1.1 Limbajul JavaScript
JavaScript este un limbaj de programar e dinamic pe deplin dezvoltat care, atunci când este aplicat
unui document HTML , poa te oferi interactivitate dinamică siteurilor. A fost inventat de Brendan Eich,
co-fondator al proiectului Mozilla, Mozilla Foundation și Mozilla Corporation. [23]
Deseori, JavaScript este asociat cu Java, însă aceste 2 limbaje sunt complet diferite. Java (dezvo ltat
de Sun Microsystems) este un limbaj mult mai puternic și mai complex, din aceeași categorie cu C sau
C++.
JavaScript poate face o mulțime de lucruri, printre car e amintim următoa rele:
• JavaScript oferă proiectanților HTML un instrument de programare – în general proiectanții
paginilor HTML nu sunt programatori, dar JavaScript este un limbaj cu o sintaxă foarte simplă
și aproape oricine poate insera mici secvențe de cod în paginile HTML
• JavaScript poate insera în mod dinamic text într -o pagină HTML – O instrucțiune JavaScript
ca aceasta: document.write("<h1>" + name + "</h1>") poate scrie un text variabil în pagina
HTML
• JavaScript poate reacționa la evenimente – Un c od JavaScript poa te fi proiecta t să se execute
când se întâmplă ceva, spre exemplu când pa gina s -a încărcat complet sau utilizatorul
acționează un element HTML
• JavaScript poate citi și scrie elementele HTML – Un cod JavaScript poate citi și modifica
conțin utul unui element HTML
• JavaScript poate fi folosit pentru a valida datele – Un cod JavaScr ipt poate fi folosit pentru a
valida datele înainte de a fi trimise către server. În acest fel serverul nu mai face procesări
suplimentare.
• JavaScript poate fi folosi t pentru a detect a browserul utilizatorului – Un cod JavaScript poate
detecta tipul browse rului și poate încărca o pagină proiectată special pentru tipul respectiv de
browser
• JavaScript poate fi folosit pentru a crea cookies – Un cod JavaScript poate fi ut ilizat pentru a
stoca și extrage informații pe calculatorul vizitatorului paginii HTML [22]
JavaScript este incredibil de versatil. De la galerii de imagini, layouturi fluctuante, și răspunsuri la
clicuri pe butoane se poate trece până la crearea de jocuri , animații grafice 2D și 3D, aplicații complexe
bazate pe baze de date și multe altele .
54
JavaScript în sine este destul de compact dar totuși foarte flexibil. Dezvoltatorii au scris o mare
variet ate de instrumente având la bază limbajul JavaScript, deblocân d o cantitate vastă de funcționalitate
suplimentară cu efort m inim. Acestea includ:
• Interfețele de programare pentru apl icațiile de browser (APIs) — API construite în browsere web,
oferind func ționalități precum crearea dinamică de HTML și setarea stiluri lor CSS, colectarea și
manipularea unui flux video de la camer a video a utilizatorului, sau generarea de imagini grafice
3D și monstre audio.
• API-uri terțe pentru a permite dezvoltatorilor să in tegreze funcționalitatea în siteurile lor de la alți
furnizori de conținut, cum ar fi Twitter sau Facebook.
• Frameworkuri și librării terțe pe care care pot fi incluse în codul HTML și care permit rapid
construcția de siteuri și aplicații. [23]
4.1.2 Node.js
Node (sau denumirea oficială Node.js) este un mediu de ex ecuție open -source, multi -platformă,
care permite dezvoltatorilor să creeze diverse instrumente și aplicații în JavaScript. Mediul de execuție
este destinat utilizării în afara contex tului unui browser (adică, rularea directă pe un computer sau pe un
serve r). Astfel, mediul omite API -urile specifice JavaScript și aduce suport pentru API -urile ce țin de
sistemul de operare, cum ar fi suport pentru HTTP și bibliotecile destinate sistemul ui de fișiere. Node.js
este un mediu de execuție construit pe baza interp retorului V8 al Chrome de JavaScript.
Din perspectiva dezvoltării unui server web, Node prezintă următoarele beneficii:
• Performanțe bune întrucât Node a fost gândit să optimizeze rezultatele și scalabilitatea în
aplicațiile web, fiind o soluție foarte bu nă pentru multe probleme comune ale dezvoltării web.
• Codul este scris în „JavaScript curat”, ceea ce înseamnă că este petrecut mai puțin timp pentru a
„schimba contextul ” mental al diferitelor limbaje atunci când se scrie cod pentru browser și pentru
server.
• JavaScript este un limbaj de programare relativ nou care beneficiază de îmbunătățirile ale design –
ului comparativ cu alte limbaje tradiționale web -server (de ex. Pyt hon, PHP, etc.). Multe alte
limbaje populare pot fi compilate/convertite în JavaScript astfel că poți folosi CoffeeScript,
ClosureScript, Scala, LiveScript, etc.
• Managerul de pachete node (NPM) oferă acces la sute de mii de pachete reutilizabile. Dintre t oate
celelalte sisteme de gestiune a pachetelor, are și cele mai bune soluții privind dependințele și
poate fi utilizat pentru automatizarea lanțului de construcție al instrumentelor.
55
• Este portabil, având versiuni care rulează pe Microsoft Windows, OS X, Linux, Solaris, FreeBSD,
OpenBSD, WebOS și NonStop OS. Mai mult, este bine suportat de multe servicii de găzduire
web, care oferă adesea infrastructură și documentație specifică pentru găzduirea de site -uri
Node. [24]
4.1.3 Framework -ul Express
Express este cel mai popular framework al Node.js și reprezintă biblioteca de bază pentru o se rie
de alte framework -uri popu lare Nod. Express oferă mecanisme pentru a:
➢ Rezolva cererile diferite de tip HTTP la diferite rute URL
➢ Integra cu motoarele de redare „view” pentru a genera răspunsuri prin introducerea datelor în
difeirte șabloane
➢ Seta diferi te setări ce țin de aplicația web cum ar fi portul pe care să se realizeze c onexiunea, și
locația șabloanelor utilizate pentru redarea conținutului.
➢ Adăuga procesare suplimentară de cereri „intermediare” în orice moment în coa da de tratare a
cererilor.
În timp ce framework -ul Express în sine este destul de minimalist, dezvoltator ii au create
pachete „middleware” pentru a aborda aproape orice problemă ce ține de dezvoltarea web. Există
biblioteci pentru a lucra cu cookie -urile, sesiunile, conectările utiliz atorilor, parametrii URL,
cererile de tip POST a datelor, anteturile de sec uritate și multe altele. [24]
4.1.4 Protocolul HTTP
„HTTP (Hypertext Transfer Protocol) este un protocol de comunicație responsabil cu transferul
de hipertext (text structurat c e conține legături) dintre un client (de regulă, un navigator) și un server web,
interacțiunea dintre acestea (prin intermediul unei conexiuni TCP persistente pe portul 80) fiind
reglementată de RFC 2616. HTTP este un protocol fără stare, pentru persistenț a informațiilor între
accesări fiind nece sar să se utilizeze soluții adiacente (cookie, sesiuni, rescrierea URL -urilor, câmpuri
ascunse). „
„Principa lele concepte cu care lucrează acest protocol sunt cererea și răspunsul.
• cererea este transmisă de client către serverul web și repr ezintă o solicitare pentru
obținerea unor resurse (identificate printr -un URL); aceasta conține denumirea metodei
care va fi utilizată pentru transferul de informații, locația de unde se găsește resursa
respectivă și versiunea de protocol;
56
• răspunsul este transmis d e serverul web către client, ca rezultat al solicitării primite,
incluzând și o linie de stare (ce conține un cod c are indică dacă starea comenzii) precum
și alte informații suplimentare. „ [25]
Figura 4. 1 Cerer e și răspuns în protocolul HTTP [26]
O cerere HTTP conține una sau mai multe linii de text ASCII, precedate în mod necesar de
denumirea metodei specificând operația ce se va realiza asupra conținutului respectiv:
Figura 4. 2 Cererile HTTP [25]
57
4.1.5 Stilul Arhitectural – REST
Representational State Transfer este un stil arhitectural folosit pentru proiectar ea serviciilor web .
Principalul element pe care se bazează acest stil arhitectural este resursa. O resursă poate fi reprezent ată
de un document, o imagine, etc., practic, de orice concept ce reprezintă ținta unui hipertext . Serviciile
web proiectat e cu ajutorul REST prezintă o arhitectură de tip client -server, în cazul căreia clientul și
server -ul schi mbă reprezentări ale re surselor folosind, de regulă, protocolul HTTP[28]. O reprezentare
este o succesiune de octeți la care se adaugă metadate pentru descrierea octeților. De exemplu,
documentul HTML este o reprezentare a unei pagini web
Printre principal ele avantaje ale u nui serviciu RESTful se numără :
• independența față de platformă, astfel, sistemul de operare al server -ului poate diferi de cel al
clientului;
• independența față de limbajul de programare, astfel, o aplicație client scrisă în limbaj Java p oate
comunica fără probleme cu o aplicație de tip server scrisă în limbaj C++ sau C#;
• poate fi utilizat fără probleme în prezența unui firew all;
• este integrat foarte ușor în alte servicii web deja existente;
• este simplu de implementat. [27]
Un API de tipul REST este o interfaț ă de programare a aplicațiilor care utilizează cererile HTTP
cu metodele de GET, PUT, POST și DELETE. Un API REST – denu mit și serviciu web RESTful – se
bazează pe tehnologia REST, un stil arhitectural și o abordare a comunicații lor utilizate adesea în
dezvoltarea serviciilor web.
4.1.6 MongoDB
„MongoDB este o bază de date NoSQL open -source orientată pe documente. Acestă bază de date
beneficiază de suport din partea companiei 10gen. MongoDB face parte din familia de sistemelo r de baze
de date NoSQL. Dif erența principală constă în faptul că stocarea datelor nu se face folosind tabele precum
într-o bază de date relațională, MongoDB stochează datele sub formă de documente JSON cu scheme
dinamice.
MongoDB este o bază de date open -source NoSQL scrisă în C++. Aceasta poate conține mai
multe baze de date, colecții și indecși. În unele cazuri (baze de date și colecții ) aceste obiecte pot fi create
implicit. Odată create, ele se găsesc în catalogul sistemului db.systems.collection, db .system.indexes.
Colecțiile conțin documente (BSON). Aceste documente conțin la rândul lor mai multe câmpuri. În
Mongo DB nu există câmpuri predefinite spre deosebire de bazele de date relaționale, unde există
coloanele care sunt definite în momentul în car e tabelele sunt create. Nu e xistă schemă pentru câmpurile
dintr -un document, acestea precum și tipurile lor pot varia. Astfel nu există operația de „alter table”
pentru adăugare de coloane. În practică este obișnuit ca o colecție să aibă o structură omogen ă, deși nu
58
este o cerință, c olecțiile putând avea structuri diferite. Această flexibilitate presupune ușurință în
migr area și modificarea imaginii de ansamblu asupra datelor. ” [29]
4.1.7 Modelul Arhitectural Model -View -Controller
„Model -View -Controller (MVC) este un model arhitectur al care separă funcționalitatea specifică
domeniului pentru care este dezvoltat sistemul software de interfața grafică a aplicației, permițând
dezvoltarea, în treținerea și testare separată a celor două părți. În Figur a 4.3 este descris grafic modelul
arhitectural MVC. Acest model împarte un sistem software în trei părți, și anume: controller, view și
model.
Modelul gestionează datele sistemului software, răspu nde la interogări referitoare la stare (de
obicei solicitate de Vie w) și realizează operații de mo dificare a datelor (de obicei invocate de controller).
În cazul sistemelor bazate pe evenimente, modelul notifică observatorii (de obicei view -urile), atunci
când informația se modifică pentru ca aceștia să poată reacționa la aceste modificări.
View -ul re dă modelul într -o formă care permite interacțiunea cu utilizatorul, de obicei prin
intermediul elementelor de interfață cu utilizatorul. Pentru un singur mode l pot exista mai multe view –
uri pentru a deservi diferite scopuri. ”[30]
Controller -ul recepționează acț iunile utilizatorului și răspunde interogând modelul.
Figura 4. 3 Modelul Structural Model -View -Controller [30]
„Un sistem software care implementează modelul arhitectural MVC poate fi văz ut ca și o colecție
de triplete (model, view, controller). Fiecare triplet este responsabil de un anumit element al interfeței
grafice. ” [30]
59
4.1.8 HTML
HyperText Markup Language (HTML) este un limbaj de marcare utilizat pentru crearea paginilor
web ce pot fi afișate într -un browser . Scopul HTML este mai degrabă prezentarea informațiilor –
paragrafe, fonturi, tabele ș.a.m.d. – decât descrierea semanticii documentului. [31]
„Limbajul HTML const ă intr-o serie de etichete numite și taguri care permit form atarea modului
de afi șare a informa ției din pagina Web (folosirea unor anumite font -uri, culori si stiluri pentru text,
inserarea unor imagini sau a unor tab ele, utilizarea listelor și a formularelor etc.).
Tag-urile HTML sunt incluse între paranteze ascu tite <>, majoritatea dintre ele fiind in pereche,
tag-ul de inceput av ând sintaxa <..> i iar tag -ul de sfarsit </..> . Unele dintre tag -urile HTML permit
precizarea unor caracteristici ale elementului pe care îl introduc, sub forma caracteristic ă=valoare, aceste
caracteristici fiind numite atribute. O eti chetă poate avea unul, nici unul, sau mai multe atribute.
Conținutul unui document HTML nu este case -sensit ive, cu alte cuvinte nu se face diferen ța între litere
mari și mici la nivelul etichetelor si atrib utelor, însă valoarea unui atribut poate fi case -sensitive, cum
este cazul loca țiilor fi șierelor si adreselor URL.
Un document HTML este un fi șier care are extensia .htm sau .html. Pentru editarea textului unui
document HTML pot fi folosite orice tipuri d e editoare, incep ând cu editoare simple cum ar fi Notepad,
Textpad și ajung ând la editoare mai complexe cum ar fi Macromedia Dreamweaver.
Două dintre tr ăsăturile de baz ă ale unui document HTML sunt independen ța față de platform ă și
legăturile hypertext (h yperlink -uri). Independen ța față de platform ă este o tr ăsătură care permite ca
documentul HTML s ă fie afi șat în mod asem ănător pe diferite calculatoare din p unct de vedere al graficii,
fontului, culorii, lucru extrem de esen țial pentru un num ăr mare de viz itatori. Totu și, interpretarea c odului
HTML poate s ă fie diferit ă în func ție de tipul de browser Web utilizat. Astfel un document HTML poate
fi afi șat de c ătre un browser Internet Explorer într-un anumit fel, iar de c ătre alt browser (sper exemplu
Mozilla Firefox) în alt fel. Hyperlink -urile au o importan ță major ă în cadrul unui site Web, întruc ât permit
ca orice cuv ânt, fraz ă, imagine sau element al unei pag ini Web s ă facă referire la o alt ă pagin ă Web sau
chiar la paragrafe din interiorul aceleia și pagin i, realiz ându-se astfel navigare a cu u șurință între paginile
unui site Web sau între p ărțile componente ale aceleia și pagini. ” [32]
4.1.9 CSS
Primele variante ale limbajului HTML nu prezentau etichete pentru formatarea conținutului
paginii web, scopul limbajului fiind doar acela de a descrie conținut ului paginii sub forma: <h1>Aceasta
un header <h1>, <p>Acesta este un paragraf</p>. Odată cu apariția versiunii HTML 3. 2, în care au fost
introduse etichete precum <font> dar și atributele pentru specificarea culorii, procesul de dezvoltare a
site-urilor we b cu multe pagini a devenit unul greoi doarece era necesară introducerea informațiilor
referitoare la font și la culoa re pentru fiecare pagină în parte. Au apărut astfel cazurile defavorabile în
care aceleaș i informații erau introduse separat în mai multe fișiere cu extensia html asociate site -ului
60
web. Pentru ca timpul pierdut în realizarea acestei operații să poată fi e liminat W3C a creat CSS,
Cascading Style Sheets . [33]
„CSS (Cascading Style Sheets), în română având denumirea foi de stil in cascad ă, reprezint ă un
limbaj d e stilizare care permite formatarea elementelor unui document scris intr -un limbaj de marcare
(HTML, XML etc.). Codul HTML se utilizeaz ă, de obicei, pentru plasarea con ținutului în pagina WEB,
detaliile legate de afi șare (culori, font -uri, fundaluri, margi ni, etc. ) fiind asigurate de elementele CSS.
CSS este conceput în primul rând pentru a oferi posibilitatea separ ării documentului ca și conținut
(scris în HTML sau un Markup Language sim ilar) de documentul de prezentare (scris în CSS). Această
separare î mbunătățeste accesibilitatea conținutului, ofer ă o mai mare flexibilitate și asigur ă un control
mai simplu al modului de prezentare al ele mentelor HTML. Aplicarea foilor de stil în cascadă asupra
codului HTML se poate face în mai multe mo duri: stiluri în l inie, stiluri interne, stiluri externe sau clase
CSS. ” [32]
4.1.10 EJS – Embedded Javascript Templates
În primul rând, un template engine (motor de șablon are) este un instrument care permite
dezvoltatorilor de HTML, alături de funcțiile acestuia , să introducă variabile în fereastr a vizibilă de
afișare sau să execute o anumită logică de programare la execuție, înainte de a trimite fișierul HT ML
final în browser pentru afișare.
EJS înse amnă pur și simplu JavaScript Încorporat . Este un limbaj/motor de șablonare care permite
utilizato rului să genereze HTML cu Javascript simplu. Acest oferă o modalitate mai ușoară de a
concatena șirurile de carac tere trimise către afișare. Practic putem leg a diferite variabile utilizate în partea
de backend a aplicației cu partea de frontend, ceea ce va fi vizibil pentru utilizator.
Sintaxele utilizate în codul HTML sunt următoarele:
• <% %>: Aceasta este folosită pentru a încorpora codurile Javascript care fie returnează ceva, fie
verificare unor condiții, de clararea variabilelor și multe altele;
• <%= %> : Aceasta este folosită pentru a încorpora codul din partea de backend care se presupune
că va fi o expre sie folosită pe partea de „view” la rulare;
• <%# %>: A ceasta este folosită pentru a include comentarii.
61
4.2 Descrierea aplicației dezvoltate
4.2.1 Configurarea inițială
Pentru a rula o aplicație web, un prim lucru util este crearea unui server local . Un server web
virtual rulează pe propriul computer cu ajutorul unui server software. Crearea unui astfel de server virtual
este folositoare deoarece ne permite să testăm caractersticile oricărei aplicații web dezvoltate.
Întreg codul pentru această apli cație a fost scris în editorul de cod Visual Studio C ode.
Pentru început am instalat mediul de execuție Node.js care are la bază limbajul JavaScript.
Înainte, numai browserele web ca Google Chrome puteau citi și executa cod JavaScript. Pentru Chrome,
acest interpretor care se ocupa de acest lucru este numit V8. Noua caracteristică care a făcut Node atât
de popular este ca permite rularea codului JavaScr ipt pe toate mașinile – ceea ce înseamnă că browserul
nu mai reprezintă o restricție pentru executarea co dului JavaScript . Din punctul meu de vedere, Node
este cea mai bună opțiune de a construi un server simplu pentru toate tipurile de aplicații.
Apoi, a m instalat toate dependențele necesare aplicației noastre. Toate acestea se instalează
utilizând NPM (Nod e Packet Manager) , care este managerul oficial de pa chete pentru Node și este
asociat și instalat automat cu mediul , utilizând comanda „npm init”. Toa te aceste dependențe se vor
descărca în folderul node_modules utilizând comanda „npm install [nume_pache t]” și vor fi trecute în
fișierul de configurare al a plicației package.json cum se poate vedea și în F igura 4.4.
Figura 4. 4 Configurarea aplicației web
62
Fișierul package.json servește ca o documentație în ceea ce privește pachetele folosite în proiect.
Totodată ne permite să specificăm versiunile unui pachet folosit în aplicație, a cest fișier fiind foarte ușor
de împăr țit cu alți dezvoltatori.
Apoi am creat fișierul ce ține de partea de server a aplicației intitul at app.js.
Figura 4. 5 Inițial izare s erver web
Pe linia 1, respectiv 2, am importat în cadrul acestui fișier framework -ul expr ess, cât și partea
de controller din modelul arhitectural MVC discutat anterior. Pe linia 3 am creat aplicația express
atribuind -o variabilei app. În cele din urmă am inițializat rutele pentru views (parte a MVC), cât și
rutele publice în care vom stoca to ate fișierele ce țin de partea de design a aplicației.
Figura 4. 6 Lansarea aplicației și configurarea portului
Apoi, iniția lizăm controllerul numit loraController și în final metoda listen va lega aplicația
creată de port ul dorit, respectiv 3000.
4.2.2 Recepționarea datelor din TTN via protocolul HTTP
Pentru a avea acces la datele noastre, putem integra diverse diverse ser vicii externe aplicației
din TTN, printre care și integrarea clasică HTTP. Aceasta ne permite să t rimitem pachetele de date de
la noduri către un punct final prin intermediul protocolului HTTP . Pentru aceasta am configurat o
63
metodă de POST prin care vom tr imite întregul pachet de date în standardul JSON (JavaScript O bject
Notation) către un URL al apli cației create.
În cadrul controllerului din aplicație acest lucru se face folosind metoda de POST, având
parametru l jsonParser, cum se poate vedea și în Figu ra 4.7.
Figura 4. 7 Recepționarea datelor din TTN via HTTP
4.2.3 I ntegrarea bazei de date MongoDB
Întregul pachet de date recepționat de aplicație prin metoda POST va fi stocat sub forma unui
document într -o bază de date M ongoDB. MongoDB stochează datele sub formă de documente JSON
cu scheme dinamice. Pentru a avea acc es oriunde la baza de date , am creat un un Cluster pe platforma
oficială de Cloud a MongoDB. Acest Cluster este hostat pe serverele din Europa a Amazon Web
Services și suportă o stocare totală a datelor de 512 MegaOcteți.
Conexiunea la această bază de dat e, mai exact cluster, se realiz ează în felul următor , unde
DATABASE_URL reprezintă adresa către clusterul de pe serverul AWS :
Figura 4. 8 Conexiunea la MongoDB
Apoi, am creat o schemă în baza de date MongoDB în care specific ăm fiecare câmp și tipul
acestu ia al pachetului JSON care va fi stocat, în felul următor (schema conține mult mai multe câmpuri):
64
Figura 4. 9 Declarea schemei în MongoDB
Un document complet stocat în baza de date vă ar ăta în felul următor:
Figura 4. 10 Stocarea unui pachet complet în baza de date
Pentru afișarea acestora se va utiliza metoda de G ET, în care vom face o randare a documentelor
din baza de date către fereastra de vizualizare, ast fel:
Figura 4. 11 Listarea documentelor utilizând metoda GET
4.2.4 Afișarea datelor folosind Șablonul EJS
65
Pentru a avea acces în paginile de vizualizare (views din modelul structural MVC) la
documentele din baza de date, în metoda de GET descrisă mai sus, parcurgem toate documentele din
baza de date și vom face o randare a acestora, în felul următor (unde variabila data conține toate
documentele ale bazei de date) :
Figura 4. 12 Randarea variabil elor în interfața WEB
În paginile HTML de views vom integra codul EJS pentru a avea acces la varibilele din partea de
controller. În exemplul de mai jos se fa face o afișare a ultimei temperaturi a primului nod, unde
loramodels reprezintă toate document ele din baza de date, iar length numărul de documente din aceasta.
Figura 4. 13 Integrarea codului EJS în HTML
Designul acesto r pagini a fost făcut intregral folosind limbajul CSS, cât și frameworkul
Bootstrap.
4.2.5 Integr area graficelor în aplicație
Pentru a observa o evoluție explicită a diverșilor parametrii, am implementat diverse grafice în
aplicație, utilizând bibliotec a Plotly.JS.
Am creat pentru toți cei 4 parametrii de la cele două noduri, câte un grafic în care se observă
evoluția acestora în timp, pentru fiecare din cele 2 noduri. Spre exemplu, generarea graficului
temperaturilor de la cele două noduri am facut -o în felul următor:
66
Figura 4. 14 Trasarea graficului folosind Plotly.JS
Integrarea acestora se face în pagina HTML dorită, în cazul nostru în pagina „ \graphs”.
4.3 Interacțiunea cu utilizatorul
Pagina princip ală a aplicați ei web arată în felul următor:
67
Figura 4. 15 Pagina principală a apl icației web
Am ales să creez o interfață cât mai minimalistă și ușor de interacționat cu utilizatorul. În partea
de sus se regăsește un logo, timpul actual, data actuală, cât și 4 butoane către paginile: Istoric Nod 1,
Istoric Nod2, Vizualizare grafice ș i Despre Proiect.
În tabelul central se regăsesc în partea sus locația, cât și cele mai recente temperaturi detectate
de senzorii celor două noduri. În partea de jos, se regăsesc umiditatea, dista nța până la apă, cât și alerta
nivelului de apă de la senzor ul de nivel de la cele 2 noduri.
Paginile celor unde se poate vizualiza Istoricul celor 2 noduri arată în felul următor (vom
exemplifica doar pentru Nodul 1, pentru 2 totul fiind similar):
68
Figur a 4. 16 Istoricul Nodului 1
În partea de sus avem link -urile către Istoricul Nodului 2, către Grafice și către Pagina
Principală.
Mai jos avem valorile medii ale parametrilor de la senzori , cât și un loc unde se va spefica o
stare a sistemului: Stare ok/ Stare de pericol. Apoi, avem is toricul complet al parametrilor preluați de la
senzori. Practic această este o interogare completă a bazei de date .
69
Pagina de Vizualizare a gra ficelor cuprinde în partea de sus un b uton de Generare grafice(se vor
construi cele 4 grafice în m od automat cu valorile din baza de date), cât și link -urile către Istoricul
Nodului 1 și 2, cât și către Pagina Principală.
Figura 4. 17 Exemplu de grafic implementat în aplicație
Se va face o analiză a parametrilor și d acă este detectată o situație de ur gență, o alertă va apărea
în cadrul aplicației.
70
Figura 4. 18 Alertă în caz de urgență
De asemenea, aplicația dispune și de o pagină despre care cuprinde un scurt rezumat al
întregului pro iect.
Figura 4. 19 Descrierea proiectului în aplicația web
71
REZULTATE
Sistem ul integrat de monitorizare și prevenție a sit uațiilor de urgență folosind tehnologia LoRa
poate avea o multitudine de s cenarii de aplicabilitate. Menționez că t oate rezu ltatele obț inute în cadrul
acestei lucrăr i au fost obți nute experimental.
Am ales LoRa ca tehn ologie de transmisie a datelor datorită perfor manțelor de ne egalat privind
distanța la care poate transmite către o sta ție de bază, precum si consumului mic de curent la fiecare
transmisiune , avantaj de care această te hnologie beneficiaz ă.
Scenari ile cel e mai adecvate pentru utilizarea acestui s istem constau în ariile unde nu avem acces
la internet , precum c âmpurile deschise, ia r utilizarea unui modul 3 G/LTE este foar te ineficient din punct
de vedere energe tic. O reț ea a acestui sistem e ste formată dintr -o stație de baz ă și poate con ține zeci de
noduri de la care se p oate fac e o achizi ție a datelor. Avantaju l cel mai mare este că avem nevoie de
internet doar la stația de bază pentru a trimite datele noastre că tre un server sau aplicație. În res t, toată
comunicația se face prin mod ulație LoRa.
Ceea ce m -a impresionat cel mai mult la acest proiect, sunt testele efec tuate în scopul măsurării
distan ței de transmisiune a un ui pachet de date. Din ca drul Campus ului Leu, cu un nod de tran smisie
LoRa al acestui proiect am putu t trimite date către gatewa y-uri amplasate pe Calea Vict oriei, ba chiar
unul la Piața Unirii, ceea ce pentru mediul ur ban est e extrao rdinar (reprezintă o distanță de circa 5 km).
În urma unei estimări , în c âmp deschis, acest e noduri ar putea transmite pe distanțe reale de circa 8 -10
km, doar utiliz ând modulația LoRa. Singurul defect al a cestui tip de transmisie este faptul c ă intervalul
minim de timp între dou ă transmis iuni, dacă ținem cont de reglementări bineînțeles, este undeva la 2
minute. Dar în majoritatea scenariilo r de aplicabilit ate pu tem configura nodurile s ă transmit ă date la
intervale de 5 sau 10 minute, ceea ce ar spo ri și durata de viaț ă a eventualei baterii conectate.
Un prim scenar iu este cel exemplificat în lucrare și anu me un sistem integrat de monitorizare și
o prevenție timpurie a inundațiilor . Presupunem c ă există un r âu, având un debit foarte mare al apei către
un punct de vărsa re intr-o zonă predis pusă la i nundaț ii din punct de vedere al evenimentelor din trecut.
Se pot amplasa mai multe no duri în zone diversificate ale punctului de văr sare pentru a urmări di verși
parametrii . În aplicația exe mplificată, dispunând de acesți senzori, putem monitoriza temperatura,
umid itatea, distanța până la apă dintr -un punct fix uti lizând un senzor ultra sonic de distan ță, cât și nivelul
actual al a pei folosind senzorul de nivel. Astfel putem prez ice eventualele situații de urgen ță care ar putea
produce pagube mari p rin poten țialele lor d istructive.
Un alt scenar iu poate fi considerat un sistem de p revenție și alertă în scurt timp a incendii lor.
Nodul nostru este unul modular în sensul c ă putem dispune de aproape orice ti p de senzor pe ace sta, b a
chiar până la 5-6 senzori per nod. In acest scenar iu sugerat, putem dispune de senzor i de fum, de
temperatură , precum și alții (precum cei de calitate a aerului ) care ne -ar putea ajuta în prezicerea
eventualelor incendii . Cu o cutie adecvată pentru protec ția nodurilor, acest si stem integrat ar putea face
față aproape oric ărei situa ții critice.
72
CONCLUZII ȘI PERSPECTIVE
Sistem ul integrat de monitorizare și prevenție a sit uațiilor de urgență folosind tehnologia LoRa
poate reprezenta o solu ție pentru diver se domenii unde es te necesar ă o m onitorizare a un or parametrii
critici , unde nu avem ac ces la internet și ne dorim o eficien ță energetic ă cât mai mare. Consider că
proiectul a reușit să îndeplinească toate cerințele specificate inițial, totodată existând posibilitatea de a
puta fi adaptat mai multor scenarii de aplicabilitate, cum a m vorbit și mai sus. De asemenea, pe întreaga
perioad ă de lucru în cadrul proiectului am întâmpinat destule probleme de la faptul c ă gateway -ul nu era
vizibil p ână la probleme ce țin de cap tarea datelor din TTN, situa ție la care am stat c âteva zile pentru a
găsi o soluție adecvat ă.
O primă concluzie ce poate fi desprins ă în urma acestui proiect este eficien ța de care dispu ne a
transmisiunilor, at ât prin distan țele maxime la care pot comunica nodurile cu stația de bază, cât și prin
consumul redus de curent. Trans mițătorul SX1276 ut ilizat în acest proiec t necesită undeva la 10 mA
pentru fiecare transmisiune.
O a doua concluzie care se poate extrage din acest proiect este modularitatea de care dispune
acest a și adaptarea sa c ătre alte medii de utilizare. Putem trimite date de la aproape orice senzori
implementa ți în cadrul nodurilor noastre, ba chiar p utem face și o analiz ă locală prin care putem transmite
spre exemplu o medie a 5 valori m ăsurate, ex tinzând astfel și mai mult durata de via ță a bateriei
dispozitivelor. De aseme nea și aplicaț ia web poate fi a daptată în orice direcți e, în funcție de mediul de
aplicabilitate.
Din punct de vedere al costurilor de implementare a proiectului, acestea s -au ridicat undeva la
800 RON, însă nu am căutat pre țul cel mai mic (puteam cumpă ra din surse externe ), însă am vrut să am
acces c ât mai rapid la componentele hardware . Pot spune c ă este o sum ă acceptabil ă, fiindc ă am putu t
realiza un sistem ce are la bază o rețea co mpletă de co munica ție LoRaWAN , format ă din stația de ba ză
și cele 2 noduri aferente .
O eventua lă îmbunătă țire a proiectului ar putea fi implementarea unor panouri fotovoltaice care
ar avea capacitatea de a încărca bateria nodurilor periodic, duc ând astfel la o durată de viaț ă, teor etic, de
până la zeci de ani. Aceast ă sursă de a limentare cu energie elec trică o consider a fi cea mai ef icient ă dac ă
nodu rile sunt dispu se în spații deschise, unde lumina s oarelui este suficientă. O altă îmbunătă țire ce ține
tot de noduri , constă în rea lizarea un ei carcase pentru a proteja componentele fizice ale acestui a care nu
sunt c onstruite pentru a rezista la condiții extreme de me diu.
Ca o ultim ă concluzie , pot afirma că am realizat acest proiect p rin combinarea mai mult or
tehnologii de actuali tate pintre care tehnologia car e stă la baza comunicației dispozitivelor utiliza te și
anume Lo Ra, cât și dezvoltarea unei aplicații web care face legătura cu sistemul nostru fizic utiliz ând
mediul de e xecu ție Node.J S, al ături de fram ework -urile sale de actualitate , cât și baza de date non –
relațională MongoDB.
73
BIBLIOGRAFIE
[1] – The Evolution of the Internet of Things http://www.tij.co .jp/jp/lit/ml/swrb028/swrb028.pdf
[2] – TECHNOLOGY PILLARS FOR ALL THINGS IoT https://www.mouser.com/empowering –
innovation/All -Things -IoT
[3] – Internet of Things (IoT) connected devices https://www.statista.com/statistics/471264/iot –
number -of-connected -devices -worldwide/
[4] – Connectivity Te chnologies for IoT https://www.telenorconn exion.com/connectivity –
technologies -for-iot/
[5] – IoT Architecture https://www.javatpoint.com/iot -architecture -models
[6] – Mikhaylov, K., Petaejaejaervi, J., & Haenninen, T. (2016, May ). Analysis of capacity and
scalability of the LoRa low power wide area network technology. In European Wireless 2016;
22th Europe an Wireless Conference (pp. 1 -6). VDE.
[7] – Petajajarvi, J., Mikhaylov, K., Ro ivainen, A., Hanninen, T., & Pettissalo, M. (2 015,
December). On the coverage of LPWANs: range evaluation and channel attenuation model for
LoRa technology. In 2015 14th Intern ational Conference on ITS Telecommunications (ITST)
(pp. 55 -59). IEEE.
[8] – The Things Network Documentation https://www.thethingsnetwork.org/docs/lorawan/
[9] – LoRaWAN™ S ECURITY for T he LoRa ALLIANCE https://lora –
alliance.org/sites/default/files/2019 -05/lorawan_security_whitepaper.pdf
[10] – Connectivity Technologies for IoT https://www.telenorconnexion.com/connectivity –
technologi es-for-iot/
[11] – Primii pași în utilizarea plăcii Raspberry Pi 3 https://blog.robofun.ro/2017/04/18/primii -pasi-
in-utilizarea -placii -raspberry -pi-3/
[12] – Raspberry Pi LoRa/GPS HAT https://www.robofun.ro/raspberry -pi-lora-gps-hat?search=lora
[13] – SX1276/77/78/79 – 137 MHz to 1020 MHz Low Power Long Range Transceiver
https://www.mouser.com/ds/2/761/sx1276 -1278113.pdf
[14] – Curs 4 Mic rocontrolere și automate programabile , prof . Bratu Cristian, Universitatea din
Craiova http://retele.elth.ucv.ro/Bratu%20Cristian/MAP/004%20 -%20Curs%20004%20 –
%20MAP%20 -%20Arduino.pdf
[15] – LoRa Shield for Arduino http://www.dragino.com/products/module/item/102 -lora-shield.html
[16] – Modul Senzor de Temperatura și Umiditate DHT11 https://www.optimusdigital.ro/ro/senzori –
senzori -de-temperatura/99 -senzor -de-temperatura -si-si-umiditate -dht11.html
[17] – Principiul ultrasonic https://www.se nzori -ultrasonici.ro/principiul -ultrasonic
[18] – HC-SR04 ultrasonic sensor https://www.optimusdigita l.ro/en/ultrasonic -sensors/9 -hc-sr04-
ultrasonic -senso r.html
74
[19] – Senzor de nivel al apei https://www.optimusdigital.ro/ro/senzori -altele/2 72-senzor -de-nivel –
al-apei.html
[20] – Îndrumător laborator microcon trolere ARDUINO , Sebastian Petru SABOU , Editura
U.T.PRESS https://biblioteca.utcluj.ro/files/carti -online -cu-coperta/341 -7.pdf
[21] – Arduino -LMIC library https://github.com/matthijskooijman/arduino -lmic
[22] – Introducere în JavaScript
http://laurian.ro/wordpress/wp -conte nt/uploads/2013/JavaScript_a5.pdf
[23] – Noțiuni de bază JavaScript
https://developer.mo zilla.org/ro/docs/Learn/Getting_started_with_the_web/JavaSc ript_basics
[24] – Introducere în Express/Node https://developer.mozilla.org/ro/docs/Learn/Server –
side/Express_Nodejs/Introduction
[25] – Laborator 07 – Invocarea de Servicii Web prin Protocolul HTTP , cursul de Elemente de
Inform atică Mobil ă, Drago ș Niculescu, Computer and Science D epartment UPB –
https://ocw.cs.pub.ro/courses/eim/la boratoare/laborator07
[26] – Tools to Simulate HTTP Requests https://ubidots.com/blog/top -3-online -tools -for-simulating –
http-requests/
[27] – Learn REST: A Tutori al http://rest.elkstein.org/2008/02/what -is-rest.html
[28] – The Java EE 6 Tutorial https://docs.oracle.com/javaee/6 /tutorial/doc/gijqy.html
[29] – MongoDB https://ro.wikipedia.org/wiki/MongoDB
[30] – Curs 11 – Model e Arhitecturale Care Asigură Separarea , Proiectarea Sistemelor Software
Complexe , Unive rsitatea Pol itehnic ă Timi șoara
http://www.aut.upt.ro/staff/diercan/data/PSSC/curs -11.pdf
[31] – HyperText Ma rkup Language https://ro.wikipedia.org/wiki/HyperText_Markup_Language
[32] – Introducere in HTML si CSS http://www.aut.upt.ro/~andreea.robu/Lab1_PAI.pdf
[33] – CSS Introduction https://www.w3schools.com/css/css_intro.asp
75
ANEXA 1 – Codul sursă pentru tran smiterea pachet ului de date de la nodul
1, folosind tehnologia LoR a
Programu l are la baz ă codul u rmător de H elloWorld de pe Git Hub
[https://github.com/SensorsIot/LoRa/blob/master/Nodes/Dragino/HelloWorld/HelloWorld.ino ].
Acesta este un simplu program prin care se transmite un mes aj „hi”.
Însă, acesta este doar un punct de plecare în realizarea programului. Am adaptat codul în
întregime pentru a transmite un payload util către TTN. Am creat noi funcții în intregime si mi -am
construit payload -ul cu datele obținute de la senzorii con ectați pe mo dul. De asemenea, am realizat și un
workaround , fiindc ă aveam nevoie să tra nsmit doar pe o singură frecvență și un singur factor de
împr ăștiere (limitare a g ateway -ului construit ), am adus modific ări în librăria LMIC pentru a transmite
doar pe frecvenț a de 868. 3 MHz, și totodată dezact ivând celelalte canal e.
Codul este urm ătorul:
// MIT License
// https://github.com/gonzalocasas/arduino -uno-dragino-lorawan/blob/master/L ICENSE
// Based on examples from https://github.com/matthijskooijman/arduino -lmic
// Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
// Adaptions: Andreas Spiess
#include <lmic.h>
#include <hal/hal.h>
//#include <credentials.h>
#include <dht11.h>
#ifdef CREDENTIALS
static const u1_t NWKSKEY[16] = { 0x66, 0x9F, 0xAC, 0x DA, 0x8E, 0x41, 0x4E, 0x7B, 0x44, 0x0B,
0x2C, 0x11, 0x98, 0x23, 0xAA, 0x91 };
static const u1_t APPSKEY[16] = { 0xA4, 0xC3, 0xC0, 0x32, 0xB1, 0x33, 0x4B, 0x59, 0x3D, 0x62,
0x37, 0x 67, 0xD7, 0x0B, 0x81, 0xE1 };
static const u4_t DEVADDR = 0x2601163D;
#else
/*static const u1_t NWKSKEY[16] =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static const u1_t APPSKEY[16] =
{0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static const u4_t DEVADD R = 0x00000000;
*/
static const u1_t NWKSKEY[16] = { 0x66, 0x9F, 0xAC, 0xDA, 0x8E, 0x41, 0x4E, 0x7B, 0x44, 0x0B,
0x2C, 0x11, 0x98, 0x23, 0xAA, 0x91 };
static const u1_t APPSKEY[16] = { 0xA4, 0xC3, 0xC0, 0x32, 0xB1, 0x33, 0x4B, 0x59, 0x3D, 0x62,
0x37, 0x67, 0xD7, 0x0B, 0x81, 0xE1 };
static const u4_t DEVADDR = 0x2601163D;
#endif
// These callbacks are only used in over -the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in config.h, otherwis e the linker will c omplain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }
static osjob_t sendjob;
// Schedule TX every this many seconds (might become longer due to duty
76
// cycle limitations).
const unsigned TX_INTER VAL = 297; //897
// Pin mapping Dragino Shield
const lmic_pinmap lmic_pins = {
.nss = 10,
.rxtx = LMIC_UNUSED_PIN,
.rst = 9,
.dio = {2, 6, 7},
};
// Pin mapping DHT11 SENSOR
#define DHT11PIN 5
dht11 DHT11;
//Pin mappin g for Ultrasonic sensor
int trig = 3;
int echo = 4;
long lecture_echo;
long cm;
void setup() {
//Pins for Ultrasonic sensor
pinMode(trig, OUTPUT);
digitalWrite(trig, LOW);
pinMode(echo, INPUT);
Serial.begin( 115200);
Serial.println(F("Starting…"));
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// Set static session parameters.
LMIC_setSession (0x1, DEVADDR, N WKSKEY, APPS KEY);
// Disable link check validation
LMIC_setLinkCheckMode(0);
Serial.println("European Channels");
// for (int i = 1; i <= 8; i++) LMIC_disableChannel(i);
#define CHANNEL 0
for (uint8_t i = 0; i < 9; i++) {
if (i != CHANNE L) {
LMIC_disableChannel(i);
}
}
// TTN uses SF9 for its RX2 window.
LMIC.dn2Dr = DR_SF9;
// Set data rate and transmit power for uplink (note: txpow seems to be ignored by the
library)
//LMIC_setDrTxpow(DR_SF12,14);
LMIC_setDrTxpow(DR_SF12,14);
// Start job
77
do_send(&sendjob);
}
void onEvent (ev_t ev) {
if (ev == EV_TXCOMPLETE) {
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
}
}
void do_send(osjob_t* j){
// Payload to send (uplink)
//static uint8_t message[] = "1234567890abcdefGHIJabcdefq";
//Serial.println(sizeof(message) -1);
byte payload[7];
int temperature, humidity, is_water, distance;
temperature = readTemp();
humidity = readHum();
is_water = readWat er();
distance = readDistance();
Serial.print("Values \n");
Serial.println(temperature);
Serial.println(humidity);
Serial.println(distance);
Serial.println(sizeof(temperature));
// Check if there is not a current TX/RX jo b running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
payload[0] = temperature >> 8;
payload[1] = temperat ure & 0xFF;
payload[2] = humidity >> 8;
payload[3] = humidity & 0xFF;
payload[4] = is _water & 0xFF;
payload[5] = distance >> 8;
payload[6] = distance & 0xFF;
LMIC_setTxData2(1, payload, sizeof(payload), 0); // 1 is the port
Serial.println(F("Sending uplink packet…"));
}
// Next TX is scheduled aft er TX_COMPLETE event.
}
float readTempInCelsius(int count, int pin) {
float temperatu raMediata = 0;
float sumaTemperatura = 0;
for (int i =0; i < count; i++) {
int reading = analogRead(pin);
float voltage = reading * 2.5; // * 5.0 fara senz or apa
voltage /= 1024.0;
float temperatureCelsius = (voltage – 0.5) * 100 ;
sumaTemperatura = sumaTemperatura + temperatureCelsius;
}
return sumaTemperatura / (float)count;
}
int readWater()
{
78
int sensorValue = analogRead(A1);
Serial.print("Water sensor value: ");
Serial.println(sensorValue);
if(sensorValue <= 500) r eturn 0;
else if(sensorValue <= 600) return 1;
else if(sensorValue <= 650) return 2;
else if(sensorValue > 650) return 3;
}
int readTemp()
{
int chk = DHT11. read(DHT11PIN);
Serial.print("Temperature (C): ");
Serial.println((float)DHT11.temperature, 2);
return (int)DHT11.temperature;
}
int readHum()
{
int chk = DHT11.read(DHT11PIN);
Serial.print("Humidity (%): ");
Serial.println((float)DHT11.h umidity, 2);
return (int)DHT11.humidity;
}
int readDistance()
{
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
lecture_echo = pulseIn(echo, HIGH);
cm = lecture_echo / 58;
Serial.print("Distance in cm : ");
Serial.println(cm);
return cm;
}
void loop() {
os_runloop_once();
}
79
ANEXA 2 – Codurile sur să ale aplicației W eb
Aplicația a fost în întregime creată de mine , parcurg ând bineînțeles documenta țiile pachetelor ale
mediului de execuție Node.JS. Sin gurele contribu ții externe sunt cele ce țin de de des ignul aplicației. M-
am folosi t de diverse șabloane și proprietă ți CSS din pachete exter ne. Am încercat s ă le combin și s ă le
modific pr opriet ățile astfel încât aplicația s ă aibă un aspect c ât mai minimal ist și s ă poată fi ma nipulată
cu ușurin ță de orice utilizat or.
Fișierul app.js :
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}
const express = require('express')
const loraController = require('./controllers/loraControll er')
const app = express()
// Set up template engine
app.set('view engine', 'ejs')
// Static files
app.use(express.static('./public'))
// Fire Controllers
loraController(app)
// Listen to port
app.listen(process.env.PORT || 3000)
console.log('You are listening to port 3000')
Fișierul loraController .js :
const bodyParser = require('body -parser')
const mongoose = require('mongoose')
// Connect to the database
//mongoose.connect('mongodb+srv://test:test@cluster0 –
8rgpi.mongodb.net/test?retryWrites=tr ue&w=majority', { useNewUrlParser: true })
mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true})
const db = mongoose.connection
db.on('error', error => console.error(error))
db.once('open', () => console.log('Connected to Mongoose'))
// Create a schema – this is like a blueprint
const loraSchema = new mongoose.Schema({
app_id: {
type: String,
required: true
},
dev_id: {
type: String,
required:true
},
hardware_serial: {
type: String,
80
required: true
},
port: {
type: Number,
required: true
},
counter: {
type: Number,
required: true
},
payload_raw: {
type: String,
required: true
},
payload_fields: {
type: Object,
required: true
},
metadata: {
type: Object,
required: true
},
downlink_url: {
type: String,
required: true
}
})
// Create a model
const loraModel = mongoose.model('loraModel' , loraSchema)
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var jsonParser = bodyParser.json()
module.exports = function(app) {
app.get('/main', (req, res) => {
// Get data from mongdo db and pass it to view
loraModel.find({} , (err, data) =>{
if (err) throw err
let temp= [];
let dist= [];
let waterAlert= [];
let i = -1;
let waSum = 0;
data.forEach( (item) => {
temp[i] = (item.payload_fields && item.payload_fi elds.temperature)
dist[i] = (item.payload_fields && item.payload_fields.distance)
waterAlert[i] = (item.payload_fields && item.payload_fields.water_alert)
waSum = waSum + (item.payload_fields && item.payload_fields.water _alert)
i++;
})
waMean = waSum / i;
waLast = waterAlert[i -1];
res.render('main', {
loramodels: data,
length: data.length,
waMean: waMean,
waLast: waLast,
81
tables_1: "/tables_1",
tables_2: "/tables_2",
graphs: "/graphs",
about: "/about"
})
})
})
app.post('/main', jsonParser, (req, res) => {
// Get data from the view and add it to mongodb
let newlo raModel = loraModel(req.body).save( (err,data) =>{
if (err) throw err
res.json(data)
console.log(req.body)
})
//data.push(req.body)
})
app.get('/about', (req, res) => {
res.render('about' , {
tables_1: "/tables _1",
tables_2: "/tables_2",
graphs: "/graphs",
main: "/main"
})
})
app.get('/shop', (req, res) => {
res.render(' shop')
})
app.get('/lora', (req, res) => {
res.render('lora')
})
app.get('/graphs', (req, res) => {
res.render('graphs', {
generate: "/generate_graphs",
tables_1: "/tables_1",
tables_2: "/tables_2",
main: "/main"
})
})
app.get('/danger', (req, res) => {
res.render('danger', {
link: "https://www.google.com/ "
})
})
app.get('/tables_1', (req, res) => {
loraModel.find({}, (err, data) =>{
if (err) throw err
//console.log("My data " + JSON.stringify(data))
//console.log("My dev_id "+ data.dev_id)
//let x = JSON.stringify(d ata[2])
//console.log(x)
let temp= [];
let dist= [];
82
let waterAlert= [];
let hum= [];
let i = -1;
let tempSum= 0, distSum = 0, humSum = 0, waSum = 0;
data.forEach( (item) => {
if(item.dev_id === "lora_1") {
temp[i] = (item.payload_fields && item.payload_fields.temperature)
tempSum = tempSum + (item.payload_fields && item.payload_fields.temperature)
dist[i] = (item.payload_fields && item.payload_f ields.distance)
distSum = distSum + (item.payload_fields && item.payload_fields.distance)
waterAlert[i] = (item.payload_fields && item.payload_fields.water_alert)
waSum = waSum + (item.payload_fields && item.payload_fiel ds.water_alert)
hum[i] = (item.payload_fields && item.payload_fields.humidity)
humSum = humSum + (item.payload_fields && item.payload_fields.humidity)
i++;
}
})
tempMean = tempSum / i;
humMean = humSum / i;
distMean = distSum / i;
waMean = waSum / i;
if(waMean < 1) state = 'Stare ok'
else state = "Stare de pericol"
res.render('tables_1', {
loramodels: data,
length: data.length,
tempMean: tempMean,
humMean: humMean,
distMean: distMean,
state: state,
tables_2: "/tables_2",
graphs: "/graphs",
main: "/main"
})
})
})
app.get('/tables_2', (req, res) => {
loraModel.find({}, (err, data) =>{
if (err) throw err
//console.log("My data " + JSON.stringify(data))
//console.log("My dev_id "+ data.dev_id)
//let x = JSON.stringify(data[2])
//console.log(x)
let temp= [];
let dist= [];
let waterAlert= [];
let hum= [];
let i = -1;
let tempSum= 0, distSum = 0, humSum = 0, waSum = 0;
data.forEach( (item) => {
if(item.dev_id = = 'lora_2') {
temp[i] = (item.payload_fields && item.payload_fields.temperature)
tempSum = tempSum + (item.payload_fields && item.payload_fields.temperature)
dist[i] = (item.payload_fields && item.payload_fields.distance )
distSum = distSum + (item.payload_fields && item.payload_fields.distance)
waterAlert[i] = (item.payload_fields && item.payload_fields.water_alert)
waSum = waSum + (item.payload_fields && item.payload_fields.water_alert)
83
hum[i] = (item.payload_fields && item.payload_fields.humidity)
humSum = humSum + (item.payload_fields && item.payload_fields.humidity)
i++;
}
})
tempMean = tempSum / i;
humMean = humSum / i;
distMean = distSum / i;
waMean = waSum / i;
if(waMean < 1) state = 'Stare ok'
else state = "Stare de pericol"
res.render('tables_2', {
loramodels: data,
length: data.length,
tempMean: tempMean,
humMean: humMean,
distMean: d istMean,
state: state,
tables_1: "/tables_1",
graphs: "/graphs",
main: "/main"
})
})
})
app.get('/generate_graph s', (req, res) => {
loraModel.find({}, (err, data) =>{
if (err) throw err
//console.log("My data " + JSON.stringify(data))
//console.log("My dev_id "+ data.dev_id)
//let x = JSON.stringify(data[2])
//console.log( x)
let temp 1= [];
let temp2= [];
let dist1= [];
let dist2= [];
let hum1= [];
let hum2= [];
let waterAlert1= [];
let waterAlert2= [];
let time1X = [];
let time2X = [];
let i = -1;
data.forEach( (item) => {
if(item.dev_id === 'lora_1') {
temp1[i] = (item.payload_fields && item.payload_fields.temperature)
hum1[i] = (item.payload_fields && item.payload_fields.humidity)
dist1[i] = (item.pa yload_fields && item.payload_fields.distance)
waterAlert1[i] = (item.payload_fields && item.payload_fields.water_alert)
time1X[i] = (item.metadata && item.metadata.time)
//console.log(temp1[i])
i++;
}
})
console.log(i)
i = -1;
data.forEach( (item) => {
84
if(item.dev_id === 'lora_2') {
temp2[i] = (item.payload_fields && item.paylo ad_fields.temperature)
hum2[i] = (item.payload_fields && item.payload_fields.humidity)
dist2[i] = (item.payload_fields && item.payload_fields.distance)
waterAlert2[i] = (item.payload_fields && item.payload_fi elds.water_alert)
time2X[i ] = (item.metadata && item.metadata.time)
//console.log(temp2[i])
i++;
}
})
plotly = require('plotly')("mihai.banica97", "NqIyhBnmXQ9PSj8dI9vc")
// Grafice Temperaturi
var trace1_temp1 = {
x: time1X,
y: temp1,
type: "scatter",
name: "Temp Nod 1"
}
var trace2_temp2 = {
x: time2X,
y: temp2,
type: "scatter",
name: "Tem p Nod 2"
}
var dataGraph = [trace1_temp1, trace2_temp2]
var graphOptions = {filename: "temperaturi", fileopt: "overwrite"};
plotly.plot(dataGraph, gr aphOptions, function (err, msg) {
console.log(msg);
});
// Grafice umiditate
var trace1_hum1 = {
x: time1X,
y: hum1,
type: "scatter",
name: "Hum Nod 1"
}
var trace2_hum2 = {
x: time2X,
y: hum2,
type: "scatter",
name: "Hum Nod 2"
}
var dataGraph = [trace1_hum1, trace2_hum2]
var graphOptions = {filename: "umiditate", fileopt: "overwrite"};
plotly.plot(dataGraph, graphOptions, function (err, msg) {
console.log(msg);
});
// Grafice distanta
var trace1_dist1 = {
x: time1X,
y: dist1,
type: "scatter",
name: "Dist Nod 1"
85
}
var trace2_dist2 = {
x: time2X,
y: dist2,
type: "scatter",
name: "Dist Nod 2"
}
var dataGraph = [trace1_dist1, trace2_dist2]
var graphOptions = {filename: "distanta", fileopt: "overwrite"};
plotly.plot(dataGr aph, graphOptions, function (err, msg) {
console.log(msg);
});
// Grafice Water Alert
var trace1_wa1 = {
x: time1X,
y: waterAlert1,
type: "scatter",
name: "WA Nod 1"
}
var trace2_wa2 = {
x: time2X,
y: waterAlert2,
type: "scatter",
name: "WA Nod 2"
}
var dataGraph = [trace1_wa1, trace2_wa2]
var graphOptions = {filename: "alerta_apa", f ileopt: "overwrite"};
plotly.plot(dataGraph, graphOptions, function (err, ms g) {
console.log(msg);
});
res.render('graphs', {
loramodels: data,
length: data.length,
generate: "/generate_graphs",
tables_1: "/tables_1",
tables_2: "/tables_2",
main: "/main"
})
})
})
}
Fișierul package.json :
{
"name": "licenta_v1",
"version": "1.0.0",
"description": "",
"main": "app.js",
86
"scripts": {
"test": "echo \"Error: no test specified \" && exit 1",
"start": "node app.js",
"devStart": "nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"dotenv": "^8. 0.0",
"ejs": "^2.6.1",
"express": "^4.17.1",
"mongoose": "^5.5.14",
"plotly": "^1.0.6"
}
}
Fișierul main .ejs :
<!DOCTYPE html>
<html>
<!–<meta http -equiv="refresh" content="5" > –>
<head>
<title>Monitorizare situatii de urgenta</titl e>
<!– bootstrap –>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0 –
beta.3/css/bootstrap.min.css" integrity="sha384 –
Zug+QiDoJOrZ5t4lssLdxGhVr urbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
<!– fontawesom e –>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font –
awesome/4.7.0/css/font -awesome.min.css">
<!– weather icons –>
<link rel="styleshe et" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/weather –
icons/2.0 .9/css/weather -icons.min.css">
<!– stylesheet –>
<link rel="stylesheet" type="text/css" href="assets/main/css/style.css">
</head>
<body>
<div class="hero">
<!– navbar –>
<nav class="navbar">
<a class="navbar -brand" href="#">
<i class=" wi wi-cloud-up" aria -hidden="true"></i>
<strong>LoRa</strong> Alert
</a>
<span id="time" class="lead">ora/data</span>
<span id="date" class="lead">ora/data</span>
</nav>
<nav>
<ul class="nav -links">
<img src="htt p://international.upb.ro/wp -content/uploads/2018/06/ sigla-UPB-
transparent.png" style="width:140px;height:140px;">
<li ><a class="nav -link" href="<%= tables_1 %>" >Istoric Nod 1</a> </li>
<p><a class="nav -link" href="<%= tables_2 %>" >Is toric Nod 2</a> </p>
<li ><a class=" nav-link" href="<%= graphs %>">Vizualizare grafice</a></li>
<li ><a class="nav -link" href="<%= about %>">Despre</a></li>
<img src="http://discipline.elcom.pub.ro/saim/index_files/image 003.gif"
style="width:140px;height:140px;">
</ul>
</nav>
<!– weather section –>
<div class="container">
87
<div class="row">
<div id="" class="col -8 mx-auto weather">
<!– weather header section –>
<div class="wea ther-head">
<h1 id="location" class="text -center display –
4">Bucuresti, RO</h1>
<div class="row">
<div id="description" class="description col -6
text-center">
<i id="icon -desc" class="wi wi -flood"></i>
<p class="des c" >Situatie nivel apa</p>
</div>
<div id="temperature" class="col -6 text-center">
<% for(var i=loramodels.length – 2; i <
loramodels.length; i++) { %>
<a>
<% if (loramodels[i].dev_id
=== "lora_1") {%>
<%=
loramode ls[i].payload_fields && loramodels[i].payload_fields.temperature%>
<i id="icon -thermometer"
class="wi wi -thermometer"></i>
</a>
<% } %>
<% } %>
<% for(var i=loramodels.l ength – 2;
i < loramodels.length; i++) { %>
<a>
<% if (loramodels[i].dev_id
=== "lora_2") {%>
<%=
loramodels[i].payload_fields && loramodels[i].payload_fields.temperature%>
<i id="icon -thermometer"
class="wi wi -thermometer"></i>
</a>
<% } %>
<% } %>
<!–<i id="icon -celsius" class="wi
wi-celsius"></i> –>
<!–<i id="icon -thermometer" class="wi wi -thermometer"></i>
–>
</div>
</div>
<!– weather body header –>
<div class="weather -body">
<div class="row">
<div class="humidity col -3 text-center">
<i class="wi wi -storm-
warning"></i><span> Nodul LoRa </span>
</div>
<div class="humidity col -3 text-center">
<i class="wi wi –
humidity"></i><span> Umiditate</span>
</div>
<div class="wind col -3 text-center">
<i class="wi wi -strong-
wind"></i><span> Distanta pan a la apa</span>
</div>
<div class="visibility col -3 text-center">
88
<i class="fa fa -eye"></i><span>
Alerta apa [0 ->3]</span>
</div>
</div>
<!– weather body data –>
<div class="row">
<div id="humidity" class="humidity -data col -3 text-center">
<% for(var i=loramodels.length – 2; i < loramodels.length; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_1") {%>
<%= loramodels[i].dev_id%>
</p>
<% } %>
<% } %>
<% for(var i=loramodels.length – 2; i <
loramodels.length; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_2") {%>
<%= loramodels[i].dev_id%>
</p>
<% } %>
<% } %>
</div>
<div id="humidity" class="humidity -data
col-3 text-center">
<% for(var i=loramodels.length – 2; i < loramodels.length; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_1") {%>
<%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.humidity%>
</p>
<% } %>
<% } %>
<% for(var i=loramodels.length – 2; i <
loramodels.length; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_2") {%>
<%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.humidity%>
</p>
<% } %>
<% } %>
</div>
<div id="wind" class="wind -data col -3
text-center">
<% for(var i=loramodels.length – 2;
i < loramodels.length ; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_1") {%>
<%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.distance%>
</p>
<% } %>
<% } %>
<% for(var i=loramodels.length – 2;
i < loramodels.length; i++) { %>
<p>
89
<% if (loramodels[i].dev_id ===
"lora_2") {%>
<%= loramodels[i].payload_fields &&
loramodels[i].paylo ad_fields.dista nce%>
</p>
<% } %>
<% } %>
</div>
<div id="visibility" class="degree -data
col-3 text-center">
<% for(var i=loramodels.length – 2;
i < loramodels.length; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_1") {%>
<%=
loramodels[i].payload_fields && loramodels[i].payload_fields.water_alert%>
</p>
<% } %>
<% } %>
<% for(var i=loramod els.length – 2;
i < loramodels.length; i++) { %>
<p>
<% if (loramodels[i].dev_id ===
"lora_2") {%>
<%=
loramodels[i].payload_fields && loramodels[i].payload_fields.water_alert%>
</p>
<% } %>
<% } %>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!– javascript file –>
<script >
window.onload = function() {
//variables
var currentDate = new D ate();
var dayNight = "day";
var today = new Date();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var dateTime =time;
//setting the date
var dateElem = document.getEl ementById("date");
dateElem.innerHTML = currentDate.toDateString();
var timeElem = document.getElementById("time");
timeElem.innerHTML = dateTime;
var a = <%= waMean %>;
var last_a = <%= waLast %>;
//console.log(last_a);
if( a > 0.3 || l ast_a > 0) {
alert('ALER TĂ, o situație de urgență a fost detectată');
// window.location.replace("danger");
// }
90
}
</script>
</body>
</html>
Fișierul tables_1 .ejs :
<!DOCTYPE html>
<html lang="en">
<head>
<title>Tabel Nod 1</title>
<meta charset="UTF -8">
<meta nam e="viewport" content="width=device -width, initial -scale=1">
<!–=============================================================================================== –
->
<link rel="icon" type="image/ png" href="assets/tables/images/icons/favicon.ico"/>
<!–=============================================================================================== –
->
<link rel="stylesheet" type="text/css"
href="assets/tables/vendor/bootstrap/css/bootstrap.min.css">
<!–========================================================= ====================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/fonts/font -awesome-4.7.0/css/font –
awesome.min.css">
<!–==================================== =========================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/vendor/animate/animate.css">
<!–=============================================================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/ven dor/select2/select2.min.css">
<!–=============================================================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/v endor/perfect -scrollbar/perfect –
scrollbar.css">
<!–========== ===================================================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/css/util.css">
<link rel="stylesheet" type=" text/css" href="assets/tables/css/main.css">
<link rel="style sheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/weather –
icons/2.0.9/css/weather -icons.min.css">
<!–========================================================================== ===================== –
->
</head>
<body>
<header>
<div class="logo -container">
<img src="https://images -wixmp-ed30a86b8c4ca887773594c2.wixmp.com/i/dcfe7691 -0ada-4a1e-
9e7d-5932ea18fe6a/dalgn2y -d128adda -4820-46f3-8adf-e7e419ab17ed.png" alt ="log"
style="width:60px;height:40px;">
<h4 class= "logo"> Baza de date Nod 1</h4>
</div>
<nav>
</a>
<ul class="nav -links">
<li ><a class="nav -link" href="<%= tables_2 %>">Istoric nod 2</a></li>
<li ><a class="nav -link" href="<%= graphs %>"> Grafice</a></li>
<li ><a class="nav -link" href="<%= main %>">Pagina principala</a></li>
</ul>
</nav>
</header>
91
<div class="limiter">
<div class="container -table100">
<div class="wrap -table100">
<div class ="table100">
<table>
<thead>
<tr class="table100 -head">
<th class="column1">Tabel Valori
Medii</th>
<th class="column2">Temperatura</th>
<th class="column3">Umiditate</th>
<th class="column4">Distanta</th>
</tr>
</thead>
<td class="column1"><%= state%></td>
<td class="column2"><%= tempMean%></td>
<td class="column3"><%= humMean%></td>
<td class="column4"><%= distMean%></td>
</tr>
</table>
<br>
<table>
<thead>
<tr class="table100 -head">
<th class="col umn1">Data</th>
<th class="column2">Nr Pachet</th>
<th class="column3">Temperatura</th>
<th class="column4">Umiditate</th>
<th class="column5">Distanta</th>
<th class="column6">Alerta nivel</th>
</tr>
</thead>
<% for (var i = loramodels.length – 1; i >= 0; i –) { %>
<% if (loramodels[i].dev_id === "lora_1") {%>
<tr>
<td class="column1"><%= loramodels[i].metadata && loramodels[i]. metadata.time%></td>
<td class="column2"><%= loramodels[i].counter %></td>
<td class="column3"><%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.temperature%></td>
<td class="column4"><%= loramodels[i].payload_fields &&
loramodels[i ].payload_fields.humidity%></td>
<td class="column5"><%= loram odels[i].payload_fields &&
loramodels[i].payload_fields.distance%></td>
<td class="column6"><%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.water_alert %></td>
</tr>
<% } %>
<% } %>
</table>
</div>
</div>
</div>
</div>
<!–=============================================================================================== –
->
92
<script src="assets/tables/vendor/jquery/jquery -3.2.1.min.js"></script>
<!–===================================================== ========================================== –
->
<script src="assets/tables/vendor/bootstrap/js/popper.js"></script>
<script src="assets/tables/vendor/bootstrap/js/bootstrap.min.js"></script>
<!–============================================================= ================================== –
->
<script src="assets/tables/vendor/select2/select2.min.js"></script>
<!–========================================================================================= ======-
->
<script src="assets/tables/js/main.js"></scri pt>
</body>
</html>
Fișierul tables_ 2.ejs :
<!DOCTYPE html>
<html lang="en">
<head>
<title>Tabel Nod 2</title>
<meta charset="UTF -8">
<meta name="viewport" content="width=device -width, initial -scale=1">
<!–=============================================================================================== –
->
<link rel="icon" type="image/png" href="assets/tables/images/icons/favicon.ico"/>
<!–======================================================= ============ ============================ –
->
<link rel="stylesheet" type="text/css"
href="assets/tables/vendor/bootstrap/css/bootstrap.min.css">
<!–=============================================================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/fonts/font -awesome-4.7.0/css/font –
awesome.min.css">
<!–===================================== ========================================================== –
->
<link rel="stylesheet" type="text/css" href="ass ets/tables/vendor/animate/animate.css">
<!–=============================================================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/vendor/select2/select2.min.css">
<!–================ =============================================================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/ve ndor/perfect -scrollbar/perfect –
scrollbar.css">
<!–============================================================ =================================== –
->
<link rel="stylesheet" type="text/css" href="assets/tables/css/util.css">
<link rel="stylesheet" type="t ext/css" href="assets/tables/css/main.css">
<!–=============================================================== ================================ –
->
</head>
<body>
<header>
<div class="logo -container">
<img src="https://images -wixmp-ed30a86b8c4ca887773594c2.wixmp.com/i/dcfe7691 -0ada-4a1e-
9e7d-5932ea18fe6a/dalgn2y -d128adda -4820-46f3-8adf-e7e419ab17 ed.png" alt="log"
style="width:60px;height:40px;">
<h4 class="logo"> Baza de date Nod 2</h4>
</div>
<nav>
</a>
93
<ul class="nav -links">
<li ><a class="nav -link" href="<%= tables_1 %>">Istoric nod 1</a></li>
<li ><a class="nav -link" href="<%= graphs %>">Grafice</a></li>
<li ><a class="nav -link" href="<%= main %>">Pagina principala</a></li>
</ul>
</nav>
</header>
<div class="limiter">
<div class="container -table100">
<div class="wrap -table100">
<div class="table100">
<table>
<thead>
<tr class="table100 -head">
<th class="column1">Tabel Valori
Medii</th>
<th class="column2">Temperatura</th>
<th class="column3">Umiditate</th>
<th class="column4">Distanta</th>
</tr>
</thead>
</tr>
<td class="column1"><%= state%></td>
<td class="column2"><%= tempMean%></td>
<td class="column3"><%= humMean%></td>
<td class= "column4"><%= distMean%></td>
</tr>
</table>
<br>
<table>
<thead>
<tr class="tabl e100-head">
<th class="column1">Data</th>
<th class="column2">Nr Pachet</th>
<th class="column3">Temperatura</th>
<th class="column4">Umiditate</th>
<th class="column5">Distanta</th>
<th class="column6">Alerta nivel</th>
</tr>
</thead>
<% for (var i = loramodels.length – 1; i >= 0; i –) { %>
<% if (loramodels[i].dev_id === " lora_2") {%>
<tr>
<td class="column1"><% = loramodels[i].metadata && loramodels[i].metadata.time%></td>
<td class="column2"><%= loramodels[i].counter%></td>
<td class="column3"><%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.temperat ure%></td>
<td class="column4"><%= lo ramodels[i].payload_fields &&
loramodels[i].payload_fields.humidity%></td>
<td class="column5"><%= loramodels[i].payload_fields &&
loramodels[i].payload_fields.distance%></td>
<td class="column6"><%= l oramodels[i].payload_fields &&
loramodels[i ].payload_fields.water_alert %></td>
</tr>
<% } %>
<% } %>
</table>
</div>
</div>
94
</div>
</div>
<!–========================================================================================= ======-
->
<script src="assets/tables/vendor/jquery/jquery -3.2.1.min.js"></script>
<!–=========================================================================== ==================== –
->
<script src="assets/tables/vendor/bootstrap/js/popper.js"></script>
<script src="assets/tables/vendor/bootstrap/js/bootstrap.min.js"></script>
<!–=================================================================================== ============ –
->
<script src="assets/tables/vendor/select2/select2.min.js"></script>
<!–=============================================================================================== –
->
<script src="assets/tables/js/main.js"></script>
</body>
</html>
Fișierul graphs .ejs :
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/c ss" href="assets/graphs/css/style.css">
</head>
<body>
<header>
<div class="logo -container">
<img src="https://images -wixmp-ed30a86b8c4ca887773594c2.wixmp.com/i/dcfe7691 -0ada-4a1e-
9e7d-5932ea18fe6a/dalgn2y -d128adda -4820-46f3-8adf-e7e419ab17ed.png" alt="log"
style="width:60px;height:40px;">
<h4 class="logo"> Grafice</h4>
</div>
<nav>
</a>
<ul class="nav -links">
<li ><a class="nav -link" href="<%= generate %>">Generare graf ice</a></li>
<li ><a class="nav -link" href="<%= tables_1 %>">Istoric nod 1</a></li>
<li ><a class="nav -link" href="<%= tables_2 %>">Istoric nod 2</a></li>
<li ><a class="nav -link" href="<%= main %>">Pagina pr incipala</a></li>
</ul>
</nav>
</header>
<h1 style="text -align:center"> Graficul temperaturii al celor 2 Noduri</h1>
<div id="NW">
<a href="https://plot.ly/~mihai.banica97/14/?share_key=tAfjmRTNgJSjIF1ADFXyLv" target="_blank"
title="temperaturi" style="display: block; text -align: center;"><img
src="https://plot.ly/~mihai.banica97 /14.png?share_key=tAfjmRTNgJSjIF1ADFXyLv" alt="temperaturi"
style="max -width: 100%;width: 600px;" width="600"
onerror="this.onerror=null;this.src='htt ps://plot.ly/404.png';" /></a>
<script data -plotly="mihai.banica97:14" sharekey -plotly="tAfjmRTNgJSjI F1ADFXyLv"
src="https://plot.ly/embed.js" async></script>
95
</div>
<h1 style="text -align:center"> Graficul umiditatii al celor 2 Noduri</h1>
<div id=" NE">
<a href="https://plot.ly/~mihai.banica97/20/?share_key=LK82xaGq6wYpyXYdDwfzhO" target="_blank"
title="umiditate" style="display: block; text -align: center;"><img
src="https://plot.ly/~mihai.banica97/20.png?share_key=LK82xaGq6wYpyXYdDwfzhO" alt="um iditate"
style="max -width: 100%;width: 600px;" width="600"
onerror="this.onerror=null;this.src='https:// plot.ly/404.png';" /></a>
<script data -plotly="mihai.banica97:20" sharekey -plotly="LK82xaGq6wYpyXYdDwfzhO"
src="https://plot.ly/embed.js" async></s cript>
</div>
<h1 style="text -align:center"> Grafic al distantei pana la apa</h1>
<div id="SE">
<a href="https://plot.ly/~mihai.banica97/18/?share_key=9nX6tsDaT16yN1xqLyXXs1" target="_blank"
title="distanta" style="display: block; text -align: center ;"><img
src="htt ps://plot.ly/~mihai.banica97/18.png?share_key=9nX6tsDaT16yN1xqLyXXs1" alt="distanta"
style="max -width: 100%;width: 600px;" width="600"
onerror="this.onerror=null;this.src='https://plot.ly/404.png';" /></a>
<script data -plotly="mihai.ba nica97:18" share key-plotly="9nX6tsDaT16yN1xqLyXXs1"
src="https://plot.ly/embed.js" async></script>
</div>
<h1 style="text -align:center"> Grafic al alertei privind nivelul de apa</h1>
<div id="SW">
<a href="https://plot.ly/~mihai.banica97/16/?share_ke y=qcPHPWugrv7bsI YTt54ke1" target="_blank"
title="alerta_apa" style="display: block; text -align: center;"><img
src="https://plot.ly/~mihai.banica97/16.png?share_key=qcPHPWugrv7bsIYTt54ke1" alt="alerta_apa"
style="max -width: 100%;width: 600px;" width="600"
onerror="this.on error=null;this.src='https://plot.ly/404.png';" /></a>
<script data -plotly="mihai.banica97:16" sharekey -plotly="qcPHPWugrv7bsIYTt54ke1"
src="https://plot.ly/embed.js" async></script>
</div>
</body>
</html>
Fișierul about .ejs :
<!DOCTYPE html>
<html>
<body>
<head>
<link rel="stylesheet" type="text/css" href="assets/about/css/style.css">
</head>
<body>
<header>
<div class="logo -container">
<img src="https://images -wixmp-ed30a86b8c4ca887773594c2.wixmp.com /i/dcfe7691 -0ada-4a1e-
9e7d-5932ea18fe6a/dalgn2y -d128adda -4820-46f3-8adf-e7e419ab17ed.png" alt="log"
style="width:60px;height:40px;">
<h4 class="logo"> Despre Proiect</h4>
96
</div>
<nav>
</a>
<ul class="nav -links">
<li ><a class="nav -link" href="<%= graphs %>">Grafice</a></li>
<li ><a class="nav -link" href="<%= tables_1 %>">Istoric nod 1</a></li>
<li ><a class="nav -link" href="<%= tables_2 %>">Istoric nod 2</a></li>
<li ><a class="nav -link" href="<%= main %>">Pagina principala</a>< /li>
</ul>
</nav>
</header>
<main>
<section class="presentation">
<div class="introduction">
<div class="intro -text">
<h1>Sistem integrat de monitorizare și prevenție a sit uațiilor de urgență
folosind tehnologia LoRa</h1>
<br>
<br>
<h2> Un proiect realizat de Bănică Mihai Valentin, 441B -ELA, ETTI </h2>
<h2> -Sub indrumarea profesorului coordonato r Ș. L. Dr. Ing. Mădălin FRUNZETE –
</h2>
<br>
<br>
<p> Lucrarea are ca scop realizarea unui sistem de detecție a uno r situații de
urgență, cât și o prevenție a acestora, proiectul fiind bazat pe o comunicare într -o rețea LoRaWAN.
Marele avantaj al acestui tip de comuncație este faptul că se pot transmite date utile pe distanțe
de ordinul kilometrilor fără a avea acces l a internet, și cu un consum de energie foarte scăzut.
</p>
<p> Rețeaua va fi compusă din noduri LoRa, cât și o stație de bază la care se
vor conecta și vor transmite date nodurile aferente. O aplicație a acestui sist em constă în
prevenirea inundațiilor folosindu -se de datele achiziționate privind volumul de apă/nivelul
acestuia.
</p>
<p> Un nod va fi compus dintr -o placă de dezvoltare, un modul de transmisie
LoRa, o antenă, cât și senzori ce țin de aplicația vizată (prevenirea inundațiilor) precum senzor de
detecție al apei, senzor cu ultrasunete pentru observarea nivelului de apă, senzor de umiditate. Se
va realiza o achiziție la nivel local a datelor de la senzori, care urmează să fie prelucrate, și
transmise folosind modulul LoRa către stația de bază. În f inal, se va realiza o decodare și o
analiză a pachetului de date transmis.
</p>
<p> Întregul sistem integrat va cuprinde și o aplicație WEB unde se pot
monitoriza toți parametrii ce ne interesează de la cele 2 noduri , cu un istoric complet, cât și
avertizări în caz de eventualele pericole detectate. Această aplicație face subiectul capitolului
următor.
</p>
</div>
</body>
</html>
Fișierul CSS al main .ejs :
body {
background -image: url("../img/city_river_2 -wallpaper -1920×1080.jpg");
min-height: 100vh;
background -size: cover;
background -position: center;
background -repeat: no -repeat;
margin: 0 au to;
color: white;
97
}
/* background color on top of bg image*/
.hero {
/* position: absolute; */
min-height: 100vh;
min-width: 100vw;
top: 0;
bottom: 0;
background -color: rgba(31, 34, 118, 0.5);
z-index: -5;
text-shadow: 2px 2px rgb(12, 12, 12);
}
/* navbar */
.navbar {
/* background -color: rgb(69, 106, 171); */
}
.navbar a {
color: white;
font-size: 25px;
}
.weather {
border:1px solid white;
margin-top: 6rem;
background -color: rgba(0, 0, 0, 0.5);
border-radius: 20px;
color: white;
}
.weather -head {
height: 50%;
}
#icon-desc {
font-size: 5rem;
padding-top: 1rem;
}
.humidity, .wind, .visibility {
border-top: 1px solid white;
border-bottom: 1px solid white;
font-size: 1.5rem;
}
#description {
font-size: 2rem;
}
#temperature {
font-size: 5rem;
}
#icon-thermometer {
font-size: 5rem;
}
#humidity, #wind, #visibility {
font-size: 2rem;
padding-top: 1rem;
98
padding-bottom: 1rem;
}
nav {
flex: 2;
}
.nav-links {
justify-content: space -around;
list-style-type: none;
display: flex;
}
.nav-link {
color: whitesmoke;
font-size: 24px;
text-decoration: none;
text-shadow: 2px 2px rgb(12, 12, 12);
}
Fișierul CSS al graphs .ejs :
* {
margin: 0px;
padding: 0px;
box-sizing: border -box;
}
body {
font-family: 'Poppins', sans -serif;
}
button {
font-family: 'Poppins', sans -serif;
}
header {
display: flex;
width: 90%;
height: 10vh;
margin: auto;
align-items: center;
}
.logo-container,
.nav-links,
.cart{
display: flex;
}
.logo-container {
flex: 1;
font-size: 25px;
}
.logo {
font-weight: 400;
margin: 5px;
}
99
nav {
flex: 2;
}
.nav-links {
justify-content: space -around;
list-style-type: none;
}
.nav-link {
color: rgb(26, 23, 23);
font-size: 20px;
text-decoration: none;
}
.button {
background -color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline -block;
font-size: 16px;
}
.button {
-webkit-transition -duration: 0.4s; /* Safari */
transition -duration: 0.4s;
}
.button:hover {
background-color: #4CAF50; /* Green */
color: white;
}
.h1 {
font-size: 44px;
font-weight: 500;
text-align: center;
background: linear -gradient(to right, #494964, #6f6f89);
-webkit-background -clip: text;
-webkit-text-fill-color: transparent;
}
.p {
margin-top: 5px;
font-size: 22px;
color: #585752;
}
.presentation {
/*display: flex; */
width: 90%;
margin: auto;
min-height: 80vh;
align-items: center;
}
.introduction {
flex: 1;
}
100
.intro-text h1 {
font-size: 36px;
font-weight: 500;
background: linear -gradient(to right, #152d7c, #595a69);
-webkit-background -clip: text;
-webkit-text-fill-color: transparent;
text-align: center;
}
.intro-text h2 {
font-size: 30px;
font-weight: 500;
background: linear -gradient(to right, #070707, #6f6f89);
-webkit-background -clip: text;
-webkit-text-fill-color: tr ansparent;
text-align: center;
}
.intro-text p {
margin-top: 5px;
font-size: 22px;
color: #585752;
text-align: justify;
text-indent: 2em;
}
101
ANEXA 3 – Codu l sursă pentru gateway (stația de bază)
Programul este scris în limbajul C++ și are la bază pachetul de pe Github dual_chan_pkt_fwd
[https://github.com/bokse001/dual_chan_pkt_fwd ]. Acest pachet conține o dovadă a implementării
conceptul ui de Gateway cu două canale , însă eu m -am folosit doar de implementarea cu un singur canal
al acestuia. Am configurat acest pachet, în fișierul „global _conf.json”, conform setărilor dorite privind
pinii Hat -ului LoRa, cât și ca aceasta stație de bază sa f ie vizibilă pe platforma TTN .
Fișierul global_conf.json :
{
"SX127x_conf":
{
"freq": 868300000,
"freq_2": 868100000,
"spread_factor": 12,
"pin_nss": 6,
"pin_dio0": 7,
"pin_nss_2": 6,
"pin_dio0_2": 7,
"pin_rst": 3,
"pin_led1":4,
"pin_NetworkLED": 22,
"pin_InternetLED": 23,
"pin_ActivityLED_0": 21,
"pin_ActivityLED_1": 29
},
"gateway_conf":
{
"ref_latitude": 44.43345,
"ref_longitude": 26.01034,
"ref_altitude": 10 ,
"name": "mihai97",
"email": "a@b.c",
"desc": "LoRa Emergency Ga teway",
"interface": "eth0",
102
"servers":
[
{
"address": "router.eu.staging.thethings.network",
"port": 1700,
"enabled": tr ue
},
{
"address": "router.eu.thethings.network",
"port": 1700,
"enabled": false
}
]
}
}
Fișierul dual_chan_pkt_fwd.cpp :
/******************************************************************** **********
*
* Copyright (c) 2015 Thomas Telkamp
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is availabl e at
* http://www.eclipse.org/legal/epl -v10.html
*
* Changes for creating a dual channel gateway with the Raspberry Pi+ LoRa(TM) Expansion Board
* of Uputronics, see also: store.uputronics.com/index.php?route=product/product&product_id=68
********* **********************************************************************/
// Raspberry PI pin mapping
// Pin number in this global_conf.json are Wir ing Pi number (wPi colunm)
// issue a `gpio readall` on PI command line to see mapping
// +––+––+––– +––+–+–Pi 3–+–+––+––– +––+––+
103
// | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
// +––+––+––– +––+–+–-++–-+–+––+––– +––+––+
// | | | 3.3v | | | 1 || 2 | | | 5v | | |
// | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5V | | |
// | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | |
// | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT5 | TxD | 15 | 14 |
// | | | 0v | | | 9 || 10 | 1 | ALT5 | RxD | 16 | 15 |
// | 17 | 0 | GPIO. 0 | OUT | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 |
// | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | |
// | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
// | | | 3.3v | | | 17 || 18 | 1 | IN | GPIO. 5 | 5 | 24 |
// | 10 | 12 | MOSI | ALT0 | 0 | 19 || 2 0 | | | 0v | | |
// | 9 | 13 | MISO | ALT0 | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
// | 11 | 14 | SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT | CE0 | 10 | 8 |
// | | | 0v | | | 25 || 26 | 1 | OUT | CE1 | 11 | 7 |
// | 0 | 30 | SD A.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
// | 5 | 21 | GPIO.21 | OUT | 0 | 29 || 30 | | | 0v | | |
// | 6 | 22 | GPIO.22 | OUT | 0 | 31 || 32 | 1 | IN | GPIO.26 | 26 | 12 |
// | 13 | 23 | GPIO.23 | OUT | 0 | 33 || 34 | | | 0v | | |
// | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
// | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.2 8 | 28 | 20 |
// | | | 0v | | | 39 || 40 | 0 | OUT | GPIO.29 | 29 | 21 |
// +––+––+––– +––+–+–-++–-+–+––+––– +––+––+
// | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
// +––+––+––– +––+–+–Pi 3–+–+––+––– +––+––+
// For Uputronics Raspberry Pi+ LoRa(TM) Expansion Board
// pins configuration in file global_conf.json
//
//
// "pin_nss": 10,
// "pin_dio0": 6,
// "pin_ nss2": 11,
// "pin_dio0_2": 27,
// "pin_rst": 0,
// "pin_NetworkLED": 22,
104
// "pin_InternetLED": 23,
// "pin_ActivityLED_0": 21,
// "pin_ActivityLED_1": 29,
//
#include "base64.h"
#include <rapidjson/document.h>
#include <rapidjson/fil ereadstream.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netdb.h>
#include <cstdlib>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
static const int CHANNEL = 0;
using namespace std;
105
using namespace rapidjson;
#define BASE64_MAX_LENGTH 341
static const int SPI_CHANNEL = 0;
static const int SPI_CHANNEL_2 = 1;
bool sx1272 = true;
typedef unsigned char byte;
struct sockaddr_in si_other;
int s;
int slen = sizeof(si_other);
struct ifreq i fr;
uint32_t cp_nb_rx_rcv;
uint32_t cp_nb_rx_ok;
uint32_t cp_nb_rx_ok_tot;
uint32_t cp_nb_rx_bad;
uint32_t cp_nb_rx_nocrc;
uint32_t cp_ up_pkt_fwd;
typedef enum SpreadingFactors
{
SF7 = 7,
SF8,
SF9,
SF10,
SF11,
SF12
} SpreadingFactor_t;
typedef struct Server
{
string address;
106
uint16_t port;
bool enabled;
} Server_t;
/*******************************************************************************
*
* Default values, configure them in global _conf.json
*
*******************************************************************************/
// uputronics – Raspberry connections
// Put them in global_conf.json
int ssPin = 0xff;
int dio0 = 0xff;
int ssPin_2 = 0xff;
int dio0_2 = 0xff;
int RST = 0xff;
int Led1 = 0xff;
int NetworkLED = 22;
int InternetLED = 23;
int ActivityLED_0 = 21;
int ActivityLED_1 = 29;
// Set location in global_conf.json
float lat = 0.0;
float lon = 0.0;
int alt = 0;
/* Informal status field s */
char platform[24] ; /* platform definition */
char email[40] ; /* use d for contact email */
char description[64] ; /* used for free form description */
// Set spreading factor (SF7 – SF12), &nd center frequency
// Overwritten by the o nes set in global_conf.json
SpreadingFactor_t sf = SF7;
107
uint16_t bw = 125;
uint32_t freq = 868100000; // in Mhz! (868.1)
uint32_t freq_2 = 868300000; // in Mhz! (868.3)
// Servers
vector<Server_t> servers;
// internet interface
char interface[6 ]; // Used to set the int erface to communicate to the internet either eth0 or wlan0
// #############################################
// #############################################
#define REG_FIFO 0x00
#define REG_FIFO_ADDR _PTR 0x0D
#define REG_FIFO_TX_BASE_AD 0x0E
#define REG_FIFO_RX_BASE_AD 0x0F
#define REG_RX_NB_BYTES 0x13
#define REG_OPMODE 0x01
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS 0x12
#define REG_DIO_MAPPING_1 0x40
#define REG_DIO_MAPPING_2 0x41
#define REG_MODEM_CONFIG 0x1D
#define REG_MODEM_CONFIG2 0x1E
#define REG_MODEM_CONFIG3 0x26
#define REG_SYMB_TIMEOUT_LSB 0x1F
#define REG_PKT_SNR_VALUE 0x19
#define REG_PAYLOAD_LENGTH 0x22
#define REG_IRQ_FLAGS_MASK 0x11
#define REG_MAX_PAYLOAD_LENGTH 0x23
#define REG_HOP_PERIOD 0x24
#define REG_SYNC_WORD 0x39
#define REG_VERSION 0x42
108
#define SX72_MODE_RX_CONTINUOS 0x85
#define SX72_MODE_TX 0x83
#define SX72_MODE_SLEEP 0x80
#define SX72_MODE_STANDBY 0x81
#define PAYLOAD_LENGTH 0x40
// LOW NOISE AMPLIFIER
#define REG_LNA 0x0C
#define LNA_MAX_GAIN 0x23
#define LNA_OFF_GAIN 0x00
#define LNA_LOW_ GAIN 0x20
// CONF REG
#define REG1 0x0A
#define REG2 0x84
#define SX72_MC2_FSK 0x00
#define SX72_MC2_SF7 0x70
#define SX72_MC2_SF8 0x80
#define SX72_MC2_SF9 0x90
#define SX72_MC2_SF10 0x A0
#define SX72_MC2_SF11 0xB0
#define SX72_MC2_SF12 0xC0
#define SX72_MC1_LOW_DATA_RATE_OPTIMIZE 0x0 1 // mandated for SF11 and SF12
// FRF
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
#define FRF_MSB 0xD9 // 868.1 Mhz
#define FRF_MID 0x06
#define FRF_LSB 0x66
109
#define BUFLEN 2048 //Max length of buffer
#define PROTOCOL_VERSION 1
#define PKT_PUSH_DATA 0
#define PKT_PUSH_ACK 1
#define PKT_PULL_DATA 2
#define PKT_PULL_RESP 3
#define PKT_PULL_ACK 4
#define TX_BUFF_SIZE 2048
#define STATUS_SIZE 1024
void LoadConfiguration(string filename);
void PrintConfiguration();
void Die(const char *s)
{
perror(s);
exit(1);
}
void SelectReceiver(byte CE)
{
if (CE == 0)
{
digitalWrite(ssPin, LOW);
} else {
digitalWrite(ssPin_2, LOW);
}
}
void UnselectReceiver(byte CE)
{
110
if (CE == 0 )
{
digitalWrite(ssPin, HIGH);
} else {
digitalWrite(ssPin_2, HIGH);
}
}
uint8_t ReadRegister(uint8_t addr, byte CE)
{
uint8_t spibuf[2];
SelectReceiver(CE);
spibuf[0] = addr & 0x7F;
spibuf[1] = 0x 00;
wiringPiSPIDataRW(CE, spibuf, 2);
UnselectReceiver(CE);
return spibuf[1];
}
void WriteRegister(uint8_t addr, uint8_t value, byte CE)
{
uint8_t spibuf[2];
SelectReceiver(CE);
spibuf[0] = addr | 0x80;
spibuf[1] = value;
wiringPiSPIDataRW(CE, spibuf, 2);
UnselectReceiver(C E);
}
bool ReceivePkt(char* payload, uint8_t* p_length, byte CE)
{
// clear rxDone
111
WriteRegister(REG_IRQ_FLAGS, 0x40, CE);
int irqflags = ReadRegister(REG_IRQ_FLAGS, CE);
cp_nb_rx_rcv++;
// payload crc: 0x20
if((irqflags & 0x20) == 0x20) {
printf("CRC error \n");
WriteRegister(REG_IRQ_FLAGS, 0x20, CE);
return false;
} else {
cp_nb_rx_ok++;
cp_nb_rx_ok_tot++;
uint8_t currentAddr = ReadRegister(REG_FIFO_RX_CURRENT_ADDR, CE);
uint8_t receivedCount = ReadRegister(REG_RX_NB_BYTES, CE);
*p_length = receivedCount;
WriteRegister(REG_FIFO_ADDR_PTR, currentAddr, CE);
for(int i = 0; i < receiv edCount; i++) {
payload[i] = ReadRegister(REG_FIFO, CE);
}
}
return true;
}
char * PinName(int pin, char * buff) {
strcpy(buff, "unused");
if (pin != 0xff) {
sprintf(buff, "%d", pin);
}
return buff;
112
}
void SetupLoRa(byte CE)
{
char buff[16];
if (CE == 0) {
printf("Trying to detect module CE0 with ");
printf("NSS=%s " , PinName(ssPin, buff));
printf("DIO0=%s " , PinName(dio0 , buff));
printf("Reset=%s ", PinName(RST , buf f));
printf("Led1=%s \n", PinName(Led1 , buff));
} else {
printf("Trying to detect module CE1 with ");
printf("NSS=%s " , PinName(ssPin_2, buff));
printf("DIO0=%s " , PinName(dio0_2 , buff));
printf("Reset=%s ", PinName(RST , b uff));
printf("Led1=%s \n", PinName(Led1 , buff));
}
// check basic
if (ssPin == 0xff || dio0 == 0xff) {
Die("Bad pin configuration ssPin and dio0 need at least to be defined");
}
uint8_t version = ReadRegister(REG_VERSION, CE);
if (version == 0x22) {
// sx1272
printf("SX1272 detected, starting. \n");
sx1272 = true;
} else {
// sx1276?
version = ReadRegister(REG_VERSION, CE);
if (version == 0x12) {
// sx1276
113
if (CE == 0)
{
printf("SX1276 detected on CE0, starting. \n");
} else {
printf("SX1276 detected on CE1, starting. \n");
}
sx1272 = false;
} else {
printf("Transceiver version 0x%02X \n", version);
Die("Unrecogn ized transceiver");
}
}
WriteRegister(REG_OPMODE, SX72_MODE_SLEEP, CE);
// set frequency
uint64_t frf;
if (CE == 0)
{
frf = ((uint64_t)freq << 19) / 32000000;
} else {
frf = ((uint64_t)freq_2 << 19) / 32000000;
}
WriteRegister(REG_FRF_MSB, (uint8_t)(frf >> 16), CE );
WriteRegister(REG_FRF_MID, (uint8_t)(frf >> 8), CE );
WriteRegister(REG_FRF_LSB, (uint8_t)(frf >> 0), CE );
WriteRegister(REG_SYNC_WORD, 0x34, CE); // LoRaWAN public sync word
if (sx1272) {
if (sf == SF11 || sf == SF12) {
WriteRegister(REG_MODEM_CONFIG, 0x0B, CE);
} else {
WriteRegister(REG_MODEM_CONFIG, 0x0A, CE);
}
114
WriteRegister(REG_MODEM_CONFIG2, (sf << 4) | 0x04, CE);
} else {
if (sf == SF11 || sf == SF12) {
WriteRegister(REG_MODEM_CONFIG3, 0x0C, CE);
} else {
WriteRegister(REG_MODEM_CONFIG3, 0x04, CE);
}
WriteRegister(REG_MODEM_CONFIG, 0x72, CE);
WriteRegister(REG_MODEM_CONFIG2, (sf << 4) | 0x04, CE);
}
if (sf == SF10 || sf == SF11 || sf == SF12) {
WriteRegister(REG_SYMB_TIMEOUT_LSB, 0x05, CE);
} else {
WriteRegister(REG_SYMB_TIMEOUT_LSB, 0x08, CE);
}
WriteRegister(RE G_MAX_PAYLOAD_LENGTH, 0x80, CE);
WriteRegister(REG_PAYLOAD _LENGTH, PAYLOAD_LENGTH, CE);
WriteRegister(REG_HOP_PERIOD, 0xFF, CE);
WriteRegister(REG_FIFO_ADDR_PTR, ReadRegister(REG_FIFO_RX_BASE_AD, CE), CE);
// Set Continous Receive Mode
WriteRegister(REG_LNA, LNA_MAX_GAIN, CE); // max lna gain
WriteRegister(REG_OPMODE, SX72_MODE_RX_CONTINUOS, CE);
}
void SolveHostname(const char* p_hostname, uint16_t port, struct sockaddr_in* p_sin)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
char service[6] = { ' \0' };
snprintf(service, 6, "%hu", port);
115
struct addrinfo* p_result = NULL;
// Resolve the domain name into a list of addresses
int error = getaddrin fo(p_hostname, service, &hints, &p_result);
if (error != 0) {
fprintf(stderr, "getaddrinfo: %s \n", gai_strerror(error));
exit(EXIT_FAILURE);
}
// Loop over all returned results
for (struct addrinfo* p_rp = p_result; p_rp != NULL ; p_rp = p_rp ->ai_next) {
struct sockaddr_in* p_saddr = (struct sockaddr_in*)p_rp ->ai_addr;
//printf("%s solved to %s \n", p_hostn ame, inet_ntoa(p_saddr ->sin_addr));
p_sin->sin_addr = p_saddr ->sin_addr;
}
freeaddrinfo(p_result);
}
void SendUdp(char *msg, int length)
{
for (vector<Server_t>::iterator it = servers.begin(); it != servers.end(); ++it) {
if (it->enabled) {
si_other.sin_port = htons(it ->port);
SolveHostname(it ->address.c_str(), it ->port, &si_othe r);
if (sendto(s, (char *)msg, len gth, 0 , (struct sockaddr *) &si_other, slen)== -1) {
Die("sendto()");
}
}
}
}
void SendStat()
116
{
static char status_report[STATUS_SIZE]; /* status report as a JSON object */
char stat_timestamp[24];
int stat_index = 0;
digitalWrite(InternetLED, HIGH);
/* pre-fill the data buffer with fixed fields */
status_report[0] = PROTOCOL_VER SION;
status_report[3] = PKT_PUSH_DATA;
status_report[4] = (unsigned char)ifr.ifr _hwaddr.sa_data[0];
status_report[5] = (unsigned char)ifr.ifr_hwaddr.sa_data[1];
status_report[6] = (unsigned char)ifr.ifr_hwaddr.sa_data[2];
status_report[7] = 0xFF;
status_report[8] = 0xFF;
status_report[9] = (unsigned char)ifr.ifr_hwaddr. sa_data[3];
status_report[10] = (unsigned char)ifr.ifr_hwaddr.sa_data[4];
status_report[11] = (unsigned char)ifr.ifr_hwaddr.sa_data[5];
/* start composing datagram with the header */
uint8_t token_h = (uint8_t)rand(); /* random token */
uint8_t token_l = (uint8_t)rand(); /* random token */
status_report[1] = token_h;
status_report[2] = token_l;
stat_index = 12; /* 12 -byte header */
/* get timestamp for statistics */
//time_t t = time(NULL);
time_t rawtime;
struct tm * ptm;
time ( &rawtime );
ptm = gmtime ( &rawtime );
117
ptm->tm_hour = pt m->tm_hour + 2;
//strftime(stat_timestamp, sizeof stat_timestamp, "%F %T %Z", gmtime(&t));
strftime(stat_timestamp, sizeof stat_timestamp, "%F %T %Z", ptm);
// Build JSON object.
StringBuffer sb;
Writer<StringBuffer> writer(sb);
writer.StartObject();
writer.String("stat");
writer.StartObject();
writer.String("time");
writer.String(stat_timestamp);
writer.String("lati");
writer.Double (lat);
writer.String("long");
writer.Double(lon);
writer.String("alti");
writer.Int(alt);
writer.String("rxnb");
writer.Uint(cp_nb_rx_rcv);
writer.String("rxok");
writer.Uint(cp_nb_rx_ok);
writer.String("rxfw");
writer.Uint(cp _up_pkt_fwd);
writer.String("ackr");
writer.Double(0);
writer.String("dwnb");
writer.Uint(0);
writer.String("txnb");
writer.Uint(0);
writer.String("pfrm");
writer.String(platform);
writer.String("mail");
writer.String(email);
118
writer.String("desc");
writer.String(description);
writer.EndObject();
writer.EndObject();
string json = sb.GetString();
//printf("stat update: %s \n", json.c_str());
printf("stat upda te: %s", stat_timestamp);
if (cp_nb_rx_ok_tot== 0) {
printf(" no packet received yet \n");
} else {
printf(" %u packet%sreceived \n", cp_nb_rx_ok_tot, cp_nb_rx_ok_tot>1?"s ":" ");
}
// Build and send message.
memcpy(status_report + 12, json.c_str(), json.size());
SendUdp(status_ report, stat_index + json.size());
digitalWrite(InternetL ED, LOW);
}
bool Receivepacket(byte CE)
{
long int SNR;
int rssicorr, dio_port;
bool ret = false;
if (CE == 0)
{
dio_port = dio0;
} else {
dio_port = dio0_2;
}
if (digitalRead(dio_port) == 1) {
char message[256];
uint8_t length = 0;
119
if (ReceivePkt(message, &length, CE)) {
// OK got one
ret = true;
uint8_t value = ReadRegister(REG_PKT_SNR_VALUE, CE);
if (CE == 0)
{
digitalWrite(ActivityLED_0, HIGH);
} else {
digitalWrite(ActivityLED_1, HIGH);
}
if (value & 0 x80) { // The SNR sign bit is 1
// Invert and divide by 4
value = ((~value + 1) & 0xFF) >> 2;
SNR = -value;
} else {
// Divide by 4
SNR = ( value & 0xFF ) >> 2;
}
rssicorr = sx1272 ? 139 : 157;
printf("CE%i Packet RSSI: %d, ", CE, ReadRegist er(0x1A, CE) – rssicorr);
printf("RSSI: %d, ", ReadRegister(0x1B,CE) – rssicorr);
printf("SNR: %li, ", SNR);
printf("Length: %hhu Message:'", length);
for (int i=0; i<length; i++) {
char c = (char) message[i];
printf("%c",isprint(c)?c:'.');
}
printf("' \n");
char buff_up[TX_BUFF_SIZE]; /* buffer to compose the upstream packet */
120
int buff_index = 0;
/* gateway < -> MAC protocol variables */
//static uint32_t net_mac_h; /* Most Significant Nibble, network order */
//static uint 32_t net_mac_l; /* Least Significant Nibble, network order */
/* pre-fill the data buffer with fixed fields */
buff_up[0] = PROTOCOL_VERSION;
buff_up[3] = PKT_PUSH_DATA ;
/* process some of the configuration variables */
//net_mac_h = htonl((uint32_t)(0xFFFFFFFF & (lgwm>>32)));
//net_mac_l = htonl((uint32_t)(0xFFFFFFFF & lgwm ));
//*(uint32_t *)(buff_up + 4) = net_mac_h;
//*(uint32_ t *)(buff_up + 8) = net_mac_l;
buff_up[4] = (uint8_t)ifr.ifr_hwaddr.sa_data[0];
buff_up[5] = (uint8_t)ifr.ifr_hwaddr.sa_data[1];
buff_up[6] = (uint8_t)ifr.ifr_hwaddr.sa_data[2];
buff_up[7] = 0xFF;
buff_up[8] = 0xFF;
buff_up[9] = (uint8_t)ifr.ifr_hwaddr.sa_data[3];
buff_up[10] = (uint8_t)ifr.ifr_hwaddr.sa_data[4];
buff_up[11] = (uint8_t)ifr.ifr_hwaddr.sa_data[5];
/* start composing datagram with the header */
uint8_t token_h = (uint8_ t)rand(); /* random token */
uint8_t token_l = (uint8_t)rand(); /* random token */
buff_up[1] = token_h;
buff_up[2] = token_l;
buff_index = 12; /* 12 -byte header */
// TODO: tmst can jump is time is (re)set, not good.
struct timeval now;
gettimeofday(&now, NULL);
uint32_t tmst = (uint32_t)(now.tv_sec * 1000000 + now.tv_usec);
121
// Encode payload.
char b64[BASE64_MAX_LENGTH];
bin_to_b64((uint8_t*)message, length, b64, BASE64_MAX_L ENGTH);
// Build JSON object.
StringBuffer sb;
Writer<StringBuffer> writer(sb);
writer.StartObject();
writer.String("rxpk");
writer.StartArray();
writer.StartObject();
writer.String("tmst");
writer.Uint(tmst);
writer.String("freq");
if (CE == 0) {
writer.Double((double)freq / 1000000);
writer.String("chan");
writer.Uint(0);
} else {
writer.Double((double)freq_2 / 1000000);
writer.String("chan");
writer.Uint(1);
}
writer.String("rfch");
writer.Uint(0);
writer.String("stat");
writer.Uint(1);
writer.String("modu");
writer.String("LORA");
writer.String("datr");
char datr[] = "SFxxBWxxx";
snprintf(datr, strlen(datr) + 1, "SF%hhuBW%hu", sf, bw);
writer.St ring(datr);
writer.String("codr");
122
writer.String("4/5");
writer.String("rssi");
writer.Int(ReadRegister(0x1A, CE) – rssicorr);
writer.String("lsnr");
writer.Double(SNR); // %li.
writer.String("size");
writer.Uint(length);
writer.String("data");
writer.String(b64);
writer.EndObject();
writer.EndArray();
writer.EndO bject();
string json = sb.GetString();
printf("rxpk update: %s \n", json.c_str());
// Build and send message.
memcpy(buff_up + 12, json.c_str(), json.size());
SendUdp(buff_up, buff_index + json.size());
fflush(stdout);
}
}
return ret;
}
int main()
{
struct timeval nowtime;
uint32_t lasttime;
unsigned int led0_timer,led1_timer;
LoadConfiguration("global_conf.json");
PrintConfiguration();
// Init WiringPI
123
wiringPiSetup() ;
pinMode(ssPin, OUTPUT);
pinMode(ssPin_2, OUTPUT);
pinMode(dio0, INPUT);
pinMode(dio0_2, INPUT);
pinMode(RST, OUTPUT);
pinMode(NetworkLED, OUTPUT);
pinMode(ActivityLED_0, OUTPUT);
pinMode(ActivityLED_1, OUTPUT);
pinMode(InternetL ED, OUTPUT);
// Init SPI
wiringPiSPISetup(SPI_CHANNEL, 500000);
wiringPiSPISetup(SPI_CHANNEL_2, 500000);
// Setup LORA
digitalWrite(RST, HIGH);
delay(100);
digitalWrite(RST, LOW );
delay(100);
SetupLoRa(0);
SetupLoRa(1);
// Prepare Socket connection
while ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
digitalWrite(NetworkLED, 1);
printf("No socket connection possible yet. Retrying in 10 seconds… \n");
delay(10000);
digitalWrite(N etworkLED, 0);
}
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
ifr.ifr_addr.sa_family = AF_INET;
124
strncpy(ifr.ifr_name, interface, IFNAMSIZ -1); // use configured network interface eth0 or wlan0
ioctl(s, SIOCGIFHWADDR, &ifr);
// ID based on MAC Adddress of interface
printf( "Gateway ID: %.2x:%.2x:%.2x:ff:ff:%.2x:%.2x:%.2x \n",
(uint8_t)ifr.ifr_hwaddr.sa_data[0],
(uint8_t)ifr.ifr_hwaddr.sa_data[1],
(uint8_t)ifr.ifr_hwaddr.sa_data[2],
(uint8_t)ifr.ifr_hwaddr.s a_data[3],
(uint8_t)ifr.ifr_hwaddr.sa_data[4],
(uint8_t)ifr.ifr_hwaddr.sa_data[5]
);
printf("Listening at SF%i on %.6lf Mhz. \n", sf,(double)freq/1 000000);
printf("Listening at SF%i on %.6lf Mhz. \n", sf,(double)freq_ 2/1000000);
printf(" –––––––––––– \n");
while(1) {
// Packet received ?
if (Receivepacket(0)) {
// Led ON
if (ActivityLED_0 != 0x ff) {
digitalWrite(ActivityLED_0, 1);
}
// start our Led blink timer, LED as been lit in Receivepacket
led0_timer=millis();
}
if (Receivepacket(1)) {
// Led ON
if (ActivityLED_1 != 0xff) {
digitalWrite(ActivityLED_1, 1);
}
// start our Led blink timer, LED as been lit in Receivepacket
125
led1_timer=millis();
}
gettimeofday(&nowtime, NULL);
uint32_t nowseconds = (uint32_t)(nowtime.tv_sec);
if (nowsecond s – lasttime >= 30) {
lasttime = nowseconds;
SendStat();
cp_nb_rx_rcv = 0;
cp_nb_rx_ok = 0;
cp_up_pkt_fwd = 0;
}
// Led timer in progress ?
if (led0_timer) {
// Led timer expiration, Blink duration is 250ms
if (millis() – led0_timer >= 250) {
// Stop Led timer
led0_timer = 0;
// Led OFF
if (ActivityLED_0 != 0xff) {
digitalWrite(ActivityLED_0, 0);
}
}
}
if (led1_timer) {
// Led timer expiration, Blink duration is 250ms
if (millis() – led1_timer >= 250) {
// Stop Led timer
led1_timer = 0;
// Led OFF
if (ActivityLED_1 != 0xff) {
digitalWrite(ActivityLED_1, 0);
126
}
}
}
// Let some time to the OS
delay(1);
}
return (0);
}
void LoadConfiguration(string configurationFile)
{
FILE* p_file = fopen(configurationFile.c_str(), "r");
char buffer[65536];
FileReadStream fs(p_file, buffer, sizeof(buffer));
Document document;
document.ParseStream(fs);
for (Value::ConstMemberIterator fileIt = document.MemberBegin(); fileIt != document.MemberEnd(); ++fileIt) {
string objectType(fileIt ->name.GetString());
if (objectType.compare("SX127x_conf") == 0) {
const Value& sx127x_conf = fileIt ->value;
if (sx127x_conf.IsObject()) {
for (Value::ConstMemberIterator confIt = sx127x_conf.MemberBegin(); confIt != sx127x_conf.MemberEnd();
++confIt) {
string key(confIt ->name.GetString());
if (key.compare("freq") == 0) {
freq = confIt ->value.GetUint();
} else if (key.compare("freq_2") == 0) {
freq_2 = (SpreadingFactor_t)confIt ->value.GetUint();
} else if (key.compare("spread_factor") == 0) {
sf = (SpreadingFactor_t)confIt ->value.GetUint();
} else if (key.compare("pin_nss") == 0) {
127
ssPin = confIt ->value.GetUint();
} else if (key.compare(" pin_nss_2") == 0) {
ssPin_2 = confIt ->value.GetUint();
} else if (key.compare("pin_dio0") == 0) {
dio0 = confIt ->value.GetUint();
} else if (key .compare("pin_dio0_2") == 0) {
dio0_2 = confIt ->value.GetUint();
} else if (key.compare("pin_rst") == 0) {
RST = confIt ->value.GetUint();
} else if (key.compare("pin_NetworkLED") == 0) {
NetworkL ED = confIt ->value.GetUint();
} else if (key.compare( "pin_InternetLED") == 0) {
InternetLED = confIt ->value.GetUint();
} else if (key.compare("pin_ActivityLED_0") == 0) {
ActivityLED_0 = confIt ->value.GetUint();
} else if (key.compare("pin_ActivityLED_1") == 0) {
ActivityLED_1 = confIt ->value.GetUint();
}
}
}
} else if (objectType.compare("gateway_conf") == 0) {
const Value& gateway_conf = fileIt ->value;
if (gateway_conf.IsObject()) {
for (Value::ConstMemberIterator confIt = gateway_conf.MemberBegin(); confIt != gateway_conf.MemberEnd();
++confIt) {
string memberType(confIt ->name.GetString());
if (memberType.compare("ref_latitude") == 0) {
lat = confIt ->value.GetDouble();
} else if (memberType.compare("ref_longitude") == 0) {
lon = confIt ->value.GetDouble();
} else if (memberType.compare("ref_altitude") == 0) {
alt = confIt ->value.GetUint();
} else if (memberType.compare("name") == 0 && confIt ->value.IsString()) {
128
string str = confIt ->value.GetString();
strcpy(platform, str.length()<=24 ? str.c_str() : "name too long");
} else if (memberType.compare ("email") == 0 && confIt ->value.IsString()) {
string str = confIt ->value.GetString();
strcpy(email, str.length()<=40 ? str.c_str() : "email too long");
} else if (memberType.compare("desc") == 0 && confIt ->value.IsString()) {
string str = confIt ->value.GetString();
strcpy(description, str.length()<=64 ? str.c_str() : "description is too long");
} else if (mem berType.compare("interface") == 0 && confIt ->value.IsString()) {
string str = confIt->value.GetString();
strcpy(interface, str.length()<=6 ? str.c_str() : "interface too long");
} else if (memberType.compare("servers" ) == 0) {
const Value& serverConf = confIt ->value;
if (serverConf .IsObject()) {
const Value& serverValue = serverConf;
Server_t server;
for (Value::ConstMemberIterator srvIt = serverVal ue.MemberBegin(); srvIt !=
serverValue.MemberEnd(); ++srvIt) {
string key( srvIt->name.GetString());
if (key.compare("address") == 0 && srvIt ->value.IsString()) {
server.address = srvIt ->value.GetString();
} else if (key.compare("port") == 0 && srvIt ->value.IsUint()) {
server.port = sr vIt->value.GetUint();
} else if (key.compare("enabled") == 0 && srvIt ->value.IsBool()) {
server.enabled = srvIt ->value.GetBool();
}
}
servers.push _back(server);
}
else if (serverConf.IsArray()) {
for (SizeType i = 0; i < serverConf.Size(); i++) {
const Value& serverValue = serverConf[i];
Server_t server;
for (Value::ConstMemberIterator srvIt = serverValue.MemberBegin(); srvIt !=
serverValue.MemberEnd(); ++srvIt) {
string key(srvIt ->name.GetString());
129
if (key.compare("address") == 0 && srvIt ->value.IsString()) {
server.address = srvIt ->value.GetString();
} else if (key.compare("port") == 0 && srvIt ->value.IsUint()) {
server.p ort = srvIt ->value.GetUint();
} else if (key.compare("enabled") == 0 && srvIt->value.IsBool()) {
server.enabled = srvIt ->value.GetBool();
}
}
servers.push_back(ser ver);
}
}
}
}
}
}
}
}
void PrintConfiguration()
{
for (vector<Server_t>::iterator it = servers.begin(); it != servers.end(); ++it) {
printf("server: .address = %s; .port = %hu; .enable = %d \n", it->address.c_str(), it ->port, it ->enabled);
}
printf("Gateway Configur ation\n");
printf(" %s ( %s)\n %s\n", platform, email, description);
printf(" Latitude=%.8f \n Longitude=%.8f \n Altitude=%d \n", lat,lon,alt);
printf(" Interface: %s \n", interface);
}
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Sistem integrat de monitorizare și prevenție a situațiilor de urgență [622612] (ID: 622612)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
