Sistem Client Server Pentru Monitorizarea Continua a Tulburarilor Apneice
Cuprins
1. Introducere 3
1.1. Sindromul de apnee în somn 3
1.1.1 Diagnosticarea 3
1.1.2 Tratarea Apneei 3
1.2 Contextul de realizare 4
1.3 Specificații generale 4
2. Tehnologii Folosite 6
2.1. Vedere de ansamblu 6
2.2. Utilizatorul 6
2.3. Browser-ul 7
2.4. Serverul Web 9
2.5. Servicii Backend 9
2.6. Node.js 9
2.7. MongoDB 10
2.8. Express 11
2.9. Front End 11
2.10. HTML 12
2.11. CSS 13
2.12. Javascript 13
2.13. AngularJS 14
3. Proiectare și implementare 15
3.1 Arhitectura 15
3.2 Serviciul web și baza de date 16
3.2.1 Configurarea Serverului 16
3.2.2 Baza de date 17
3.2.3 Autentificare de tip Token-Based 20
3.2.4 Interfața webService 22
3.3 Website AngularJS 27
3.3.1 Vedere de ansamblu 27
3.3.2 Configurare 28
3.3.3 Arhitectură. Rutare. 29
3.3.4 Interfața 30
3.3.5 Serviciul Angular HTTP 35
3.3.6 Logica de Autentificare 36
3.3.7 Pagina principală – HomePage 38
3.3.8 Pagina de adăugare/editare a pacienților 40
3.3.9 Pagina de adăugare/actualizare a măștilor 42
3.3.10 Pagina de statistici și grafice 42
4. Concluzii 44
Introducere
1.1. Sindromul de apnee în somn
Apneea este o întrerupere temporară a respirației, iar persoanele care suferă de acest sindrom se opresc din respirat în mod repetat în timpul somnului pentru intervale cuprinse între câteva secunde și un minut sau chiar mai mult.
În timpul somnului scade ritmul respirației și al inimii, iar temperatura corpului și presiuniea sanguină se modifică. Un somn cu probleme, sau insuficient va afecta funcțiile și sănătatea întregului organism.
Dacă într-un interval de o oră pacientul are cel puțin zece întreruperi ale respirației, fiecare cu durata de minimum 10 secunde fiecare, cantitatea de oxigen care ajunge la creier este insuficientă. În această situație, concentrația de bioxid de carbon din sânge crește și apar variații ale ritmului cardiac. Scăderea concentrației de oxigen declanșează o trezire parțială ("microtrezire"), însoțită de un sforăit puternic și o inspirație bruscă. Aceste "microtreziri" rămân neobservate de către pacient, dar produc o superficializare a somnului. Acest somn superficial duce la refacerea insuficientă a organismului în timpul nopții și la somnolență și oboseală în timpul zilei.
Pacienții care suferă de apnee în somn se simt adesea extrem de obosiți și somnolenți în timpul zilei iar capacitatea lor de concentrare și performanța diurnă suferă drastic.
Pe termen lung, desaturațiile repetate dăunează grav organelor vitale. Apneea în somn netratată duce la complicații ca tensiune arterială, afecțiuni cardiace sau atac cerebral.
1.1.1 Diagnosticarea
Persoanele suspectate de sindromul de apnee în somn trebuie să fie testate cu aparatură specială. Într-o primă etapă, parametrii mai importanți cum sunt sforăitul, saturația de oxigen, ritmul cardiac etc. pot fi înregistrați chiar la domiciliul pacientului folosind un aparat portabil. Specialistul pregătește aparatul și explică modul de utilizare a acestuia, iar pacientul trebuie doar să atașeze senzorii înainte de a dormi. A doua zi, aparatul se returnează medicului, care va interpreta datele înregistrate. Dacă prelucrarea acestor date indică apneea în somn, medicul va îndruma pacientul către un laborator de somnologie pentru un diagnostic mai detaliat și recomandarea terapiei.
Un laborator de somnologie dispune de aparatură complexă cu ajutorul căreia se pot monitoriza toți parametri asociați somnului, cum sunt: etapele somnului (electro-encefalograma, electro-oculograma, electro-miograma), microtrezirea, ritmul cardiac (electro-cardiograma), respirația (fluxul, efortul toracic și abdominal, sforăitul), poziția corpului etc.
Tehnicianul va atașa pacientului senzorii necesari și va supraveghea somnul acestuia prin intermediul unei camere cu infraroșu. Toți parametrii se monitorizează și se înregistrează de-a lungul întregii nopți și vor fi evaluați de către specialist a doua zi.
1.1.2 Tratarea Apneei
Cel mai obișnuit tratament prescris pentru apneea obstructivă în somn este un aparat CPAP. CPAP este o prescurtare din limba engleză: Continuous Positive Airway Pressure (presiune pozitivă continuă în căile aeriene). Acest tip de aparat furnizează o presiune prin intermediul unei măști confortabile pe care pacientul o poartă în timpul nopții. Masca este fabricată dintr-un silicon moale și poate fi fixată cu o curea reglabilă. Presiunea furnizată de aparat menține căile respiratorii deschise, eliminând astfel apneea în somn și asigurând o respirație normală pe tot timpul nopții. Este indicat ca pacientul să se familiarizeze cu un astfel de aparat în laboratorul de somnologie, unde se poate alege masca optimă, pentru o fixare comodă și totodată etanșă.
În mod normal efectele benefice apar rapid, imediat după începerea tratamentului prin această metodă. În afară de terapia CPAP, sunt recomandate și schimbările în regimul de viață. Persoanele supraponderale, de exemplu, ar fi favorizate de scăderea în greutate. Există și recomandări nespecifice care pot veni în ajutorul terapiei, cum ar fi evitarea alcoolului, tutunului și somniferelor, precum și a cafelei seara. În cazuri extrem de rare, pacienții cu apnee în somn pot avea nevoie de medicație sau chiar de intervenții chirurgicale.
La ora actuală terapia CPAP se dovedește a fi cel mai indicat mod de a trata persoanele cu apnee obstructivă în somn.
1.2 Contextul de realizare
Având în vedere contexul de desfășurare al sindromului de apnee în somn, motivația proiectului de față este strâns legată de monitorizarea complianței tratamentului pentru apnee. Proiectul general presupune proiectarea și dezvoltarea unui sistem informatic care să ofere suport pentru monitorizarea complianței paciențiilor în tratamentul sindromului apneic. Acest sistem este compus din două mari componente. Prima componentă este alcătuită din aparatul de tip CPAP care va fi programat pentru a trimite în fiecare zi către un server, starea de utilizare al aparatului în ziua respectivă. Aparatul de tratare al sindromului apneic va fi programat și configurat ca parte dintr-un alt proiect de către studentul Filipovici Andrei.
A doua componentă este reprezentată de un mediu informatic de observare a complianței în tratarea acestui sindrom, și este destinată utilizării pentru medici parte din programul de tratare și observare a paciențiilor care suferă de sindromul de apnee în somn. Ca funcționalitate principală, sistemul informatic va permite supravegharea modului în care folosesc sau nu pacienții tratamentul destinat sindromului în cauză. Sistemul va permite evaluarea unor statistici referitoare la folosința măștii de tratare, va permite adăugarea de pacienți și aparate în baza de date și observarea lor. Sistemul este alcătuit dintr-un serviciu web care va prelua rezultatul primit de la aparatul de tratare al apneei, și va memora informațiile într-o bază de date. Serviciul împreună cu baza de date și o pagină web vor forma obiectul acestei lucrări și formează sistemul client-server pentru monitorizarea complianței tratamentului pentru sindromul de apnee în somn.
1.3 Specificații generale
Proiectul Client-Server este alcătuit dintr-un serviciu web programat și dezvoltat pe platforma Node.js, împreună cu framework-ul Express. Acest serviciu va administra comunicarea dintre apartul de tratare a apnee programat de colegul meu și baza de date, dar și dintre pagina web de monitorizare a complianței și baza de date.
Baza de date a sistemului este de tip NoSQL. A fost ales acest tip de bază de date deoarece bazele de date NoSQL au fost create ca răspuns la creșterea volumului de date despre utilizatori, obiecte și produse stocate, dar și la creșterea frecvenței cu care sunt accesate acestea, și nevoile de performanță și procesare ale aplicațiilor din ziua de astăzi. Tehnologia aleasă pentru baza de date este MongoDB.
Website-ul pentr monitorizarea complianței paciențiilor la tratamentul pentru sindromul apneic, este cel care va oferi interfața de interacțiune pentru medic, cel care va avea acces la informațiile despre folosirea sau nefolosirea tratamentului de către pacienți. Pagina web va oferi posibilitatea de adăugare, ștergere și actualizare a paciențiilor în baza de date, dar mai ales va oferi posibilitatea de vizualizare a unor statistici privind complianța paciențiilor.
Pagina web este realizată folosind arhitectura MVC (Model View Controller), framework-ul AngularJS pentru logica aplicației web, framework-ul Mobile Angular UI pentru interfața website-ului, Google Charts, Angular NVD3 și AmCharts pentru grafice.
Tehnologii Folosite
2.1. Vedere de ansamblu
Node.js furnizează platforma fundamentală pentru dezvoltare. Servicile backend și scripturile server side sunt toate scrise in Node.js. MongoDB furnizează spațiul de stochare pentru website și este accesat folosind driverul MongoDB care este un modul Node.js. Serverul Web este definit folosind framework-ul Express care este de asemenea un modul Node.js.
Componenta vizuală din browser este definită și controlată folosind framework-ul AngularJS. AngularJS este un framework MVC (Model View Controller)unde modelul este alcătuit din obiecte JSON sau JavaScript, view-ul este format din componentele HTML/CSS iar controllerul este construit în AngularJS JavaScript.
Diagrama următoate este o diagramă de bază despre organizarea întregului sistem Node.js – AngularJS.
Figura 2-1. Arhitectură sistem REST
2.2. Utilizatorul
Utilizatorii (users) sunt o parte fundamentală a tuturor website-urilor deoarece ei sunt principalul motiv al existenței website-ului. Așteptările utilizatorului definesc specificațiile pentru dezvoltarea unui website bun. Așteptările utilizatoriilor s-au schimbat foarte mult de-a lungul anilor. Înainte aceștia obișnuiau să accepte o experiență lentă și greoaie a internetului, dar această epocă a apus. Acum utilizatorii așteaptă de la website-uri să aibă un comportament cât mai apropiat de al aplicațiilor instalate pe computerele acestora și pe device-urilor mobile.
Rolul utilizatorului într-un framework web este de a observa output-ul vizual al website-ului și de a interacționa cu acesta. Aceasta se poate traduce astfel: utilizatorul vizualizează rezultatul procesării tuturor framework-urilor web iar mai apoi interacționează folosind mouse-ul și tastatura iar pentru device-urile mobile ”swipe”-uri și ”tap”-uri.
În particular, pentru aplicația web propusă, utilizatorul este reprezentat de catre medic.Acesta va controla folosind website-ul aplicatiei starea si modul de folosință al măștii de către pacienții care au primit tratamentul necesar tratării apneei. Medicul va interacționa cu pagina web folosind tastatura și mouse-ul când accesează pagina de pe computer, iar când accesează website-ul de pe dispozitivul mobil (smartphone sau tabletă) va interacționa folosind gesturile specifice ecranelor touch screen.
2.3. Browser-ul
Browser-ul are 3 roluri în framework-ul web. Primul rol este acela de a furniza comunicarea ”la” și ”de la” serverul web. Al doilea rol este de a interpreta informațiile de la server și de a le reda pentru ca utilizatorul să poată să le vadă. Iar ultimul rol al browser-ului este să controleze interacțiunea utilizatorului care poate folosi tastatura, mouse-ul, ecranul tactil sau altfel de dispozitive de intrare și să realizeze interacțiunea în mod corect.
Comunicarea dintr browser si serverul web constă dintr-o serie de request-uri care folosesc protocolul HTTP/HTTPS. HTTP (Hypertext Transfer Protocol) definește comunicarea între browser și server. Protocolul HTTP definește ce tipuri de request-uri pot fi realizate, dar și formatul acestor request-uri și al răsunsurilor HTTP (response).
HTTPS adaugă un nivel de securitate SSL/TLS pentru a asigura conexiuni sigure cerând serverului web să furnizeze un certificat de securitate browser-ului. Utilizatorul este mai apoi cababil să aleagă dacă acceptă sau nu certificatul înainte să accepte conexiunea.
Există trei mari tipuri de request-uri care browser-ul le trimite la server:
GET: Acest tip de request este în mod normal folosit pentru a cere informații de la server precum fișiere html, imagini sau date în format JSON.
POST: Acest tip de request-uri sunt folosite pentru a trimite date la server ca de exemplu: trimiterea unui formular web.
AJAX (Asynchronous JavaScript and XML): Sunt defapt request-uri GET sau POST realizate în mod direct de codul JavaScript încărcat în browser. În ciuda numelui, request-urile AJAX pot recepționa date în format XML, JSON sau raw.
Randarea elementelor vizuale. Ecranul final pe care utilizatorul îl va vedea și cu care va interacționa este construit din mai multe seturi de date venite de la server. Browser-ul citește datele de la URL-ul inițial iar mai apoi randează documentul HTML pentru a construi DOM-ul (Document Object Model). DOM-ul este un obiect cu structură arborescentă care are ca rădăcină documentul HTML. Structura arborelui se potrivește cu structura documentului HTML. Spre exemplu document-ul va avea ca și copil: html, care va avea și el copil pe body și asa mai departe precum în figura următoare:
Figura 2-2. Structura arborescentă a documentului de tip HTML
Browser-ul va interpreta fiecare element din DOM și îl va randa pe ecranul utilizatorului pentru a construi view-ul pagini web.
Browser-ul de cele mai multe ori va construi pagina web pe baza mai multor tipuri de date, date primite în urma request-urilor la server. Următoarele tipuri de date sunt cele mai comune tipuri pe care browser-ul le folosește pentru a randa ecranul final al utilizatorului, dar și pentru a defini comportamentul paginii web.
Fișiere HTML: Acestea furniezează structura fundamentală a DOM-ului.
Fișiere CSS: Acestea definesc stilul pentru fiecare din elementele paginii. Spre exemplu font-uri, culori sau spațiere.
Scripturi Cliend Side: În mod normal acestea sunt fișiere JavaScript. Acestea pot asigura anumite funcționalități pentru pagina web, manipula DOM-ul pentru a schimba aspectul website-ului, și pot furniza orice logică necesară pentru a afișa pagina și a furniza funcționalitatea.
Fișiere Media: Imagini, videoclipuri și fișiere audio care sunt randate ca părți componente ale paginii web.
Date: Orice tip de date: XML, JSON sau text raw sunt furnizate de către serverul web ca răspuns la un request AJAX.
Antete HTTP: Protocoul HTTP definește un set de antete care pot fi folosite de către browser pentru a defini comportamentul paginii web. De exemplu: cookies-urile se regăsesc în antetele HTTP. Antetele HTTP definesc de altfel și tipul de date din request dar și tipul de date așteptat în răspuns.
Utilizatorul interacționează cu browser-ul prin componente de intrare precum mouse-ul, tastatura și ecranele tactile. Browserul deține un sistem complex de evenimente care surprind toate aceste evenimente de intrare și pun în aplicare efectele potrivite. Aceste acțiuni pot varia de la afișarea unui meniu la încărcarea unui nou document de la server.
2.4. Serverul Web
Principalul scop al serverului Web este să controleze request-urile venite de la browser. Așa cum am descris anterior, browser-ul poate să solicite documente, să trimită informații sau să trimită request-uri de tip AJAX. Serverul Web va folosi antetele HTTP și URL-urile pentru a determina ce acțiune va urma.Acest punct este cel în care lucrurile devin diferite în funcție de server, confugurație sau tehnologii folosite.
Majoritatea serverelor web (de ex Apache), sunt făcute să stocheze fișiere statice precum .html, .css și fișiere media. Pentru a trata request-uri de tip POST care modifică date pe server și request-uri AJAX pentru interacțiunea cu servicii backend, serverele web trebuie extinse folosind script-uri server side.
Scrip-urile server-side nu sunt altceva decât script-uri executate de server pentru a realiza task-uri solicitate de browser. Acestea pot fi scrise în limbaje de programare precum: PHP, Python, C, C++,C#, Perl, Java etc. Servere precum Apache furnizează mechanisme pentru includerea script-urilor server side.
Aici este locul unde un framework solid poate să facă o mare diferență. Adeseori este nevoie de o configurare importantă pentru a activa diverse limbaje de scripting și a le încărca astfel încât serverul web să poata face legătura între request-uri și scriptul potrivit.
Script-urile server side ori vor genera răspunsuri direct prin execuția codului propriu, ori vor realiza conexiuni cu alte servere backend precum baze de date, pentru a obține informațiile necesare și mai apoi vor construi și trimite răspunsul potrivit.
2.5. Servicii Backend
Serviciile backend sunt servicii care rulează în spatee serverului web și furnizează date folosite pentr contruirea răspunsurilor. Cel mai comun tip de serviciu backend este baza de date care stocheză informații. Când un request vine de la browser și solicită informații de la baza de date sau alt serviciu backend, serverul se va conecta la baza de date și va obține informațiile cerute, le va formata și mai apoi le va trimite înapoi la browser.
2.6. Node.js
Node.js este un framework de dezvoltare bazat pe motorul V8 JavaScript realizat de Google. Astfel node.js este scris (ca limbaj de programare) în JavaScript și mai apoi compilat în cod mașină de V8 la execuție.
Pentru serviciul web tehnologia aleasă este Node.js. Node.js este un mediu cross-platform open source pentru dezvoltarea aplicațiilor server-side. Aplicațiile Node.js sunt scrise in limbajul de programare Javascript și pot fi rulate folosiind serviciul node.js pe majoritatea sistemelor de operare: OS X, Microsoft Windows, Linux, FreeBSD, NonStop și IBM i.
Node.js asigură o arhitectură event-driven și un non-blocking I/O API care optimizeză scalabillitatea și transferul aplicațiilor web. Această tehnologie este adeseori folosită pentru real-time applications.
Node.js este adoptat din ce în ce mai des ca platformă server-side și este folosit în acest moment de Microsoft, Yahoo, Walmart, Groupon, SAP, LinkedIn, Rakuten, PayPal etc.
Istoric Node.js. Node.js a fost conceput în anul 2009 de către programatorul Ryan Dahl și alți programatori care lucrau la Joyent. Node.js a fost creat și lansat pentru Linux în 2009, iar dezvoltarea și mentenanța a fost condusă de Ryan Dahl și firma pentru care acesta lucra, Joyent.
Platforma a început sa atragă atenția după debutul său la conferința European JSConf pe data de 8 Noiembrie 2009. Dahl a prezentat platforma Node.js care combină engine-ul Javascript Google V8, un evet-loop, și un I/O API low level. Proiectul a fost primit cu mult succces și a avut o creștere a popularității demnă de invidiat în perioada de timp ce a urmat.
Majoritatea servicilor backend pot fi scrise în Node.js, chiar și scripturi server-side. Partea frumoasă a lui Node.js este că totul este scris în javaScript deci este foarte ușor să muți funcționalitate dintr-un script client-side într-un script server-side. De asemenea serverul poate rula direct folosind platforma Node.js, deoarece modulul Node.js face configurarea servicilor sau scrierea scripturilor server-side mult mai ușoar decât în cazul tehnologiei Apache.
Iată câteva motive pentru care Node.js este un framework excelent:
Javascript End to End: Unul din marele avantaje ale lui Node.js este că permite programarea scripturilor server-side și client-side în JavaScript. Întotdeauna au fost dificultăți în alegerea locului în care să pui logica de scripting. Prea multă logică client-side poate face programarea greoaie și mentenanța dificilă, iar prea multă logică server-side poate încetinii aplicațiile web și să îngreuneze cu sarcini mari serverul. Cu Node.js poți folosi cod JavaScript client-side și să-l adaptezi ușpr pentru server și vice versa. Mai mult, programatorii client-side și cei server-side vor folosi același limbaj de programare.
Scalabilitate Event Driven: Node.js foosește o logică diferită pentru controlul request-urilor. Request-urile în loc să fie așteptate si procesate de mai multe fire de execuție, în Node.js sunt procesate de același fir de execuție folosind un model de evenimente. Aceasta permite scalarea serverelor Node.js în moduri imposibile pentru serverele web tradiționale.
Extensibilitate: Node.js are o comunitate activă de dezvoltare. Apar tot timpul module noi Node.js pentru extinderea funcționalității. De asemenea este foarte simplu să instalezi și să adaugi module noi în Node.js.
Timp: Node.js este foarte ușor de instalat și configurat.
2.7. MongoDB
MongoDB este o bază de date NoSQL agilă și foarte scalabilă. Numele Mongo vine de la „humongous”. Se bazează pe modelul de stocare de documente NoSQL, ceea ce înseamnă că informațiile se stochează în baza de date mai degrabă ca obiecte JSON, spre deosebire de rânduri și coloane în baze de date relaționale.
MongoDB este un backend storage pentru website-uri foarte bun pentru pagini web cu trafic mare de date.
Node.js suportă o varietate mare de drivere de acces a bazelor de date, iar integrarea bazei de date NoSQL devine foarte simplă. În continuare iată câteva din motivele pentru care MongoDB se potrivește foarte bine în sistemul Node.js:
Document Oriented: Deoarece MongoDB este orientat pe documente, informațiile sunt stocate în baza de date în format foarte apropiat de cel folosit atât server-side cât și client-side.
Performanță Ridicată: MongoDB este una din bazele de date cu cea mai înaltă performanță disponibilă. În special în ziua de azi când tot mai mulți oameni interacționează cu paginile web, este foarte important să existe un backend care suportă trafic ridicat.
Disponibilitate Ridicată: Modelul de replicare folosti de MongoDB favorizează păstrarea scalabilității în timp ce se păstrează și o performanță ridicată.
Scalabilitate Ridicată: Structura MongoDB favorizează scalarea orizontală prin partiționarea informațiilor pe mai multe servere.
NoSQL Injection: MongoDB nu este susceptibilă la SQL injection, deoarece obiectele sunt stocate ca obiecte nu ca string-uri SQL.
2.8. Express
Modulul Express are funcționalitatea unui webserver în sistemul nostru. Faptul că rulează în Node.js face ca totul să fie ușor de configura, implementat și controlat. Modulul Express extinde Node.js pentru a furniza câteva componente cheie pentru controlul request-urilor web. Acesta permite implementarea unui server web cu doar câteva linii de cod.
Câteva din avantajele modulului Express:
Management-ul Rutării: Framework-ul Express permite definirea de „routes” (URL end points) într-un mod foarte simplu.
Controlul Errorilor: Express furnizează un mechanism de tratare a erorilor.
Integrare Simplă: Un Server Express poate fi implementat chiar dacă se folosesc sisteme proxy precum Nginx sau Varnish.
Cookies: Management-ul simplu al obiectelor Cookies.
Session: Control al sesiunii.
Cache: Control al cache-ului.
2.9. Front End
Programarea Front End, cunoscută și ca dezvoltare Client Side, are ca scop punerea împreună a tehnologiilor HTML, CSS și Javascript pentru conceperea unui website sau o aplicație web pentru ca utilizatorul sau clientul să poate interacționa cu acestea. Este o combinație între cunoștințele de programare puse în practică și estetică, adică înțelegerea corectă a poziționării elementelor componente unui website, a culorilor și fonturilor. Una din principalele provocări întâlnite în domeniul de dezvoltare Front End, este că tehnologiile utilizate pentru dezvoltarea paginilor web și standardele web sunt în continuă schimbare.
Obiectivul dezvoltatorilor Front End este ca în momentul în care utilizatorul deschide pagina web, informațiile sunt așezate și organizate într-un format accesibil, ușor de citit și de căutat dar mai ales relevant. Acest obiectiv a devenit din ce în ce mai dificil în ultimii ani deoarece utilizatorii au început să folosească paginile web de pe un număr tot mai mare de dispozitive electronice, de dimensiuni foarte variate, ceea ce nu este deloc de neglijat pentru un programator, care trebuie să aibă în vedere că aplicația web trebuie să ruleze corect pe diferite browsere, pe diferite sisteme de operare și pe diferite dispozitive.
Scopurile dezvoltării Front End sunt:
Accesibilitate: datorită ascensiunii dispozitivelor mobile precum smartphones sau tablete, programatorii și designerii trebuie să se asigure că produsul oferă aceeași calitate pe diferite browsere și dispozitive. Aceasta poate fi realizată prin creearea unui design responsive, folosind limbajul CSS.
Uzabilitate: Un website care respectă această proprietate este creat în așa fel ca utilizatorii să poată găsii informațiile cele mai importante într-un timp cât mai scurt.
Performanță: acest scop este corelat cu timpul de randare al paginii, manipularea HTML, CSS și JavaScript pentru a asigura un timp cât mai scurt de încărcare a paginii.
2.10. HTML
HTML sau HyperText Markup Language este un limbaj de programare (sau de marcare) standard folosit în dezvoltarea paginilor web. Este scris sub formă de elemente HTML numite tag-uri scrise între semnele < și > .
Browserul web poate să citească fișiere HTML și să le randeze în pagini web vizibile sau audibile. Browserul nu afișază tag-uril HTML sau scripturile, ci le folosește pentru a interpreta corect conținutul paginii. Limbajul HTML descrie structura paginilor web din punct de vedere semantic împreună cu indicii de prezentare, ceea ce face ca HTML să fie considerat mai degrabă un limbaj de marcare.
Fiecare website existent este construit din elemente și blocuri HTML. Acesta permite încapsularea de imagini sau obiecte și poate fi folosit pentru creearea de formulare interactive. Poate încapsula scripturi JavaScript, scripturi ce pot influența comportamentul și aspectul paginilor web.
Cel mai nou standard HTML lansat este bine cunoscutul HTML5, care a fost finalizat în Octombrie 2014. Principalele obiective ale acestuia sunt de a furniza suport pentru elementele multimedia nou apărute în timp ce păstrează paginile ușor de citit și folosit pentru utilizatori, dar și înțelese de către calculatoare și dispozitive.
HTML5 aduce o serie de îmbunătățiri și obiecte noi sintactive: printre acestea menționăm tag-urile video, audio și canvas, dar și MathML pentru formule matematice. Aceste îmbunătățiri au ca scop folosirea și vizualizarea cât mai ușoară a elementelor grafice și multimedia fără a avea nevoie de biblioteci sau plugin-uri.
2.11. CSS
CSS (Cascading Style Sheets) este un standard folosit în formatarea elementelor și aspectului documentelor HTML. Standardul CSS a fost conceput în principal pentru separarea conținutul documentului de prezentarea sa, aducând în vedere concepte precum amplasament, culori sau fonturi. Această separare aduce un plus accesibilității conținutului unui document, mai multă flexibilitate și control în specificarea caracteristicilor prezentării, permite ca mai multe pagini HTML să partajeze același stil specific și în același timp relevant, într-un singur fișier cu extensia .css, ceea ce reduce considerabil complexitatea și redundanța în partea structurală a documentului. De asemenea folosind CSS se poate ca stilul elementelor de bază HTML să fie configurat și specificat într-un fișier diferit sau într-un tag specific (style).
CSS este un standard simplu al zilelor noastre, ce ofera designerilor/programatorilor un mod eficient de a controla modul de prezentare a paginilor "WEB". In zilele noastre CSS a ajuns sa fie in mod primar, un limbaj folosit exclusiv doar pentru "web design" – insa nu putem exclude faptul ca acest limbaj este folosit si in alte medii de programare.
In comparatie cu era anilor 90, cand controlul prezentarii unei pagini se facea prin tag-uri HTML, divizate intre ele in mai multe fisiere, ce confereau o munca enorma in cazul unei actualizari, CSS vine cu un nou standard, si anume ca printr-un singur fisier ( o conventie intre programatori este sa se foloseasca numele general 'style.css' ) – sa fie controlat intreg aspectul proiectului WEB.
CSS nu necesita cunostinte avansate de hardware sau software, ci mai mult cateva cunostinte HTML, pentru a putea sa-l invatam. Citind acest manual, presupunem ca cititorul are deja cunostinte temeinice de HTML si ca intelege ce e acela un SGML ( Standard Generalized Markup Language ).
2.12. Javascript
JavaScript este un limbaj de programare dinamic, și este în mod comun utilizat în special pentru dezvoltarea paginilor web, a cărui implementare permite scripturilor client-side să interacționeze cu utilizatorul, controlul browser-ului, comincarea asincronă, și modificarea conținutului documentului HTML afișat. Limbajul JavaScript este coniderat ”limbajul de programare web” pentru realizarea de aplicații client-side. De asemenea este utilizat și pentru programarea server-side, folosind platforme precum Node.js, este folosit și pentru dezvoltare de jocuri și de asemenea pentru dezvoltarea de aplicații desktop sau pentru device-uri mobile.
Limbajul JavaScript este clasificat ca un limbaj de scripting bazat pe conceptul prototip. Este un limbaj dinamic care suportă programare orientată pe obiecte, imperativă și funcțională.
Chiar dacă din punct de vedere al numelui, din punct de vedere sintactic și cu excepția anumitor biblioteci standard, JavaScript și Java nu au nici o legătură și au o semantică diferită. Sintaxa limbajului JavaScript este defapt derivat din limbajul de programare C, în timp ce semantica și design-ul au fost influențate din limbajele de programare Self și Scheme.
JavaScript este de asemenea folosit în medii de programare care nu sunt de tip web-based, ca de exempu documente PDF, widget-uri desktop. Mașinile virtuale JavaScript noi sunt mai rapide și mai eficiente, la fel ca platfomele bazate pe acestea, au făcut ca popularitatea folosirii limbajului de programare JavaScript pentru aplicații de tip server-side să crească semnificativ.
2.13. AngularJS
AngularJS este un framework client-side dezvoltat de Google. Acesta furnizează toată funcționalitatea pentru controlul interacțiunii utlilzatorului cu browserul, manipularea informațiilor pe partea de client și controlul afișării elementelor . Scopul din spatele AngularJS a fost crearea unui framework care să permită implementarea simplă de aplicații web folosind framework-ul MVC.
Iată și câteva motive pentru care AngularJS este ceea ce avem nevoie:
Data Binding: AngularJS deține o metodă curată pentru asignarea (bind) datelor la elemente HTML folosind mecanismul scope.
Extensibilitate: Arhitectura AngularJS permite extinderea majorității aspectelor limbajului, pentru a permite o implementare cât mai personalizată.
Clean: Angular forțează programatorul să scrie cod curat, logic.
Cod reutilizabil: Combinarea dintre extensibilitate și cod curat duce la un cod reutilizabil.
Suport: Google investește foarte mult în acest proiect pentru a oferi avantaje acolo unde alte inițiative au eșuat.
Compatibilitate: AngularJS se bazează pe JavaScript și are o relație apropiată cu jQuery. Aceasta face mult mai simplu să integrezi AngularJS într-un mediu și să refolosesti cantități semnificative de cod existent.
Proiectare și implementare
3.1 Arhitectura
Figura 3-1. Arhitectura Serviciu Rest
Componentele principale ale proiectului sunt: un serviciu web (REST) alcătuit dintr-un servere Node.js și o bază de date NoSQL MongoDB, și un website realizat cu arhitectura MVC AngularJS.
Serviciul Web Node.js, configurat folosind framework-ul Express, are arhitectura unui web server, iar comunicarea cu baza de date se realizează folosind driver-ul MongoDB, iar pentru comunicarea cu pagina web se folosesc request-uri de tip GET/POST/PUT/DELETE.
Website-ul aplicației va fi dezvoltat folosind framework-ul AngularJS, ceea ce înseamnă că arhitectura website-ului va fi de tip MVC (Model View Controller):
Controller-ul poate fi regăsit în script-urile JavaScript, și este independent pentru fiecare pagină, iar în unele situații, pentru pagina de statistici, vor fi controllere individuale pentru fiecare grafic, pentru a păstra controllerele cât mai lizibile și logica reutilizabilă.
Modelul este definit de asemenea în scripturile JavaScript, și se bazează pe conceptul din Angular: scope. Acest concept este crucial de înțeles. Acest obiect poate fi definit simbolic ca „lipiciul” care permite template-ului (view), modelului și controller-ului să funcționeze îmreună. Biblioteca Angular folosește obiectul scope pentru a permite ca model-ul și view-ul să rămână separate dar sincronizate. Orice modificare a modelului este reflectată în view. Iar orice modificare a view-ului este reflectată în model.
View-ul este proiecția modelului prin template-ul HTML. Aceasta înseamnă că orice modificare a modelului, biblioteca Angular va actualiza view-ul.
3.2 Serviciul web și baza de date
3.2.1 Configurarea Serverului
Serviciul web Node.js este construit folosind framework-ul Express, iar pentru conectarea la baza de date MongoDB avem nevoie de un driver numit „collectionDriver”, care va defini într-un fișier JavaScript interogările către baza de date NoSQL. Pentru început definim principalele obiecte, dintre care remarcăm obiectul „express” care definește defapt principala componentă a serverului Node.js.
Pentru configurarea pachetului și dependențelor folosim fișierul package.json, care în cazul nostri arată astfel:
Codul 3-1. Configurarea pachetului și dependențelor Node.js
{
"name": "WebService MongoDB",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.3.4",
"mongodb": "1.3.23"
}
}
Acest fișier definește date structurale (metadata) ca de exemplu nume, versiune, scripturi sau dependențe. Din configurațiile proiectului nostru menționăm: name: numele proiectului, version: versiunea curentă a proiectului, private: previne publicarea accidentală a proiectului (în cazul în care este setat ca true), dependencies: reprezintă o listă a modulelor Node.js folosite de aplicația Node.js.
Prin apelul funcției require (precum în codul de mai jos) se importă pachetul cu numele respectiv într-o variabilă.
Codul 3-2. Cerințele și configurarea acestora în serviciul web
var http = require('http'),
express = require('express'),
path = require('path'),
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
CollectionDriver= require('./collectionDriver').CollectionDriver,
expressJwt = require('express-jwt'),
jwt = require('jsonwebtoken');
În continuare se va configura serverul folosind framework-ul Express. Folosm acest modul Node.js deoarece cu acest pachet separat putem defini cu ușurință căi și lanțuri de funcții de tip callback pentru fiecare request. De asemenea tratarea fiecărui request devine mult mai simplă deoarece acest modul poate trata și recunoaște request-urile în funcție de tip (GET, POST, DELETE, PUT etc).
Codul de mai jos crează aplicația Express (app) și setează portul 3000. A treia linie configurează aplicația Express pentru a putea trimite fișiere statice regăsite în folderul public, astfel vom putea accesa aplicația Angular regăsită în folderul public.
Codul 3-3. Configurarea obiectului Express
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'public')));
Paginile statice și rutarea acestora este o opțiune foarte utilă și utilizată, însă capacitățile pachetului Express sunt mult mai vaste, ca de exemplu rutarea dinamică. Modului Express folosește un „matcher” pentru expresii regulate, ceea ce va permite definirea parametrilor în adresele request-urilor.
Adresele pot conține următoarele:
Termeni statici: /files
Parametrii prefixați de „:”: /files/:parameter.
Parametrii opționali, cu sufixul „?”: /files/:parameter?, poate semnifica atât /files cât și /files/parametru.
Expresii regulate: /^\/people\/(\w+)/ poate să potriviească atât adresa /people/Andrei cât și adresa /people/Marius
Una din altele capacități ale serverului va fi tratarea erorilor. Erorile pot fi tratate în două moduri diferite: atât permiterea unei excepții să oprească aplicația, atât tratarea excepțiilor și returnarea codului specific excepției.
Protocolul HTTP 1.1 definește coduri de erori cuprinse în intervalul: 4xx – 5xx. Erorile cu codul 4xx sunt erori de tip user, ca de exemplu cererea unui obiect care nu există, iar unul din cele mai renumite coduri de eroare este 404 Not Found Error. Erorile de tip 5xx sunt erori ce ține de server, ca de exemplu erori de programare sau referințe spre null.
3.2.2 Baza de date
Baza de date MongoDB memorează obiecte JSON. Spre deosebire de bazele de date relaționale, Mongo este o bază de date de tip NoSQL, și nu suportă relații între entități. Tabelele în baza de date NoSQL se numesc colecții, și nu au nevoie să aibă câmpuri cu același nume sau un model prestabilit.
Arhitectura propusă pentru baza de date necesară stocării eficiente este formată din trei entități importante: pacienți (users), aparate (machines) și samples.
Figura 3-2. Entități principale ale bazei de date
Datorită relației dintre docunentele MongoDB și JSON, baza de date de Mongo este o opțiune excelentă atât pentru web cât și mobile. Baza de date MongoDB nu memorează în format JSON brut, ci în format BSON (Binary JSON), format care este mult mai eficient pentru stocarea datelor și pentru interogări.
Baza de date Mongo este o aplicație nativă și este accesată de către server folosind drivere. Driverul Mongo se conectează la baza de date și solicită acțiuni de citire sau scriere.
Prima configurare care trebuie făcută este importarea pachetelor necesare, iar pentru început avem nevoie de funcția ObjectID.
Codul 3-4. Definirea obiectului ObjectID pentru configurarea id-ului fiecărei înregistrări
var ObjectID = require('mongodb').ObjectID;
Dacă pentru bazele de date relaționale pentru indexare se folosește un id unic numi cheie primară, un concept asemănător este folosit și în cazul de față. Fiecare entitate adăugată are alocat un câmp denumit _id, iar pentru accesarea și compararea acestuia este nevoie de funcția ObjectID, deoarece acesta nu este de tip BSON.
Codul 3-5. Definirea obiectului driver
CollectionDriver = function(db) {
this.db = db;
};
Prin codul de mai sus se definește constructorul CollectionDriver. Acesta memorează o instanță a clientului MongoDB pentru folosința ulterioară.
Codul 3-6. Funcția getCollection
CollectionDriver.prototype.getCollection = function(collectionName, callback) {
this.db.collection(collectionName, function(error, the_collection) {
if( error ) callback(error);
else callback(null, the_collection);
});
};
Acest bloc de cod definește o metodă auxiliară pentru obținerea unei colecții după nume. Se poate observa definirea metodelor de clasă prin adăugarea metodelor la prototype.
Codul 3-6. Cod pentru căutarea unei colecții în Baza de date
db.collection(name,callback)
Această linie caută în baza de date colecția și returnează după caz ori eroare ori colecția găsită după nume.
Codul 3-7. Funcția findAll – pentru căutarea conținutului unei entități
//find all objects for a collection
CollectionDriver.prototype.findAll = function(collectionName, callback) {
this.getCollection(collectionName, function(error, the_collection) {
if( error ) callback(error)
else {
the_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
Funcția findAll se folosește de funcția getCollection definită mai sus, și obține colecția cu numele primit ca parametru, iar mai apoi dacă nu apare nici o eroare apelează funcția find. Această funcție returnează un cursor de date care poate fi folosit pentru iterarea obiectelor ce se potrivesc. Funcția find poate accepta și diverse filtre pentru selectarea rezultatului. Funcția toArray organizează datele într-o listă care va fi trimisă mai apoi în către funția callback. În final funcția callback finală va returna ori eroare ori toate rezultatele găsite.
Codul 3-8. Funcția get – pentru căutarea unei înregistrări după id
//find a specific object
CollectionDriver.prototype.get = function(collectionName, id, callback) {
this.getCollection(collectionName, function(error, the_collection) {
if (error) callback(error)
else {
var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
if (!checkForHexRegExp.test(id)) callback({error: "invalid id"});
else the_collection.findOne({'_id':ObjectID(id)}, function(error,doc) {
if (error) callback(error)
else callback(null, doc);
});
}
});
}
Funcția CollectionDriver.prototype.get de mai sus obține un singur obiect după câmpul _id. Similar funcției findAll, metoda obține colecția în funcție de nume, iar mai apoi apelează funcția findOne pentru colecția găsită. Baza de date Mongo stochează id-ul în format BSON astfel că avem nevoie de funcția ObjectID care va realiza conversia pentru a putea obține rezultatul dorit, dar nu înainte de a verifica folosind funcția checkForHexRegExp dacă id-ul este valid. În linia {'_id':ObjectID(id)}, se poate observa folosirea unui filtru pentru a obține doar obiectul JSON dorit.
Driverul bazei de date Mongo conține următoarele funcții:
getCollection: prezentată mai sus, folosită pentru a obține obiectul unei colecții în funcție de numele ei;
findAll: funcție prezentată mai sus, folosită pentru a interoga o întreagă colecție;
get: funcție folosită pentru a interoga un obiect specific;
getMachineByID: funcție folosită pentru a interoga un obiect mașină din întreaga colecție de aparate, în funcție de pacientul asociat aparatului.
getSamplesByID: funcție folosită pentru a interoga întreaga activitate a unui aparat în funcție de id-ul aparatului selectat.
Save: funcție folosită pentru salvarea unui obiect într-o colecție.
Update: funcție folosită pentru actualizarea unei entități.
Delete: funcție folosită pentru ștergearea unei entități dintr-o colecție.
Drop: funcție folosită pentru ștergerea unei întregi colecții.
Acesta este conținutul driver-ului bazei de date MongoDB, regăsit în fișierul CollectionDriver.js. Astfel dacă driverul este pregătit, este nevoie să fie integrat în serverul web pentru ca funcțiile aferente driverui să poată fi folosite, iar serverul să aibă acces la baza de date.
În continuare vom include obiectele aferente clientului bazei de date Mongo și pentru server din modulul MongoDB iar mai apoi driverul:
Codul 3-9. Obiectele necesare pentru folosirea bazei de date
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
CollectionDriver = require('./collectionDriver').CollectionDriver;
În continuare vom configura baza de date pentru a putea fi accesată în mod corect de către serviciul web Node.js. Vom seta port-ul și ip-ul pe care rulează baza de date MongoDB. După aceasta se creează clientul Mongo (MongoClient) și se stabilește conexiunea. Dacă conexiunea nu se poate realiza, ori baza de date nu este pornită sau nu s-a setat corect ip-ul și portul.
Codul 3-10. Configurarea conexiunii la baza de date
var mongoHost = 'localHost';
var mongoPort = 27017;
var collectionDriver;
var mongoClient = new MongoClient(new Server(mongoHost, mongoPort));
mongoClient.open(function(err, mongoClient) {
if (!mongoClient) {
console.error("Error! Exiting… Must start MongoDB first");
process.exit(1);
}
var db = mongoClient.db("MyDatabase");
collectionDriver = new CollectionDriver(db);
});
3.2.3 Autentificare de tip Token-Based
Pentru componenta de autentificare a serviciului web Node.js există două posibilități de implementare:
Cookie-Based Authentification: acest mod de implementare a componentei de autentificare server-side este cea mai folosită metodă și folosește cookies server-side pentru a valida fiecare request.
Token-Based Authentification: o metoda mai nouă, care constă în folosirea unui token unic pentru validarea request-urilor.
Figura 3-3. Request-uri necesare pentru autentificare
Diagrama de mai sus explică cum funcționează cele doua metode de autentificare.
Avantajele utilizării metodei Token-Based sunt:
Cross-domain: O abordare Token-Based permite trimiterea request-urilor AJAX către orice server și orice domeniu, deoarece pentru transmiterea informaților prin antetul (header) request-urilor.
Stateless (Scalabilitate a serverului): nu este nevoie de memorarea tuturor sesiunilor deoarece token-ul este o entitate care conține informațiile despre utilizator. Pentru client, starea este memorată prin cokie-uri sau în local storage.
Favorabil pentru mobil: Pentru platformele mobile (iOS, Android, Windows) nu este cel mai recomandat să fie folosite cookie-uri, iar această abordare este mai recomandată.
Performanță mai bună.
Există standarde pentru Jason Web Token (JWT), format pentru aceste token-uri pentru diverse medii de programare.
Pentru partea de server există două principale dependențe: framework-urile express-jwt și jsonwebtoken.
Pentru configurarea acestei componente a serviciului web vom seta adresa protejată cu framework-ul JWT:
app.use('/webService', expressJwt({secret: secret}));
Funcția pentru tratarea request-ului de autentificare va verifica dacă numele de utilizator este valid și va trimite token-ul dacă este cazul, sau atlfel codul 401 de eroare.
Codul 3-11. Request-ul de autentificare
app.post('/authenticate', function (req, res) {
//validate req.body.username and req.body.password
//if is invalid, return 401
var username = req.body.username;
var password = req.body.password;
console.log(username,password)
collectionDriver.getLoginDetails(username, function(err, object){
if (object!=null){
if (!(username === object.username && password === object.password)) {
res.send(401, 'Wrong user or password');
return;
}
// We are sending the profile inside the token
var token = jwt.sign(object, secret, { expiresInMinutes: 60*5 });
res.json({ token: token });
} else {
res.send(401, 'Wrong user or password');
return;
}
});
});
Astfel orice request va fi trimis la serviciul web pe adresa protejata webService, serverul va testa de fiecare dată daca token-ul este valid iar în caz de invaliditate va trimite cod de eroare ca răspuns.
3.2.4 Interfața webService
Interfața oferită de serviciul web pentru controlul și afișarea datelor va presupune mai multe tipuri de request-uri și adrese. Tipurile de request-uri care pot fi trimise și folosite cu succes în cazul serviciului Node.js sunt: GET, POST, PUT și DELETE. Fiecare din aceste metode va trebui trimis la adresa configurată de interfața Node.js.
Pentru accesarea datelor se folosesc doar metode de tip GET. Căile de acces sunt de două tipuri:
GET „/webService/:collection”.
Adresa la care trebuie trimis request-ul de tip GET de acest tip conține în primul rând numele interfeței (webService), iar mai apoi separate de un caracter „ / ” numele entități care se dorește să fie primită. Dacă serviciul ar fi fost conectat la o bază de date relaționlă atunci această entitate era un tabel, dar în cazul nostru, deoarece serviciul comunică cu o bază de date de tip NoSQL (MongoDB), vorbim despre o colecție de date.
Metoda Node.js este configurată astfel:
Codul 3-12. Request-ul pentru obținerea unei colecții
app.get('/webService/:collection', function(req, res) {
var params = req.params;
collectionDriver.findAll(params.collection, function(error, objs) {
if (error) {
res.send(400, error);
} else {
res.set('Content-Type', 'application/json');
res.send(200, objs);
}
});
});
În primul rând după ce request-ul este primit, metoda identifică în mod corect parametrul funcției, în cazul nostru colecția, iar mai apoi se va accesa, folosind driverul bazei de date, funcția findAll (descrisă la capitolul 4.2.2) . În caz de eroare metoda va returna către client codul de eroare 400, iar în caz de succes va returna conținutul colecției dorite.
GET „/webService/:collection/:entity”.
Metoda cu numărul 2, din metodele GET, va presupune accesarea unui obiect specific dintr-o colecție, desigur în funcție de id-ul obiectului.
Codul 3-13. Request-ul pentru obținerea unei înregistrări din colecție
app.get('/webService/:collection/:entity', function(req, res) {
var params = req.params;
var entity = params.entity;
var collection = params.collection;
if (entity) {
collectionDriver.get(collection, entity, function(error, objs) {
if (error) {
res.send(400, error);
} else {
res.send(200, objs);
}
});
} else {
res.send(400, {
error : 'bad url',
url : req.url
});
}
});
În primul rând după ce request-ul este primit, metoda identifică în mod corect parametrii funcției, în cazul nostru colecția și id-ul obiectului dorit, iar mai apoi se va accesa, folosind driverul bazei de date, funcția get (descrisă la capitolul 4.2.2) . În caz de eroare metoda va returna către client codul de eroare 400, iar în caz de succes va returna conținutul colecției dorite.
GET „/webService/:machines/byID/:id”.
Metoda aceasta se va folosi de funcția getMachineByID descrisă la capitolul 4.2.2 pentru a returna obiectul aparatului de tratare a apneei dorit, în funcție de id-ul său.
GET „webService/getSamples/:sampleCollection/:id”.
Metoda aceasta se va folosi de funcția getSamplesForId descrisă la capitolul 4.2.2 pentru a interoga întreaga activitate a unui aparat în funcție de id-ul aparatului selectat.
Interfața oferită aparatului (măștii) de tratare a apneei este alcătuită dintr-o adresă cu 2 parametri accesată de aparat, și arată astfel: „/sample/:machine/:value”.
Parametrii componenți ai adresei sunt: id-ul mașinii (aparatului), id introdus de medicul sau administratorul care configurează aparatele, și cel de-al doilea parametru, valoarea care reprezintă starea aparatului în ziua care a fost folosit.
Codul 3-14. Interfața serviciului pentru masca de tratare a apneei
app.get('/sample/:mach/:val',function(req,res){
var params = req.params;
var machine = params.mach;
var value = params.val;
var currentDate = new Date();
var day = currentDate.getDate();
var month = currentDate.getMonth() + 1;
var year = currentDate.getFullYear();
var sysdate = day + "-" + month + "-" + year;
console.log("sample Called: "+machine+", "+value+", "+sysdate);
var object = {"id_machine": machine, "value": value, "date": sysdate};
collectionDriver.save("samples", object, function(err, docs) {
if (err) {
res.send(400, err);
} else {
res.send(201, docs);
}
});
})
Această metoda, tot de tip GET, va calcula data din momentul în care s-a primit request-ul, iar mai apoi va introduce în baza de date în colecția samples, folosind funcția driverului numita save, obiectul alcătuit din id-ul mașinii, starea și data.
Pentru introducerea datelor în baza de date Mongo se folosește o interfață simplă formată din request-uri de tip POST, la adresa: „/webService/:collection”. Adresa va avea ca paremetru numele colecției în care se doresc să fie introduse datele primite în corpul request-ului de tip POST, care va conține un obiect de tip JSON.
Codul 3-15. Introducerea de date în baza de date
app.post('/webService/:collection', function(req, res) {
var object = req.body;
var collection = req.params.collection;
collectionDriver.save(collection, object, function(err, docs) {
if (err) {
res.send(400, err);
} else {
res.send(201, docs);
}
});
});
Se observă că metoda Node.js va determina parametrul adresei, numele colecției, și obiectul din corpul request-ului, ca mai apoi să apeleze funcția driverului numită save, pentru a salva noul obiect JSON în colecția dorită.
Pentru editarea datelor interfața este reprezentată de un simplu request PUT, la adresa „/webService/:collection/:id”, unde parametri care trebuie introduși sunt numele colecției și id-ul obiectului care se dorește a fi modificat cu obiectul regăsit de asemenea, ca în cazul request-ului de tip POST, în corpul request-ului.
Codul 3-15. Introducerea de date în baza de date
app.put('/webService/:collection/:entity', function(req, res) {
var params = req.params;
var entity = params.entity;
var collection = params.collection;
if (entity) {
collectionDriver.update(collection, req.body, entity, function(error, objs) {
if (error) {
res.send(400, error);
} else {
res.send(200, objs);
}
});
} else {
var error = {
"message" : "Cannot PUT a whole collection"
}
res.send(400, error);
}
});
Se observă că metoda Node.js va determina parametrii adresei, numele colecției și id-ul obiectului care se dorește a fi modificat, și obiectul din corpul request-ului, ca mai apoi să apeleze funcția driverului numită update, pentru a modifica obiectul JSON dorit.
Pentru ștergerea datelor, interfața oferă două modalități: ștergerea unei colecții de date întregi, sau ștergerea doar a unui obiect dintr-o colecție.
Ștergerea unei colecții
Ștergerea unei colecții se va realiza prin apelarea adresei „/webService/:collection/”, printr-un request de tip DELETE. Parametrul adresei este numele colecției.
Ștergerea unui obiect
Ștergerea unui obiect dintr-o colecție se va realiza prin apelarea adresei „/webService/:collection/:id”, printr-un request de tip DELETE. Parametrii adresei sunt numele colecției și id-ul obiectul care se dorește a fi șters.
3.3 Website AngularJS
3.3.1 Vedere de ansamblu
Pentru dezvoltarea paginii web, s-au folosit următoarele biblioteci:
AngularJS – versiunea 1.3.0;
Angular-Route
Biblioteca și componentele Mobile-Angular-UI
Google Charts Library
Angular NVD3 charting library
Folosirea bibliotecii Angular permite, așa cum aminteam la punctul 4.1, implementarea paginii și a logicii website-ului folosind pattern-ul MVC. Astfel pentru început trebuie stabilit unde vor fi plasate elementele Model, View și Controller.
Toate elementele de tip Controller sunt scrise în limbajul de programare JavaScript și vor fi scrise în fișiere separate, și plasate în folderul „/src/js”. Am ales să împart logica în mai multe fișiere pentru a simplifica programarea și urmărirea logicii fiecărei pagini, logica fiind regăsită în controller-ul template-ului (view) respectiv în fișierul specific controller-ului. Astfel în folderul specificat, vom avea mai multe fișiere javascript, unul denumit „app.js”, acesta va conține toate funcțiile globale, aici va fi configurat modulul principal Angular, și vor fi specificate toate modulele specifice și desigur funcția Angular „run” care va fi executată la intrarea în pagină, respectiv la orice „refresh”. În același folder vom regăsi șă un fișier „service.js” care va conține serviciul HTTP Angular, creat pentru simplificarea comunicării cu serviciul Node.js folosind request-uri. Pe lângă aceste 2 fișiere vor fi regăsite fișiere pentru fiecare controller al fiecărei pagini.
Modelurile vor fi regăsite în fiecare controller, deoarece conceptul principal folosit pentru arhitectura MVC este obiectul scope. Acest obiect scope este specific fiecărui controller, iar pentru comunicare între pagini va fi folosi și părinte rootScope.
View-urile sunt strâns legate de Template-urile HTML, care sunt fișiere HTML, care conțin toate obiectele HTML regăsite în pagină, iar încărcarea fiecăruia va fi realizată dinamic de către biblioteca de rutare folosita (Angular-Route).
Figura 3-4. Arhitectura MVC implementată în frameworkul Angular
3.3.2 Configurare
Dependențele și principalele proprietăți ale documentului HTML, sunt difinite ca la orice pagină web în fișierul „index.html”, regăsit la rădăcina structurii directoarelor. Acest fișier conține următoarele configurări în tag-ul head:
Codul 3-16. Configurarea documentului HTML
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimal-ui" />
Aceste linii de configurare definesc următoarele proprietăți:
Prima linie definește encodarea caracterelor pentru documentul HTML: UTF-8 (Unicode). A doua linie, X-UA-Compatible, va specifica versiunea de InternetExplorer pentru care va fi randată pagina , iar IE=Edge (edge este numele următorului browser de la Microsoft) va face ca randarea conținutului paginii să fie realizată la cel mai nou nivel. Următoarea linie, apple-mobile-web-app-capable va specifica înărcarea paginii în mod full-screen pe browserele Safari.
Următoarea linie de configurare, va specifica faptul că pagina nu va permite zoom-ul pentru dispozitivele mobile cu touch-screen, deoarece pagina va fi responsive (interfața va fi scalabilă și specifică pentru toate rezoluțiile).
După aceste linii de configurare în continuare în tag-ul head vor fi încărcate toate biblioteciile și toate fișierele javascript respectiv css care vor fi încărcate odată cu accesarea paginii.
Configurarea modului Angular se realizează astfel:
Codul 3-16. Configurarea aplicației Angular
var app = angular.module('AngularApp', ['ngRoute', 'mobile-angular-ui', 'nvd3ChartDirectives', 'mobile-angular-ui.gestures']);
Prin această linie de configurare, se menționează toate modulele Angular pe care aplicația web le utilizează. Astfel observăm că folosim modulul ngRoute ( folosit pentru configurarea rutării paginilor și controlerelor în funcție de URL), observăm folosirea modulelor mobile-angular-ui și mobile-angular-ui.gestures, de care este nevoie pentru interfața Mobile-Anguar-UI, interfață care se bazează pe Bootrstrap și Angular. Celălalt modul folosit este nvd3ChartDirectives folosit pentru unele obiecte grafice de statistică.
3.3.3 Arhitectură. Rutare.
Website-ul conține 4 pagini principale, pe lângă cea de autentificare, după cum urmează: „Home Page”, „Users”, „Machines” și „Statistics”.
Figura 3-5. Interfață pentru cele 4 pagini
Fiecare pagină are un view (template) propriu și un controler asociat, iar rutarea se realizează prin modulul Angular „ngRoute”.
Codul 3-17. Configurarea adreselor (routes)
app.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl : 'pages/home.html',
controller : "homeController",
reloadOnSearch : false
});
$routeProvider.when('/insertUser', {
templateUrl : 'pages/insertUser.html',
controller : 'insertUserController',
reloadOnSearch : false
});
$routeProvider.when('/insertMachine', {
templateUrl : 'pages/insertMachine.html',
controller : 'insertMachineController',
reloadOnSearch : false
});
$routeProvider.when('/graphs', {
templateUrl : 'pages/graphs.html',
controller : 'graphsController',
reloadOnSearch : false
});
});
După cum putem observa din această bucată de cod, modulul $routeProvider realizează rutarea după cum urmează: când se întâlnește în URL numele paginii, $routeProvider încarcă automat template-ul configurat în această secvență de cod, și mai important încarcă controlerul repartizat tot aici. Astfel navigarea între pagini devine foarte simplu de controlat deoarece acest modul se ocupă de tranziții și de încărcarea paginii dorite.
Aceste „pagini” sau mai corect spus, aceste „template”-uri vor fi încărcate în locul specificat clar de directiva „ng-view”, directivă plasată în fișierul index.html.
Pe lângă aceste template-uri mai există unul pentru bara de navigare din stânga și unul pentru bara de nagiare din dreapta. Acestea sunt incluse în fișierul „index.html”:
Codul 3-18. Includerea meniurilor de navigare
<div ng-include="'pages/sidebar.html'" ui-track-as-search-param='true' class="sidebar sidebar-left"></div>
<div ng-include="'pages/sidebarRight.html'" class="sidebar sidebar-right"></div>
3.3.4 Interfața
Pentru interfața grafică am ales să folosesc framework-ul „mobile-angular-ui”, un framework pentru interfața cu utilizatorul care folosește AngularJS și Bootstrap. Acest framework funrizează componente pentru interfața grafică fără dependențe jQuery sau cod bootstrap, ci doar module („directive”) simple AngularJS.
Unul din principalele avantaje ale interfaței Mobile-Angular-UI este că furnizează o interfață simplu de controlat și de manipulat (necesita cunoștințe de Angular și puțin Bootstrap), dar mai ales furnizează o interfață cu elemente moderne și componente actuale toate fiind Responsive. Aceasta înseamnă că website-ul va avea o interfață care se va plia pe ecran indiferent de rezoluție, și indiferent de dispozitivul pe care este încărcat, indiferent că este tabletă, telefon mobil sau laptop. De menționat este că acest framework suportă și o serie de gesturi folosite pe dispozitivele cu ecran tactil.
Figura 3-6. Componente Mobile-Angular-UI
O scurtă vedere de ansamblu a interfeței:
Figura 3-7. Interfață CSS Responsive
Principalele componente ale interfeței sunt următoarele:
Principalele 4 componente ale interfeței sunt: cele 2 sidebar-uri laterale, un NavigationBar în partea de sus pentru titlu și partea importantă a interfeței: body.
Left Sidebar. Această componentă are ca rol principal afișarea paginilor disponibile și se ocupă de partea de navigare între paginile website-ului. După cum spuneam la începutul subcapitolului, interfața și elementele din ea sunt „responsive”. Astfel acest element lateral va fi afișat doar când dispozitivul va avea o rezoluție destul de wide ca să permită afișarea meniului lateral. În cazul în care pagina este randată pe un dispozitiv mobil, smarphone sau tabletă, elementul nu va fi afișat, el însă va putea fi accesat folosind butonul din colțul din stânga sus al paginii, sau printr-un gest de „swipe” din partea stângă spre dreapta pentru toate dispozitivele cu ecran tactil.
Right Sidebar. A doua componentă importantă din interfața grafică este meniul lateral din partea dreaptă. Acesta are ca scop afișarea unor notificări în cazul în care medicul trebuie alertat cu privire la folosirea în mod deficitar a măștii pentru tratarea apneei de către unul sau mai mulți pacienți. Meniul lateral din partea dreaptă nu va fi afișat niciodată pe ecranuul principal, ci întotdeauna va putea fi extins folosind butonul din partea colțul drept de sus după cum se poate observa în figura următoare:
Navigation Bar. Antetul paginii este standardizat pentru toate paginile aplicației web și conține 3 elemente: în primul rând antetul trebuie să conțină titlul paginii curente, mai apoi în extremmitatea stângă trebuie să conțină butonul pentru extinderea meniului de navigare din partea dreaptă în cazul în care rezoluția ecranului nu este destul de wide. Un al treilea element al acestei componente se găsește în extremitatea dreaptă a antetului și este butonul de extindere a meniului lateral din dreapta.
Ultimul element este cel care ocupă cel mai mult spațiu pe suprafața ecranului, și l-am numit simplu „body”. În acest modul al interfeței vor fi randate toate componentele paginii web, toate informațiile aplicației și toate statisticile.
Din cele 4 componente amintite, cu excepția antetului, toate vor fi randate folosind template-ul HTML propriu, regăsit în folderul „/pages”. Pentru cele două meniuri laterale va exista un singur template pentru fiecare dintre componente, iar pentru corpul website-ului template-ul va fi selectat în funcție de pagina curentă, și va fi încărcat conform configurărilor făcute la punctul 4.3.3, configurări ale modulului ngRoute.
În fișierul index.html, vor fi plasate directivele pentru stabilirea interfeței, începând cu cele două meniuri laterale, care vor fi încărcate conform punctului 4.3.3. De asemenea pentru configurarea în mod corect a antetului paginii, vom plasa în fișierul index.html câteva etichete, elemente de tip „div”, care vor folosi clase CSS Bootrstrap prin care se va genera în mod corect și cu aspectul dorit, plasarea antetului și a corpului paginii, unde va fi încărcat ulterior template-ul dorit.
Pentru antet-ul paginii, bara de navigare, se vor folosi clasele bootstrap: navbar,navbar-app, navbar-absolute-top:
Codul 3-19. Tag configurat pentru header folosind Bootrstrap și conținutul acestuia
<div class="navbar navbar-app navbar-absolute-top">
<!– continut navbar –>
</div>
<!– In navbar vom avea urmatorul div–>
<div class="navbar-brand navbar-brand-center" ui-yield-to="title">
Apneea Application
</div>
<!– In template vom avea urmatorul div–>
<div ui-content-for="title">
<span>Machines</span>
</div>
În continuare pentru titlul paginii se va folosi directiva ui-yield-to împreună cu directiva ui-content-for astfel că pentru fiecare pagină, în fișierul HTML care va conține template-ul aferent paginii dorite, se va putea configura în mod unic și specific conținutul titlului.
Pentru cele două butoane care vor fi folosite pentru deschiderea celor două meniuri laterale, vom folosi icoane generate de Font Awesome, și câteva clase Bootstrap care pot fi observate mai jos:
Codul 3-20. Butonul de expandare a eniului lateral stâng
<div class="btn-group pull-left">
<div ui-toggle="uiSidebarLeft" class="btn sidebar-toggle">
<i class="fa fa-bars"></i> Menu
</div>
</div>
Codul 3-21. Butonul de expandare a eniului lateral drept
<div class="btn-group pull-right" ui-yield-to="navbarAction">
<div ui-toggle="uiSidebarRight" class="btn">
Alerts
<i class="fa fa-envelope" style="margin-left:5px"></i>
</div>
</div>
În continuare urmează directiva pentru încărcare a conținutului paginii și o etichetă care conține o animație pentru momentele în care se așteaptă încărcarea paginii.
Codul 3-22. Directiva pentru conținutul paginii
<!– App Body –>
<div class="app-body" ng-class="{loading: loading}">
<div ng-show="loading" class="app-content-loading">
<i class="fa fa-spinner fa-spin loading-spinner"></i>
</div>
<div class="app-content">
<ng-view></ng-view>
</div>
</div>
Animația arată astfel:
3.3.5 Serviciul Angular HTTP
Pentru comunicarea cu serverul Node.js, a fost dezvoltat un serviciu AngularJS denumit „serviceHTTP”. Acest serviciu Angular implementează funcțiile HTTP pentru comunicarea cu serverul. Principalele funcții de comunicare implementate sunt request-urile de tip: POST, GET, DELETE, PUT. Funcțiile se numesc: post, get, deleteReq, edit.
app.service('serviceHttp', function($http)
În continuare voi prezenta funcțiile implementate de serviciul HTTP:
Funcția „post” este utilizată pentru a adăuga date în baza de date NoSQL MongoDB. Pentru aceasta funcția are nevoie ca parametrii: url-ul către care v-a fi trimis request-ul pentru a putea fi tratat in mod corect de către server, obiectul JSON trimis prin request POST către servicul Node.js, iar ultimul parametru este funcția callback, care va fi executată în momentul în care va fi primit răspunsul din partea serverului.
Codul 3-23. Funcția pentru trimiterea unui request de tip POST a serviciului HTTP
this.post = function(url, dataA, callback) {
var req = {
method : 'POST',
url : url,
data : dataA,
}
$http(req).success(function(data, status) {
callback(data)
}).error(function() {
console.log("error on post – service Function")
});
}
Funcția „get” este utilizată pentru a cere și a primi date de la server. Aceasta este cea mai utilizată funcție a serviciului HTTP, deoarece principalul obiectiv al paginii web este să arate statistici și informații despre pacienți. Parametrii pe care îi are această funcție sunt: url-ul către care va fi trimis request-ul și funcția callback care va fi apelată pentru afișarea sau pregătirea informațiilor.
Codul 3-24. Funcția pentru trimiterea unui request de tip GET a serviciului HTTP
this.get = function(url, callback) {
var req = {
method : 'GET',
url : url,
}
$http(req).success(function(data, status) {
callback(data);
}).error(function(data, status) {
console.log("error on get – service Function")
});
}
Funcția „deleteReq” este funcția serviciului folosită pentru ștergerea de informații din baza de date. Parametrii funcției sunt url-ul care conține principalele componente și specifică exact ce trebuie să fie șters din baza de date, și funcția callback care va fi apelată când va sosi răspunsul din partea serverului.
Codul 3-25. Funcția pentru trimiterea unui request de tip DELETE a serviciului HTTP
this.deleteReq = function(url, callback) {
var req = {
method : 'DELETE',
url : url
}
$http(req).success(function(data, status) {
callback(data);
}).error(function() {
console.log("error on deleteReq – service Function")
});
}
Funcția „edit” realizează partea de editare a informațiilor din baza de date, după cum îi spune și numele. Funcția va trimite un request de tip PUT spre server, la adresa luată ca prim parametru (url-ul). De asemenea request-ul va trimite obiectul JSON care va conține informațiile noi care trebuie să înlocuiască pe cele vechi în baza de date, iar obiectul va fi primit prin cel de-al doilea parametru al funcției , iar cel de-al treilea parametru va fi funcția callback care va fi apelată la sosirea răspunsului din partea serverului.
Codul 3-26. Funcția pentru trimiterea unui request de tip PUT a serviciului HTTP
this.edit = function(url, dataA, callback) {
console.log(url)
console.log(dataA)
var req = {
method : 'PUT',
url : url,
data : dataA,
}
$http(req).success(function(data, status) {
callback(data)
}).error(function() {
console.log("error on PUT – service Function")
});
}
3.3.6 Logica de Autentificare
Pagina de autentificare apare atât la prima utilizare a aplicației web, cât și în momentul expirării sesiunii. După cum s-a spus la punctul 4.2.3 autentificarea se realizează pe baza unui token. Acest token va fi memorat pentru utilizare în localStorage-ul browser-ului.
Interfața de autentificare este reprezentată de un obiect HTML de tip form:
Codul 3-27. Formular pentru autentificare
<form ng-submit="submit()" class="col-sm-5 center-form" style="text-align: left">
<div class="form-group">
<label>Username</label>
<input
ng-model="user.username" class="form-control" type="text" name="user" placeholder="Username" />
</div>
<div class="form-group">
<label>Password</label>
<input ng-model="user.password" class="form-control" type="password" name="pass" placeholder="Password" />
</div>
<input class="btn btn-primary pull-right" type="submit" value="Login" />
</form>
Iar rezultatul vizual va fi următorul:
Controlerul acestui view va realiza în momentul accesării butonului de login un request HTTP cu adresa „/authenticate” (descrisă la punctul 4.2.3).
Codul 3-28. Funcția submit a formularului
$scope.submit = function() {
$http.post('/authenticate', $scope.user)
.success(function(data, status, headers, config) {
$window.sessionStorage.token = data.token;
$rootScope.Ui.turnOff('modal1');
$location.path("/");
$route.reload();
$scope.message = '';
}).error(function(data, status, headers, config) {
// Erase the token if the user fails to log in
delete $window.sessionStorage.token;
// Handle login errors here
$scope.message = 'Error: '+data;
});
};
După cum se poate observa în codul de mai sus, în momentul în care răspunsul de la serviciul web vine, dacă autentificarea a avut loc cu succes atunci se memorează token-ul primit, și se va naviga spre pagina dorită. În caz de eroare se șterge token-ul din local storage, și se afișează mesajul de eroare.
Acum că token-ul este salva în spațiul de stocare local al browser-ului, trebuie configurat serviciul HTTP AngularJS pentru ca fiecare request trimis către serviciul web să conțină în header token-ul existent:
Codul 3-29. Configurarea serviciului pentru mecanismul de Autentificare
app.factory('authInterceptor', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' +
$window.sessionStorage.token;
}
return config;
},
response: function (response) {
if (response.status === 401) {
// handle the case where the user is not authenticated
}
return response || $q.when(response);
}
};
});
myApp.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
Pentru deconectare se va șterge din spațiul de stocare al browser-ului acest token iar fiecare request trimis către serviciul web va fi respins.
3.3.7 Pagina principală – HomePage
Pagina principală, denumită simplu „Home Page” este pagina care întâmpină utilizatorul (medicii în cazul nostru). Pe această pagină se pot regăsi următoarele elemente: un titlu de întâmpinare, o listă cu pacienții, iar pentru fiecare dintre ei un buton care ne redirecționează către pagina cu statistici pentru respectivul pacient și un obiect de intrare pentru căutarea pacientului cu numele dorit.
În figură se pot observa elementele grafice ale interfaței, meniul de navigare în partea stângă, antetul în partea de sus a paginii, iar în corpul paginii se randează view-ul configurat pentru pagina de start, mai specific pentru adresa URL „ / ”.
Această pagină a aplicației web are două componente principale despre care doresc sa vorbim: un template HTML și un controler, cele două fiind încărcate concomitent de către modulul de rutare Angular (ngRoute).
Principalele componente ale interfeței sunt acea bară de căutare și lista cu pacienți. Pentru lista cu pacienți se folosește în primul rând directiva Angular ng-repeat, iar pentru butonul de redirectare spre pagina detaliată a pacientului se folosește directiva ng-click.
Codul 3-30. Listă în aplicația web
<div class="list-group-item" style=>
<input type="text" class="form-control" ng-model="search.name" placeholder="Search">
</div>
<div class="list-group-item row" ng-repeat="item in users | filter:search track by item.name " >
<div class="col-xs-8">
{{item.name}}
<br>
<b>Address:</b> {{item.address}}
<br>
<b>Email:</b> {{item.email}}
</div>
<div class="col-xs-4" style="color: #007aff" ng-click="selectUser(item)">
<div class="pull-right btn">
More details
<i class="fa fa-line-chart"></i>
</div>
</div>
</div>
Controlerul este configurat astfel:
Codul 3-31. Configurarea controlerului
app.controller('homeController', function($rootScope, $scope, $http, $location, serviceHttp) { … });
În interiorul controlerului vom face un request către server pentru a obține pacienții, care trebuie memorați în $scope pentru a putea fi afișați în view-ul aplicației.
Codul 3-32. Request pentru obținerea pacienților
$scope.users = [];
serviceHttp.get("/webService/usersT", function(json) {
for (var i = 0; i < json.length; i++) {
$scope.users.push(json[i]);
}
});
Funcția apelată pentru a naviga spre pagina cu statistici despre utilizatori est următoarea:
Codul 3-33. Funcție pentru controlul navigației
$scope.selectUser = function(item) { localStorage.setItem("userID", item.user_id);
localStorage.setItem("userName", item.name);
$location.path("graphs");
}
3.3.8 Pagina de adăugare/editare a pacienților
Pagina aceasta este destinată în primul rând adăugării de pacienți în baza de date, dar și pentru editarea acestor entități și asignarea aparatului pentru tratarea apneei.
Aceasta este vederea care apare la început, și avem la dispoziție o listă cu utilizatorii existenți în vederea detaliilor despre aceștia, dar și în vederea actualizării informațiilor referitoare la ei
Dacă se dorește adăugarea unui nou pacient în baza de date, tot ce trebuie făcut este folosirea butonului din partea de sus, numit „Add a new Patient”. După apăsarea acestuia se va deschide un formular pentru completarea detaliilor referitoare la noul pacient:
Dacă în schimb se dorește actualizarea detaliilor unui pacient, se folosește butonul de editare din dreptul pacientului care se dorește a fi editat, iar interfața va genera un alt formular pentru actualizarea informațiilor. Pe lângă actualizarea informațiilor despre pacient, se va putea și asigna un aparat de tratare a apneei, și se va putea și sterge pacientul din baza de date.
3.3.9 Pagina de adăugare/actualizare a măștilor
Această pagină a website-ului este identică din punct de vedere structural, structura interfeței fiind aceeași. Pagina va permite adăugarea a noi aparate de tratare a tulburărilor apneice dar și actualizarea celor existente deja în baza de date.
3.3.10 Pagina de statistici și grafice
Această pagină este cea mai importantă pentru monitorizarea tratamentului acordat pacienților. Pagina oferă o serie de statistici și grafice pe perioade de timp, bazate pe datele primite de serviciul web de la măștiile folosite de pacienți în fiecare zi.
Pagina este alcătuită din următoarele componente: un antet care oferă detalii despre pacient și oferă posibilitatea de a schimba pacientul, și o pereche de trei tab-uri care vor conține elementele grafice statistice.
Primul tab se referă la ultimele 30 de zile în care aparatul a fost folosit de către pacientul selectat, și regăsim o diagramă radială, un tabel și o axă de timp a ultimelor 30 de zile:
Al doilea tab se referă la toată perioada de utilizare a aparatului pentru pacientul selectat:
Ultimul tab oferă un grafic de tip liniar, care oferă șansa de a selecta doar anumite perioade de timp, pentru monitorizarea detaliată a modului în care este utilizat aparatul.
Concluzii
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 Client Server Pentru Monitorizarea Continua a Tulburarilor Apneice (ID: 150456)
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.
