Adaptació d’un portal de gestió de control d’accés a la incorporació
d’equips connectats
Memòria de Projecte Final de Màster
Màster Universitari en desenvolupament de llocs i aplicacions web
Autor: Gil Prat Pladevall
Professor: César Pablo Córcoles Briongos
Professor col·laborador: Carles Arnal Castelló
07 de Juny de 2021
2
© (Gil Prat Pladevall)
Reservats tots els drets. Està prohibit la reproducció total
o parcial d'aquesta obra per qualsevol mitjà o procediment,
compresos la impressió, la reprografia, el microfilm, el
tractament informàtic o qualsevol altre sistema, així com la
distribució d'exemplars mitjançant lloguer i préstec, sense
l'autorització escrita de l'autor o dels límits que autoritzi la Llei
de Propietat Intel•lectual.
3
Resum
El projecte es basa en la modificació d’un sistema real, anomenat CloudAssistant (de
l’empresa JCM Technologies) la qual permet a instal·ladors de portes de garatge i control
d’accés gestionar les portes de les comunitats que ha instal·lat.
L’aplicació ja porta uns anys funcionant però només amb equips (receptors de porta de
garatge) sense connexió a internet.
El problema principal que s’aborda és la incorporació de receptors de garatge
connectats i l’expansió del sistema no esperada des de que es va fer el primer disseny del
producte, amb afectació directa amb noves funcionalitats que ha de suportar el sistema que no
estaven pensades en primer moment.
L’objectiu del projecte és modificar l’aplicació actual de manera que sense trencar molt
a la línia general de l’empresa pugui incloure de manera fàcil les noves necessitats adquirides
amb l’avanç de la tecnologia i el sector, a més d’estructurar la part de client d’una manera més
correcta per poder fer un punt d’entrada amb testos unitaris.
Paraules clau: Administració, gestió, control d’accés, connectivitat, instal·ladors, emissors,
receptors.
4
Abstract (english version)
The project is based on the modification of a real system, named CloudAssistant (of
JCM Technologies company) which allows garage doors and access control installers to
manage the doors of the communities that has installed.
The application has been running for a few years but only with devices (door receivers)
without internet connection.
The main problem addressed is the incorporation of connected garage receivers and
the unexpected system expansion since the first product design was made, with direct impact
on new features that the system has to bear and that were not intended in the first approach.
The aim of the project is to modify the current application complying with the design
guidelines of the company, including in an easy way the new needs acquired with the
incorporation of new tecnologies in this area, in addition to improve the front end structure to be
able to make the first entry point to unit test.
Keywords: Administration, management, access control, connectivity, installers,
transmitters, receivers.
5
Índex
1. Introducció ................................................................................................................... 10
1.1 Context i justificació .................................................................................................... 10
1.2 Objectius del treball .................................................................................................... 11
1.3 Mètode seguit ............................................................................................................. 11
1.4 Planificació del treball ................................................................................................. 12
2. Definició i punt de partida ............................................................................................ 14
2.1 Punt de partida ........................................................................................................... 14
2.2 Definició del problema ............................................................................................. 18
3. Objectius ...................................................................................................................... 20
3.1 Principals .................................................................................................................... 20
3.2 Secundaris ............................................................................................................... 20
4. Continguts ........................................................................................................................ 21
4.1 Pàgines afegides ........................................................................................................ 21
4.2 Pagines modificades .................................................................................................. 21
4.3 Modificacions generals ............................................................................................... 22
5. Metodologia ...................................................................................................................... 23
6. Arquitectura del sistema ................................................................................................... 24
6.1 Back-end..................................................................................................................... 25
6.2 Front-end .................................................................................................................... 27
6.3 Base de dades ............................................................................................................ 30
7. Plataforma de desenvolupament ..................................................................................... 33
8. Procés de desenvolupament ............................................................................................ 34
8.1 Desenvolupament back-end ....................................................................................... 34
8.2 Desenvolupament front-end ....................................................................................... 38
9. Diagrames ........................................................................................................................ 45
9.1 Arbres de navegació ................................................................................................... 45
9.2 Diagrames de flux ....................................................................................................... 48
10. Prototips ......................................................................................................................... 51
10.1 Hi-Fi .......................................................................................................................... 51
11. Validació d’usabilitat ....................................................................................................... 59
11.1 Criteris de distribució ................................................................................................ 59
11.2 Objectius de la prova ................................................................................................ 59
11.3 Tasques a realitzar ................................................................................................... 59
6
11.4 Resultats ................................................................................................................... 61
12. Canvis en la planificació ................................................................................................. 64
13. Tests funcionals ............................................................................................................. 66
14. Requisits i instruccions d’instal·lació .............................................................................. 67
14.1 Requisits: .................................................................................................................. 67
14.2 Preparació: ............................................................................................................... 67
14.3 Execució: .................................................................................................................. 67
15. Errors .............................................................................................................................. 69
15.1 Memòria dels filtres de les instal·lacions .................................................................. 69
15.2 Connexió Web-Socket .............................................................................................. 69
15.3 Errors de UI/UX ........................................................................................................ 69
16. Projecció a futur ............................................................................................................. 70
16.1 Funcions no implementades..................................................................................... 70
16.2 Millores ..................................................................................................................... 70
16.3 Manteniment futur ..................................................................................................... 71
17. Conclusions .................................................................................................................... 72
Bibliografia ............................................................................................................................ 74
Annex 1. Lliurables del projecte ........................................................................................... 75
Annex 2. Captures de pantalla ............................................................................................. 76
Annex 3. Codi Back-End ...................................................................................................... 80
Controladors nous: ........................................................................................................... 80
Modificacions de controladors existents: .......................................................................... 88
Accés a la base de dades dels nous controladors ........................................................... 89
Modificació d’accés a la base de dades de controladors existents.................................. 89
Servei per accedir a la API externa per consultar els serveis activats d’un dispositiu.... 94
Comunicació amb Web-Sockets ...................................................................................... 94
ServiceBus........................................................................................................................ 95
StartUp .............................................................................................................................. 95
Annex 4. Guia d’usuari ......................................................................................................... 96
7
Índex de figures
Figura 1. Diagrama de Gantt ............................................................................................................... 13
Figura 2. Esquema general de l’aplicació. .......................................................................................... 15
Figura 3. Hardware assistant. ............................................................................................................. 17
Figura 4. Arquitectura global del sistema. ........................................................................................... 24
Figura 5. Esquema de components per el panell i les notificacions. ................................................... 28
Figura 6. Esquema de components per les alarmes i els serveis ....................................................... 29
Figura 7. Esquema de components de l’entitat usuari. ....................................................................... 29
Figura 8. Esquema de dades d’alarmes. ............................................................................................. 30
Figura 9. Taula de notificacions. ......................................................................................................... 31
Figura 10. Esquema nova entitat usuari.............................................................................................. 31
Figura 11. Esquema d’arbre general de l’aplicació. ............................................................................ 32
Figura 12. Visual Studio Community 2019. ......................................................................................... 33
Figura 13. Models de dades de les alarmes. ...................................................................................... 34
Figura 14. Part inicial controlador del panell. ...................................................................................... 35
Figura 15. Estructura de directoris dels context de dades. ................................................................. 36
Figura 16. Exemple d’utilització de Dapper consultant la base de dades. .......................................... 37
Figura 17. Funció per rebre les connexions dels clients per signalR. ................................................. 37
Figura 18. Enviament de missatge a un client concret. ....................................................................... 37
Figura 19. Posició dels elements en el panell. .................................................................................... 39
Figura 20. Redux-sagas. ..................................................................................................................... 42
Figura 21. Arbre de navegació primera pantalla. ................................................................................ 45
Figura 22. Arbre de de navegació del panell. ...................................................................................... 46
Figura 23. Arbre de de navegació de instal·lacions. ........................................................................... 46
Figura 24. Arbre de de navegació de grups d’usuaris. ........................................................................ 47
Figura 25. Arbre de de navegació d’equips o receptors. ..................................................................... 47
Figura 26. Flux de navegació des del panell. ...................................................................................... 48
Figura 27. Flux de notificacions. ......................................................................................................... 49
Figura 28. Flux de creació d’usuaris dins un grup. .............................................................................. 49
Figura 29 . Flux de consulta de serveis activats a l’equip. .................................................................. 50
Figura 30. Pantalla del panell. ............................................................................................................. 51
Figura 31. Visualització de les notificacions. ....................................................................................... 52
Figura 32. Llistat d’instal·lacions. ........................................................................................................ 52
Figura 33. Llistat d’equips d’una instal·lació. ....................................................................................... 53
Figura 34. Detall d’equip. .................................................................................................................... 53
Figura 35. Configuració de paràmetres de l’equip. ............................................................................. 54
Figura 36. Llistat de grups de una instal·lació. .................................................................................... 54
Figura 37. Opció per escollir quin tipus d’usuari es vol donar d’alta. .................................................. 55
Figura 38. Detall d’emissors d’un grup. ............................................................................................... 55
Figura 39. Detall d’usuaris d’aplicació mòbil d’un grup. ...................................................................... 56
Figura 40. Detall d’informació d’un grup. ............................................................................................. 56
Figura 41. Alta d’un usuari d’aplicació mòbil. ...................................................................................... 57
Figura 42. Detall d’emissors assignats a un usuari. ............................................................................ 57
Figura 43. Afegir emissors a un usuari. ............................................................................................... 58
8
Figura 44. Consultar i editar les llicències d’un usuari. ....................................................................... 58
Figura 45. Diagrama de Gantt final. .................................................................................................... 65
Figura 46. Panell principal i notificacions. ........................................................................................... 76
Figura 47. Panell principal i estadístiques. .......................................................................................... 76
Figura 48. Llistat de instal·lacions. ...................................................................................................... 76
Figura 49. Alarmes .............................................................................................................................. 77
Figura 50. Serveis d'un equip. ............................................................................................................. 77
Figura 51. Emissors i alarmes d'un grup. ............................................................................................ 77
Figura 52. Usuaris d'un grup ............................................................................................................... 78
Figura 53. Afegir usuari. ...................................................................................................................... 78
Figura 54. Llistat d'emissors per usuari. .............................................................................................. 78
Figura 55. Afegir emissors a un usuari. ............................................................................................... 79
Figura 56. Veure llicències d'un usuari. .............................................................................................. 79
9
Índex de taules
Taula 1. Planificació. ........................................................................................................................... 13
Taula 2. Rutes al back-end ................................................................................................................. 27
Taula 3. Planificació final. ................................................................................................................... 65
10
1. Introducció
1.1 Context i justificació
Avui en dia la majoria de gestions ja es fan a partir d’internet gràcies a la gran expansió
que ha tingut i l’augment tant de l’ús de l’ordinador com de dispositius mòbils intel·ligents. Molts
sectors han anat passant gestions que abans feien manualment per acabar-les fent amb eines
informàtiques, passant primer per aplicacions d’escriptori en alguns casos fins que al final han
acabat al núvol.
Aquest és el cas de l’empresa en la qual treballo, JCM Technologies S.A. que des de fa ja
molts anys es dedica als sistemes de control d’accés, com emissors per obrir portes de
garatge, receptors per llegir la senyal dels emissors, quadres de maniobra per els motors de les
portes, centraletes de control d’accés fins a elements de seguretat entre d’altres enfocat
principalment a comunitats de veïns.
El negoci de l’empresa es basa en vendre a instal·ladors i distribuïdors que gestionen
moltes portes de garatge de comunitats, amb valors de milions de emissors ( comandaments )
venuts a l’any. Per gestionar tots els números de sèrie d’aquests emissors a les persones
propietàries i al lloc de la instal·lació, els usuaris necessiten una plataforma de gestió de tots
aquests codis. Inicialment s’utilitzava una plataforma de gestió amb format aplicació d’escriptori
de Windows la qual a partir de un port USB i un equip connectat permetia llegir i gravar la
memòria dels dispositius de l’empresa, però les noves tecnologies van forçar l’empresa fa uns
anys a migrar els sistemes dels nostres clients al núvol.
D’aquí va sorgir el projecte CloudAssistant, que bàsicament era la mateixa aplicació
d’escriptori però en format web. Aquesta donava més flexibilitat als usuaris ja que no havien de
tenir un ordinador fixe i una base de dades local, o una base de dades en un servidor de
l’empresa del client, però obliga igualment a tenir un dispositiu connectat per port USB a un
ordinador per poder fer gestions dels productes com gravar una memòria d’un receptor o llegir-
la per exemple, que a partir d’un petit programet d’escriptori i amb un WebSocket obert permet
comunicar la pàgina web amb el dispositiu físic connectat a l’ordinador.
Un dels problemes que tenen els clients és que per a gestionar aquests controls
d’accessos cada cop que es vol modificar algun paràmetre del receptor de porta de garatge o
donar de baixa un usuari, un tècnic s’ha de desplaçar fins a la comunitat i fer les gestions
corresponents. Això comporta una quantitat de temps i diners molt gran per els nostres clients.
L’arribada del internet de les coses (IOT) ha canviat molts productes i moltes empreses i
gracies a aquestes tecnologies s’ha creat receptors de porta de garatge amb connectivitat, que
11
aconsegueixen que es puguin fer totes les gestions sense haver d’anar al lloc físic. Per altre
banda això suposa una oportunitat de negoci per a l’empresa molt gran, ja que amb aquests
nous equips es poden implementar un seguit de serveis de pagament com: estadístiques d’ús,
manteniment predictiu, alarmes, obertures remotes etc...
En aquest projecte afrontem el problema de passar d’una interfície antiga pensada per
a equips sense connectivitat i per clients amb poques instal·lacions, a una interfície més usable
i productiva per els nostres clients, amb la qual es pugui extreure el màxim profit dels serveis
de pagament que vol oferir l’empresa, aprofitant per actualitzar framework utilitzat a la última
per evitar mals funcionaments i forats de seguretat i poder fer un punt d’entrada a tests unitaris.
1.2 Objectius del treball
L’objectiu del treball és desenvolupar millores en el sistema actual i aconseguir que els
usuaris es sentin còmodes en la interfície i navegació de la pàgina així com també incrementar
la productivitat d’aquests sense canviar gaire la línia d’estil actual, ja que un canvi massa gran
farà sentir incomodes als usuaris que porten molt temps treballant amb aquesta interfície. Per
assolir aquest objectiu s’haurà de pensar la pàgina enfocada als nous serveis que es poden
oferir als usuaris a partir de les noves tecnologies (Connectivitat dels productes), per així poder
treure més benefici cobrant un preu més alt per la llicència d’utilització del producte i/o serveis.
Per aconseguir això, es crearà un panell principal on hi haurà informació valuosa per els
usuaris, estadístiques i accessos directes a les pantalles corresponents. S’implementarà un
sistema de notificacions amb temps real per a poder enviar avisos als usuaris, es revisarà la
navegació i la interfície d’usuari de les pantalles principals i es farà un punt d’entrada als tests
unitaris per aconseguir més robustesa a l’aplicació.
1.3 Mètode seguit
El mètode utilitzat per desenvolupar aquest projecte ve definit per el mètode de treball que
utilitza l’empresa propietària de l’aplicació. S’utilitzarà el mètode AGILE SCRUM amb petites
planificacions de 2 setmanes prioritzant els punts més importants per l’empresa. D’aquesta
manera s’aconsegueix que el desenvolupament sigui més flexible a canvis per aconseguir
realment el resultat final que espera el client. S’utilitzarà el software JIRA per entrar les tasques
i controlar els “sprints” i cada dia es tindrà una reunió diària de sincronització amb l’equip, per
així conèixer tots en quin punt estem encara que les modificacions del projecte es
desenvoluparan a part de el desenvolupament continu de l’empresa, per no interferir en els
lliurables que aquest projecte ja té establerts.
12
En l’àmbit del projecte les tasques no s’hauran d’acabar durant les dos setmanes que dura
un “sprint” però si que s’intentarà ajustar al màxim als lliuraments del projecte. En cada “sprint”
es farà una petita planificació del què es farà i una revisió per part de l’empresa
1.4 Planificació del treball
El desenvolupament es separarà en les quatre entregues, PAC1, PAC2, PAC3 i lliurement final.
En la primera entrega es planificarà el treball, es definirà el projecte i es farà una primera
definició de funcionalitats.
En la segona entrega s’estudiarà principalment la usabilitat i la interfície de les noves
pantalles i es revisaran alguns punts de les pantalles actuals, es dissenyarà el prototip i es
començarà a desenvolupar.
En la tercera entrega es desenvoluparà tot el back-end i el front-end principalment i en
l’última entrega s’acabarà de refinar tot el treball, es faran les proves i s’acabarà la
documentació.
Veiem en la taula següent un resum de les tasques a realitzar:
Inici Duració dies Fi
Duració
hores
PAC 1
Definició del projecte 22-feb 5 26-feb 15
Definició del funcionalitats 25-feb 5 01-mar 5
Planificació 27-feb 4 02-mar 10
PAC 2
Diagrames de flux 03-mar 6 08-mar 10
Arbre de navegació 03-mar 6 08-mar 5
Estudi d'usabilitat 08-mar 19 26-mar 20
Estudi d'interfície 16-mar 14 29-mar 10
Disseny del prototip 19-mar 12 30-mar 15
Inici del desenvolupament 25-mar 7 31-mar 15
Documentació 25-mar 7 31-mar 10
PAC 3
Desenvolupament backend 01-abr 15 15-abr 30
Estructures de dades 05-abr 5 09-abr 5
Refactorització del framework 07-abr 11 17-abr 10
Canal de notificacions 07-abr 8 14-abr 10
Desenvolupament frontend noves
pantalles 07-abr 22 28-abr 43
Modificació de la interfície antiga 25-abr 15 09-may 7
Correcció d'errors 01-may 3 03-may 10
Inici revisió responsiu 30-abr 8 07-may 5
Documentació 03-may 5 07-may 20
Entrega final
13
Adaptació a dispositius mòbils 10-may 15 24-may 15
Proves i punt entrada test unitaris 11-may 12 22-may 20
Correcció d'errors 13-may 12 24-may 5
Documentació 15-may 24 07-jun 15
Presentació 28-may 11 07-jun 20
Taula 1. Planificació.
Per completar la planificació s’ha elaborat un diagrama de Gantt amb el qual es pot
observar de manera gràfica la repartició de tasques en el temps i la seva duració:
Figura 1. Diagrama de Gantt
26-feb 18-mar 07-abr 27-abr 17-may 06-jun
Definició del projecteDefinició del funcionalitats
Planificació
Diagrames de fluxArbre de navegació
Estudi d'usabilitatEstudi d'interfície
Disseny del prototipInici del desenvolupament
Documentació
Desenvolupament backendEstructures de dades
Refactorització del frameworkCanal de notificacions
Desenvolupament frontend noves pantallesModificació de la interfície antiga
Correcció d'errorsInici revisió responsive
Documentació
Adaptació a dispositius mòbilsProves i punt entrada test unitaris
Correcció d'errorsDocumentació
Presentació
Diagrama de Gantt
14
2. Definició i punt de partida
2.1 Punt de partida
Per posar una mica més en context el treball s’explicarà breument el que fa principalment
l’empresa que executa el projecte. L’empresa es va fundar ja fa més de 35 anys i es dedica
bàsicament al control d’accés. Amb control d’accés bàsicament ens referim a l’obertura de
portes de garatge i portes peatonals a partir de “FOBS” emissors (“mandos”), targetes de
proximitat etc... i els seus receptors i cuadres de maniobra corresponents. Podeu consultar més
informació de l’empresa a la web: https://www.jcm-tech.com/ca.
Un dels punts forts que diferencia a l’empresa és que fins fa molts pocs anys copiar un
emissor de la nostra empresa era molt difícil, cosa que afavoria molt als nostres distribuïdors i
instal·ladors ja que els usuaris finals no podien anar a al ferreteria a comprar un emissor nou.
També ha set una empresa que sempre ha estat oberta a la personalització dels productes per
a clients grans, per tant alguns dels nostres clients tenen encriptades les memòries dels
receptors i els emissors de tal manera que només ells tenen accés a la lectura i modificació
d’aquesta informació a partir de un hardware especial. Això provoca que els nostres clients els
hi sigui molt difícil marxar de l’empresa ja que tot el que ja tenen instal·lat per moltes
instal·lacions només funciona amb els nostres productes i marxar suposaria canviar milers de
receptors i emissors.
Dit això, ja que els nostres clients volen gestionar les seves instal·lacions i decidir qui entra
i qui no en aquelles instal·lacions i modificar-ho necessitaven un software per gestionar tot això.
D’aquí va sortir un producte anomenat SoftAssistant, que era una aplicació d’escriptori per
Windows que a través de una base de dades SQL Server que s’instal·lava als ordinadors o
servidors del client, aquests podien gestionar les seves instal·lacions. Per gestionar al
hardware, és a dir emissors i memòries de receptors se’ls dona un aparell amb una clau
d’encriptació / desencriptació generada únicament per a ells que es connecta via USB al
ordinador.
Aquest producte va tenir molt èxit però també va portar molts problemes al servei tècnic i al
departament informàtic de l’empresa. Fer que el client es gestioni les bases de dades sempre
és un tema delicat ja que molts d’ells no tenen informàtics a les empreses.
Degut això i a la incrementació d’utilització d’internet i les pàgines web es va decidir passar
el SoftAssistant al núvol, amb una base de dades centralitzada gestionada per JCM ,on cada
client podia accedir a les seves instal·lacions. Aquest projecte es va anomenar CloudAssistant.
Veiem més informació a la pàgina web: https://www.jcm-tech.com/ca/JCM/cloud-assistant-
ca.
El primer pas d’aquest projecte va ser una mica una prova pilot. L’empresa no tenia
experiència en aquest camp i es va anar aprenent a mida que es desenvolupava el projecte. La
15
primera versió de CloudAssistant es va crear amb un back-end amb ASP.NET 4 que també
incloïa el front-end amb Razor, que és un llenguatge que inclou C# i HTML i renderitza les
pàgines en el servidor. Per comunicar amb el Hardware connectat per USB es va utilitzar una
tecnologia anomenada SignalR que bàsicament és un WebSocket amb el qual podíem
comunicar-nos amb un petit programa d’escriptori que únicament feia de pont entre el núvol i el
hardware. El projecte va ser molt lent i quan es va acabar es va veure que tot el que s’havia fet
ja estava obsolet, a més hi havia una tendència a utilitzar pagines web SPA (Single Page
Applications) cosa que no era del tot compatible amb el Razor i es va decidir fer una nova
versió.
Aquesta nova versió es va començar al 2019, i es va seleccionar .NET Core com a back-
end i es va separar totalment el front-end i es va utilitzar REACT per al seu desenvolupament,
que és el punt en el que estem ara actualment.
Funcionalitats actuals:
El software bàsicament permet la gestió de les instal·lacions dels nostres clients,
normalment comunitats de veïns. Per a fer això el software conté varis elements o estructures
de dades que s’explicaran ja que s’utilitzaran molt en aquest projecte.
El sistema bàsicament permet gestionar instal·lacions, grups d’usuaris, equips, relés,
horaris, grups universals i una part d’administració.
Figura 2. Esquema general de l’aplicació.
Instal·lacions:
L’entitat instal·lacions és l’entitat principal, és el lloc on s’ha posat en marxa els productes,
per exemple una comunitat de veïns podria ser una instal·lació, amb el nom adreça i ciutat com
a paràmetres més importants.
16
Equips:
Els equips són els dispositius físics que hi ha en una instal·lació, per exemple en una
comunitat de veïns i podríem trobar un receptor per el garatge i un per la porta peatonal.
Grups d’usuari:
Els grups d’usuaris serveixen per agrupar usuaris, podríem tenir un grup que s’anomenés
escala dreta, un que s’anomenés escala esquerra i un que es digués usuaris garatge
Fobs:
Són els dispositius físics que fan servir els usuaris finals per obrir la porta, generalment són
emissors o targetes de proximitat i sempre estan dins un grup d’usuaris. També existeix un altre
tipus que són les reserves. Les reserves les utilitzen molt els instal·ladors ja que d’aquesta
manera omplen la memòria i ningú més pot donar d’alta usuaris. També serveixen per si algú
perd un emissor, li diu a l’instal·lador i aquest agafa un emissor nou en estoc, fa una substitució
sobre una reserva d’un grup d’usuaris, això el que fa és escriure en el nou emissor que és una
substitució d’aquell codi de reserva que ja esta en la memòria de l’equip i per tant quan l’usuari
vagi a obrir la porta aquesta funcionarà. D’aquesta manera l’instal·lador no s’ha de desplaçar
fins a la instal·lació.
Relés:
Els relés com el seu nom indica són els relés que tenen disponibles els equips, és a dir
sortides. Els equips poden tenir de 1 a 4 relés.
Assignació de relés i grups:
S’ha de poder seleccionar d’alguna manera quins usuaris entraran per cada relé, per això
tenim l’entitat relé-grup, amb la qual es pot seleccionar un grup a quins relés té accés i des de
quin cala (botó de l’emissor o mando)
Horaris:
Els horaris son setmanals, aquest serveixen o bé per donar accés a un grup d’usuaris a un
relé només durant un cert interval de temps, o bé assignant l’horari a el relé directament per fer
accions com per exemple deixar la porta oberta en hores puntes per tots els usuaris
independentment del grup.
Grups universals:
Els grups universals, o grup de tècnics són grups creats fora de les instal·lacions. Els
distribuïdors o instal·ladors donen emissors o targetes de proximitat als seus tècnics i creen
aquests emissors en un grup universal. Llavors assignen aquest grup universal a tants relés de
instal·lacions com vulguin (l’assignació es fa d’igual manera que els grups normals). Així quan
vagin a arreglar una averia o fer un manteniment aquests usuaris tenen accés a la instal·lació.
17
Administració:
L’apartat d’administració serveix perquè cada client es pugui personalitzar la interfície, els
noms dels productes i també gestionar els rols d’usuari per entrar a la web que té en la seva
cadena així com enviar invitacions per a crear nous usuaris si té llicències disponibles.
Accions més comunes:
Les accions utilitzen el hardware que hem dit anteriorment d’encriptació i desencriptació
que es connecta via USB a l’ordinador de l’usuari i a través d’una aplicació d’escriptori i un
WebSocket es comunica amb el nostre sistema. Les accions més comunes amb els dispositius
físics és llegir el codi d’un emissor per entrar-lo a la base de dades, llegir una memòria, escriure
una memòria i substituir un emissor. El client cada cop que crea una instal·lació nova, després
de crear els equips en el sistema i configurar els grups d’usuaris amb els relés i els horaris el
que fan és gravar la targeta de memòria del receptor. Per a crear els “fobs” poden entrar el codi
manualment o llegir-lo amb el hardware connectat per USB, i per fer substitucions es necessita
obligatòriament el hardware connectat per USB.
Per accedir a la pàgina s’ha d’estar convidat per un administrador ja existent en el sistema i que
hagi pagat llicència per utilitzar el software i n’hi quedin de lliures. Un cop s’ha acceptat la
invitació, ja es pot utilitzar el programa amb normalitat.
El sistema es jeràrquic, és a dir un distribuïdor pot generar varis clients per sota seu i tenir
visibilitat sobre les seves instal·lacions sempre i quan els hagi creat ell i així ho hagi escollit.
Per a poder fer accions sobre dispositius com per exemple llegir un emissor o gravar una
memòria, com s’ha comentat abans es necessita un dispositiu físic que s’anomena Assistant
que té l’aspecte següent:
Figura 3. Hardware Assistant.
Es pot observar també en la imatge que porta una memòria de receptor endollada i que hi
ha una àrea de programació / lectura d’emissors i targetes. Per poder utilitzar aquest aparell
18
amb la web, des de la pròpia web, en el menú d’usuari hi ha un enllaç per descarregar
l’aplicació d’escriptori. Un cop descarregada l’aplicació s’ha d’enllaçar l’identificador d’aplicació
amb l’usuari que utilitza el sistema per poder enviar missatges per un canal de WebSocket.
Un cop conegut alt per alt el que hi ha actualment en el sistema, com funciona i quines
són les parts més importants, anem a definir que és farà a partir d’aquí.
2.2 Definició del problema
Com ja s’ha comentat, l’auge de la connectivitat de les coses esta afectant a molts sectors,
les empreses que fabriquen hardware s’han d’anar adaptant cap a un model amb equips
connectats i crear una necessitat de venda enfocada a serveis. Això bàsicament és el que està
passant a l’empresa JCM Technologies, la qual veu que em pocs anys la venda d’emissors, és
a dir la principal font de beneficis es pot veure molt reduïda per les noves tecnologies ja que
encara que avui molts usuaris prefereixin obrir la porta amb un emissor físic, es preveu que en
pocs anys ja ho facin a través d’una aplicació mòbil. Degut això l’empresa s’ha hagut d’anar
innovant i ha creat receptors amb connectivitat, que permeten a més a més d’obertures amb el
mòbil gestió remota dels mateixos.
Això però no es tant maco com sembla. Els nostres clients no volen pagar una mensualitat
per utilitzar una targeta SIM en cada receptor que instal·lin encara que tingui un preu molt baix,
ja que consideren que ara mateix no ho aprofitaran tant com per amortitzar el cost. Mica en
mica a través dels mesos alguns d’ells ja veuen que si que necessiten aquests receptors i que
al final és un benefici per ells ja que s’estalvien molts viatges a les instal·lacions, però creuen
que se’n podria treure més profit d’aquests receptors.
A partir d’aquí ha sorgit aquest projecta. El problema principal és que la interfície actual no
està pensada per equips connectats i tampoc els nostres clients, que ja porten molts anys
acostumats al sistema actual. A més a més per acabar de convèncer als nostres clients s’haurà
d’afegir algun servei addicional que fins ara no tenien i els i pugui ser útil i vulguin pagar per ell.
A continuació es descriurà detalladament els problemes a solucionar de manera que es
defineixin més des de un perfil tècnic.
Funcionament:
Ha de tenir un funcionament molt intuïtiu i que s’ajusti al que ja hi ha ara, ja que ens ha
costat molt passar els usuaris al núvol i ja s’han adaptat a la interfície actual, no els i podem
generar un canvi molt gran d’interfície perquè es perdrien per l’aplicació.
19
Entorn:
El tipus d’usuari que es dirigeix aquesta aplicació són usuaris que es dediquen a la
instal·lació de portes o la distribució d’elements de control d’accés. Aquests usuaris
normalment no tenen una formació sobre noves tecnologies gaire avançades. Solen ser de
entre uns 40 a 50 anys. Tant ho utilitzen homes com dones, ja que al final el que fa la gestió
d’aquestes instal·lacions es fa des de oficina, solen ser persones diferents els que instal·len la
porta i els que gestionen les instal·lacions.
El sistema s’utilitza majoritàriament des de un entorn de treball d’oficina amb una pantalla
d’escriptori.
20
3. Objectius
L’objectiu d’aquest treball és desenvolupar parts d’una aplicació web i fer modificacions
sobre algunes altres parts per aconseguir que el software de control d’accés
CloudAssistant de l’empresa JCM Technologies guany valor amb la incorporació dels
equips connectats i pugui començar a mostrar als nostres usuaris l’enfoc cap a la venda de
serveis en comptes de venda directa de hardware.
Les noves pantalles i funcionalitats de l’aplicació han de ser robusts i proporcionar a l’usuari
una eina fàcil i intuïtiva per a consultar el seu sistema i els seus equips connectats des de
el seu ordinador personal.
3.1 Principals
- Aprendre a gestionar un projecte gran dins l’àmbit laboral professional.
- Desenvolupar un conjunt de modificacions reals que al final del projecte es puguin
posar a producció per els nostres usuaris.
- Ampliar el coneixement obtingut en el màster amb REACT.
- Aconseguir que el software de control d’accés actual tingui un punt d’entrada a tots els
avantatges del IoT com alarmes, notificacions, estadístiques, gestió remota etc...
3.2 Secundaris
- Dissenyar un prototip complert de les modificacions i les pantalles noves amb Adobe
XD.
- Dissenyar una estructura de dades per a les noves entitats del sistema.
- Estudiar i aconseguir una millora d’usabilitat global del sistema.
- Donar un canal estable de comunicació en temps real entre el back-end i el front-end.
- Testejar l’aplicació a nivell funcional per evitar possibles errors.
- Donar un punt d’entrada als tests unitaris per a la llarga acabar tenint totes les
funcionalitats testejades automàticament.
21
4. Continguts
Per a poder desenvolupar el projecte es necessari tenir una idea de quines pantalles es
crearan, quines es modificaran i quines funcionalitats s’afegiran. En aquest apartat es
detallaran tant les pantalles que s’implementaran com les pantalles que es modificaran.
4.1 Pàgines afegides
4.1.1 Panell principal
Aquesta serà la pàgina d’accés a l’aplicació. Des de aquesta pàgina l’usuari podrà
visualitzar estadístiques dels equips connectats, alarmes i comptadors d’equips connectats i
desconnectats entre d’altres coses.
4.1.2 Notificacions
Aquesta serà la part on l’usuari veurà les notificacions que té pendents de visualitzar. Serà
accessible des de totes les pantalles de l’aplicació.
4.1.3 Serveis
Des d’aquest punt l’usuari podrà visualitzar quins serveis té activats un equip, com per
exemple targeta SIM amb baix consum, targeta SIM amb alt consum, detecció de clons etc… i
podrà sol·licitar activar o desactivar serveis que té contractats.
4.1.4 Usuaris aplicació mòbil
Amb aquesta pantalla l’usuari podrà visualitzar un llistat d’usuaris d’aplicació mòbil que
estan dins un grup d’usuaris i per tant tenen accés a l’obertura de la porta d’un equip.
4.1.4 Alta d’usuaris aplicació mòbil
En aquest punt l’usuari podrà afegir a un grup d’usuaris un email, nom, cognom i algun
altre paràmetre de una persona física perquè aquesta des de una aplicació mòbil pugui activar
una obertura d’un receptor.
4.2 Pagines modificades
4.2.1 Llistat d’instal·lacions
Es modificarà aquesta pàgina per afegir un filtre en el llistat més útil i més visible que
l’actual. A més s’afegirà una icona per marcar si aquesta instal·lació té alguna alarma activa.
4.2.2 Llistat d’equips
En aquesta pantalla es redissenyarà l’entitat d’equip en el llistat per aconseguir una
estètica millorada i aconseguir que els usuaris tinguin més clares les accions que poden fer
22
sense entrar al detall de l’equip. a més a més es canviarà la iconografia i s’indicaran les
alarmes.
4.2.3 Llistat de grups
Pel que fa al llistat de grups s’afegiran icones d’accions sense haver d’entrar al detall del
grup, al igual que en les altres entitats del sistema. S’afegirà també una icona per marcar les
alarmes actives.
4.2.4 Detall d’equips
Es modificarà el detall d’equip ja que és un punt on els usuaris es perden una mica i hi ha
molta informació separada en diferents apartats que no tenen molt sentit. A més a més
s’aprofitarà per introduir gràfics d’estadístiques.
4.2.5 Configuració d’equips i relés
Dins el detall d’equip es modificarà també l’estructura de la configuració dels paràmetres i
relés per fer-los més usables i no haver de carregar-los necessàriament cada cop que s’entra al
detall de l’equip.
4.2.5 Detall de grups
Es dividirà el detall de grup en tres apartats diferents en funció del tipus d’equip que
estiguin assignats. Tots els grups contindran com a mínim l’apartat d’informació i usuaris com
els actuals, és a dir fobs. Els grups que estiguin assignats a equips que suportin obertura
remota s’afegirà un apartat de usuaris d’aplicació mòbil.
4.3 Modificacions generals
A totes les pantalles ja creades que es detectin mancances d’usabilitat a partir del test
d’usabilitat es faran les modificacions més importants que no trenquin l’esquema de l’aplicació
però aconsegueixin fer el sistema més usable.
23
5. Metodologia
Per el desenvolupament correcte del projecte s’ha planificat una sèrie de tasques a
realitzar. Amb el mètode AGILE SCRUM amb mini planificacions internes de dos setmanes dins
l’empresa. Això provoca que cada dos setmanes hi pugi haver petits canvis de planificació en
un projecte professional. Tot i això al ser un projecte que combina l’àmbit professional amb
l’acadèmic s’ha intentat aconseguir que aquestes planificacions i definicions del projecte tinguin
el mínim de variacions possibles.
Per a començar el projecte es defineix correctament els requisits que s’han de complir i
desenvolupar per a començar a estudiar com desenvolupar-los i com afecten al projecte actual.
Per a fer això s’han seguit les següents fases:
- Definició dels objectius a complir i la problemàtica que es vol resoldre.
- Definició de les funcionalitats que ha de cobrir el nou lliurable.
- Validació amb el PM (product manager) del projecte.
- Planificació del projecte.
- Disseny de la UI/UX.
- Validació amb el PM del projecte.
- Desenvolupament del codi.
- Tests i validació de les funcionalitats.
- Documentació del projecte.
24
6. Arquitectura del sistema
L’arquitectura de l’aplicació web està formada per una part client SPA en JavaScript la
qual es podrà accedir des de un navegador web, i un servidor RESTful en .NET. La part de
front-end realitzarà peticions HTTP que es respondran en format JSON. Pel que fa a la base de
dades s’utilitzarà SQL server allotjat a AZURE. A part d’aquesta infraestructura ja muntada, hi
ha algun punt més d’importància a conèixer en el Back-End. Veiem primer la figura de
l’arquitectura actual muntada:
Figura 4. Arquitectura global del sistema.
Es pot observar en la figura que el sistema conté varis elements més que un front-end i
una RESTful API. Existeixen varies bases de dades, però les més importants són les de CA
(CloudAsisstant) i la de VTX(Vertex) que és la dels dispositius connectats. El sistema consta de
tres app services allotjats a azure, un per el front-end de CloudAssistant (On es realitzaran les
modificacions), un per el Back-End de CloudAssistant, i un altre per a el back-end d’equips
25
connectats que en aquest projecte no si farà modificacions directament, tots tres amb els seus
espais d’implementació preparats per a producció, desenvolupament i test. A més a més hi ha
creat un IoT hub per el funcionament dels equips connectats i un WebJob que recull alguns
dels missatges dels equips i els redirigeix a un Service bus que reparteix aquests missatges als
back-end corresponent. Un cop els missatges arriben al Back-End, aquest s’encarrega de fer
actualitzacions a la base de dades i si s’escau enviar notificacions a les APP’s de l’empresa
(No mostrades en la figura) a través de firebase, o enviar notificacions al front-end a través del
WebSocket SignalR.
Vista la visió global del sistema entrem en detall de les parts que es faran modificacions.
6.1 Back-end
Per el back-end, com s’ha comentat anteriorment s’utilitzarà el framework .NET Core 3 ja
que és el que hi ha actualment en l’aplicació. Sobre aquest framework s’afegiran les crides a la
API i les noves consultes a la base de dades.
6.1.2 .NET Core 3
.NET Core és la plataforma de desenvolupament de Microsoft més moderna, de codi font
obert, multi plataforma i d’alt rendiment per a tot tipus d’aplicacions. No depèn del coses
específiques de Windows com .NET Framework, per tant es pot utilitzar en altres sistemes
operatius.
- És multiplataforma i ve amb suport per a docker
- Alt rendiment
- Asincronia amb async / await
- Open Source
- Es pot utilitzar amb varis llenguatges, però s’utilitzarà amb C#.
- Inclou un ORM potent, però s’utilitzarà el ORM Dapper ja que te millor rendiment
- S’utilitzarà el patró de desenvolupament CQRS (Command and Query Responsibility
Segregation)
6.1.3 Autentificació
L’autentificació de la plataforma és una part que no es modificarà, però s’ha cregut
convenient explicar-la en aquest apartat. L’autentificació es realitzarà per JWT (Json Web
Tokens), a través d’un servidor d’identitats (IdentityServer4), per a reutilitzar la lògica de
l’autentificació per a altres softwares de l’empresa. En podem trobar més informació en el
següent enllaç:
https://docs.identityserver.io/en/release/intro/big_picture.html
26
6.1.4 Crides a la API
Seguidament es llisten les crides al back-end que s’utilitzen en el treball indicant si són
completament noves o són una modificació d’una crida ja existent.
tipus acció descripció modificació
Panell
GET /api/v4/dashboard Obtenir dades del panell
GET /api/v4/dashboard/filters Obtenir filtres per la cerca del panell
GET /api/v4/dashboard/maintenance
Obtenir comptador d’instal·lacions amb manteniment pendent
GET /api/v4/dashboard/alarms
Obtenir comptador i llistat d’últimes alarmes
GET /api/v4/dashboard/onlinestatus
Obtenir comptador de dispositius connectats i desconnectats
GET /api/v4/dashboard/devices/missconfigured
Obtenir comptador de dispositius desconfigurats
GET /api/v4/statistics/type/{statisticsType} Obtenir estadístiques del panell
Notificacions
GET /api/v4/notifications Obtenir notificacions
POST /api/v4/notifications/clear/{id}
Marcar una notificació com a vista
POST /api/v4/notifications/clear/all
Marcar totes les notificacions com a vistes
Instal·lacions
GET /api/v4/facilities/field/{fieldId} Instal·lacions amb els nous filtres
GET /api/v4/facilities Obtenir instal·lacions X
GET /api/v4/facilities/{facilityId} Obtenir una instal·lació X
GET /api/v4/facilities/byname Obtenir una instal·lació X
Grups
GET /api/v4/facilities/{facilityId}/groups Obtenir grups d'usuaris X
GET /api/v4/facilities/{facilityId}/groups/{groupId} Obtenir grup X
GET /api/v{version}/facilities/{facilityId}/groups/{groupId}/fobs Obtenir emissors d’un grup X
Usuaris d’un grup
GET /api/v4/facilities/{facilityId}/groups/{groupId}/users Obtenir usuaris d'un grup
POST /api/v4/facilities/{facilityId}/groups/{groupId}/user Crear un usuari
DELETE /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userid} Esborrar un usuari
DELETE /api/v4/facilities/{facilityId}/groups/{groupId}/users Esborrar llistat d’usuaris
PUT /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userid} Editar un usuari
POST /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userId}/fob Afegir un emissor a un usuari
GET /api/v{version}/facilities/{facilityId}/groups/{groupId}/users/fobs
Obtenir llistat d’emissors que es poden assignar a un
27
usuari
DELETE /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userId}/fob/{fobid} Treure un emissor a un usuari
GET /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userId}/licenses Obtenir llicències d'un usuari
GET /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userId}/fobs Obtenir emissors d'un usuari
PUT /api/v4/facilities/{facilityId}/groups/{groupId}/users/{userId}/licenses/{licenseid}/lock
Editar llicència d'un usuari
Equips
GET /api/v4/statistics/type/{statisticsType}/equipment/{equipmentId} Obtenir estadístiques d'un equip
GET /api/v4/facilities/{facilityId}/equipments
Obtenir llistat d'equips d'una instal·lació X
GET /api/v4/facilities/{facilityId}/equipments/{equipmentid} Obtenir equip X
GET /api/v4/facilities/{facilityId}/equipments/{equipmentId}/events Obtenir events d'un equip
GET /api/v4/facilities/{facilityId}/equipments/{equipmentId}/sim Obenir serveis activats d'un equip
Grups universals
GET /api/v4/universalgroups Obtenir grups de tècnics X
GET /api/v4/universalgroups/{universalGroupId} Obtenir grup de tècnics X
Alarmes
DELETE /api/v4/alarms/{alarmId} Esborrar una alarma
Autentificació
POST /api/v4/accounts/login Obtenir clau d'accés
POST /api/v4/accounts/RefreshToken/{refreshtoken} Renovar clau d'accés
POST /api/v4/invitations/registeruser Convidar un usuari
PUT /api/v4/invitations/{InvitationId} Usuari accepta una invitació
Taula 2. Rutes al back-end
Totes les crides marcades com a modificades s’han modificat per tal de poder tornar un
array d’alarmes en l’element, és a dir alarmes que afecten a una instal·lació, a un grup, a un
equip o a un emissor.
6.2 Front-end
Pel que respecta al front-end s’ha decidit utilitzar React. S’ha decidit escollir React, ja que
últimament està pujant molt la seva utilització i en el curs no ho hem tocat. Per tant s’ha escollit
aquest per aprendre a utilitzar-lo. A partir de React amb la llibreria Redux farem les crides a la
API i presentarem les dades per pantalla.
6.2.1 React
React és una llibreria de JavaScript focalitzada al desenvolupament de interfícies d’usuari
que va llençar Facebook l’any 2013.
28
- Basada en components.
- Sintaxi JSX .
- Components reutilitzables.
- Gran flexibilitat i rendiment.
- DOM virtual
- Permet isomorfisme.
- Cicles de vida dels components.
6.2.2 Redux
Redux és una eina a patrò per a la gestió d’estats en aplicacions JavaScript nascuda l’any
2015 que es sol associar amb React, però no necessàriament ha de treballar amb aquest. La
gestió d’estat consisteix en assegurar que la UI mostri correctament l’estat de l’aplicació. En
una aplicació moderna has de jugar amb l’asincronisme i la variació de les dades, que amb
aplicacions grans pot portar un gran problema, per fer això Redux conté únicament una font de
dades només de lectura i utilitza funcions pures o Reducers per canviar l’estat
6.2.3 Components React
L’aplicació té més de 130 elements, per tant s’ha considerat no fer un esquema de
components de l’aplicació. Pel que fa a les rutes de l’aplicació també n’hi ha moltes, per tant el
que es farà és un esquema de les parts que ens afecten en les noves pantalles i les
modificacions.
Panell i notificacions:
Figura 5. Esquema de components per el panell i les notificacions.
29
Alarmes i serveis:
Figura 6. Esquema de components per les alarmes i els serveis
Entitat usuari:
Figura 7. Esquema de components de l’entitat usuari.
Els components marcats en verd són els components que s’han realitzat nous, o el
component pare de la part nova realitzada, ja que aquests components poden tenir fills en el
seu interior, els components marcats en taronja (GenericGrow) són els components sobre els
30
quals s’han realitzat modificacions per poder mostrar les alarmes i canviar el disseny en la
pantalla d’equips.
A Partir d’aquests components es començarà a construir l’aplicació i es realitzaran els
“reducers”, les “actions” i les “sagas” per a completar el funcionament e l’aplicació.
6.3 Base de dades
Pel que fa a la base de dades s’ha utilitzat SQL server que s’accedeix des de .NET Core 3
utilitzant Dapper. Com s’ha explicat anteriorment la base de dades estarà a un servidor
d’Azure, propietat de Microsoft.
Pel que respecta a les taules de la base de dades no s’explicaran en profunditat ja que la
base de dades conté més de 50 taules i algunes d’elles amb gran complexitat. S’explicaran
només les taules afegides o modificades.
6.3.1 Alarmes
Relacions entre les taules d’alarmes:
Figura 8. Esquema de dades d’alarmes.
31
6.3.2 Notificacions
Taula de notificacions:
Figura 9. Taula de notificacions.
6.3.3 Entitat usuari
Relacions entre les noves entitats usuaris (Contacts) els grups actuals, les llicències i els
fobs o emissors:
Figura 10. Esquema nova entitat usuari.
6.3.4 Arbre principal de l’aplicació
Relacions de l’arbre principal de l’aplicació, és a dir instal·lacions, grups, equips i fobs
(emissors):
32
Figura 11. Esquema d’arbre general de l’aplicació.
33
7. Plataforma de desenvolupament
El desenvolupament de l’aplicació s’ha realitzat utilitzant el sistema operatiu Windows 10.
S’ha utilitzat SQL server com a motor de base de dades i IIS com servidor web de proves.
S’han controlat les versions a través de Azure Repos els quals utilitzen repositoris de Git
privats. S’ha creat tot el desenvolupament sobre una branca nova anomenada TFM ja que el
ser un projecte real, no s’ha volgut interferir amb les branques actuals i finalment s’ha reintegrat
al “Slot” de dev.
Pel que fa al codi s’ha utilitzat per el front-end l’editor de text Visual Studio Code amb
extensions addicionals per connectar amb Azure Repos, i per el back-end s’ha utilitzat Visual
Studio Community 2019.
Figura 12. Visual Studio Community 2019.
34
8. Procés de desenvolupament
Segons la planificació del projecte, aquest es divideix en dos grans parts que són el
desenvolupament back-end i el desenvolupament front-end.
8.1 Desenvolupament back-end
El back-end, com s’ha comentat anteriorment està creat amb c# utilitzant el framework
NET Core. Al ser un projecte ja en producció el back-end ja està funcionant, per tant en aquest
projecte s’afegeixen endpoints nous a la API RESTful i funcionalitats que es requereixen per les
especificacions de la nova versió de l’aplicació.
8.1.1 Instal·lació de dependències de NET Core
Al Instal·lar visual Studio community s’ha de seleccionar els paquets per desenvolupar amb
NET Core. En aquest cas s’utilitza NET Core 3.1.
8.1.2 Models de dades
S’han creat els models de dades corresponents definits per poder actuar sobre la base de
dades i donar resposta al front-end. Al no utilitzar entity framework ni les migracions
automàtiques de bases de dades que proporciona el framework, les relacions de claus foranes i
altres no cal especificar-les en els models de dades, per tant es converteixen més que res en
DTO (Data Transfer Object). Veiem un exemple dels models o classes creades per les alarmes.
En concret un per fer operacions a la base de dades i un per la resposta de la API.
Figura 13. Models de dades de les alarmes.
35
8.1.3 Controladors
Totes les rutes i controladors d’autentificació ja estaven generats en el projecte. El que
s’ha fet en aquest cas és crear controladors i rutes noves per a poder aplicar les noves
funcionalitats a l’aplicació.
Veiem un exemple del controlador del panell explicat amb detall en la figura 14.
En la capçalera del controlador es declara la ruta principal d’aquest i s’indica que per
accedir-hi la petició ha d’estar autentificada. Es crea la classe DashboardController que
hereta de la classe controller principal.
Seguidament s’instancia la interfície del DashboardDbSet, el qual s’utilitzarà per cridar
les funcions per accedir a la base de dades i retornar la informació.
Es crea un nou endpoint HTTP GET amb la ruta directa, és a dir “/api/v4/dashboard”.
En aquest s’agafa la informació de l’usuari amb una funció que agafa els claims del JWT
token i es crea l’objecte de resposta. Aquest objecte s’omple amb les crides a les funcions
corresponents del dbSet de l dashboard.
Figura 14. Part inicial controlador del panell.
S’ha creat el següents controladors nous:
- DashboardController.cs
- AlarmsController.cs
- NotificationsController.cs
- StatisticsController.cs
36
S’han creat o modificat rutes en els següents controladors:
- FacilitiesController.cs
- FacilityEquipmentsController.cs
- FacilityFobsController.cs
- FacilityGroupsController.cs
- UniversalFobsController.cs
- UniversalGroupsController.cs
Les modificacions que s’han fet bàsicament han estat per incloure en la resposta de les
entitats seleccionades el JSON corresponent d’alarmes en el cas que tingui alarmes actives.
També s’ha modificat i creat algun endpoint per poder resoldre de manera correcta la nova
cerca del panell.
8.1.4 Accés a la base de dades
Per accedir a la base de dades es generen uns repositoris o “dbSets” o contextos de
dades, que amb injecció de dependències s’injecten en els controladors. Des de aquest es pot
cridar una funció del respositori de dades el qual fa una connexió a SQL server i utilitzant
l’ORM Dapper accedeix a les dades i les retorna al controlador.
Figura 15. Estructura de directoris dels context de dades.
Veiem un exemple de la funció “GetMissconfiguredDevices” que es crida des del
controlador del panell. En aquest exemple es pot observar que la tasca ha de retornar un
format de dades de tipus “MissconfiguredDevices”. Seguidament s’obre la connexió a la base
de dades i s’executen les quèries que ens interessen.
37
Figura 16. Exemple d’utilització de Dapper consultant la base de dades.
8.1.5 Comunicació WEB SOCKET
Per poder enviar notificacions de forma directa al front-end s’ha utilitzat un hub
“WebSocket” natiu de Microsoft que és SignalR. S’instal·len les dependències d’aquest i
s’injecta en el start-up del projecte. Per controlar els usuaris connectats veiem en la següent
funció que al realitzar una petició de connexió, s’agafen els paràmetres de identificador del
client (entre d’altres que no afecten a aquest projecte) i es crea un grup o canal de
comunicació amb l’identificador del client i l’identificador de connexió de l’usuari.
Figura 17. Funció per rebre les connexions dels clients per signalR.
Finalment per enviar un missatge s’envia en el canal que es vol, en aquest cas
l’identificador del client de la manera següent:
Figura 18. Enviament de missatge a un client concret.
38
8.1.6 Autentificació
L’autentificació del projecte ja estava creada, funciona per JWT (JSON Web Tokens), que
al iniciar sessió genera un token que s’ha d’injectar a les peticions. Aquest token conté varis
Claims, però només s’utilitza ara per ara la claim “Sub” que conté l’identificador d’usuari.
8.1.7 Documentació de la RESTful API
Al ser un projecte privat d’una empresa la lògica de negoci del Back-End no es pot
compartir. Per tant si es vol provar el funcionament d’aquest es pot utilitzar la documentació
generada automàticament per el Swagger:
https://jcm-api-ca-v4-dev.azurewebsites.net/swagger/index.html
Per accedir a la pàgina demana usuari i contrasenya:
- usuari: Jaca Paca
- contrasenya: C0c0!!
Al ser un projecte privat no es pot adjuntar el codi per a ser compilat. No obstant es troba
en l’annex la referència a tots els fitxers i parts de codi modificats per aconseguir les noves
funcionalitats de l’aplicació.
8.2 Desenvolupament front-end
Un cop acabat el desenvolupament del back-end podem començar a realitzar les noves
pantalles i modificacions planificades en aquest projecte utilitzant la API explicada anteriorment.
Al ser una modificació d’un projecte real tota la part d’instal·lació de React i creació de
l’estructura no s’haurà que realitzar.
8.2.1 Navegació i rutes
Les rutes principals de l’aplicació ja estaven definides. El que es farà en aquest projecte és
modificar la URL principal de l’aplicació “/” per a que carregui el panell en comptes de la llista
d’instal·lacions com feia anteriorment.
Pel que fa a les redireccions que tenim des del panell totes redirigiran al llistat
d’instal·lacions, amb les instal·lacions corresponents que retorna la API en cada crida.
Es carregarà el component de notificacions dins el component “TopNavbar”. Aquest
component es carrega en totes les pantalles ja que forma part del layout de l’aplicació.
S’aprofitaran les rutes ja establertes per Instal·lacions (“Facilities”), equips (“Equipments”) i
grups (“Groups”) per injectar en la resposta d’aquests des del back-end i mostrar per pantalla
les alarmes que afecten a aquests elements.
39
Al polsar la icona de Wi-Fi dels equips amb connectivitat es mostrarà la informació de la
connectivitat d’aquests dispositius i els serveis que tenen assignats, com per exemple:
Contracte de 2G per cinc anys etc...
Per últim es modificarà la URL dels grups d’usuari per afegir les rutes corresponents als
nous apartats, actualment la URL del grup és “/facilities/{facilityName}/Groups/{groupName}”, i
en aquesta ruta es troba tota la informació. Es separarà la informació actual amb les rutes:
- “/facilities/{facilityName}/Groups/{groupName}” (emissors del grup).
- “/facilities/{facilityName}/Groups/{groupName}/info” (informació del grup).
- “/facilities/{facilityName}/Groups/{groupName}/users” (usuaris del grup).
8.2.2 Components
L’aplicació esta formada per un component (Container) principal Root del qual depenen la
resta de components. Seguidament, a part d’alguns components sense rellevància per la
documentació es trobarà el component layout i a partir d’aquí ja es trobaran components com el
MenuNavbar i el Main que és el component principal de l’aplicació i a on es mostraran els
canvis aplicats en aquest projecte.
Panell
Per a visualitzar el panell principal com jas’entrarà per la URL “/” o “dashboard”. En
aquesta ruta es carregarà el component DashboardTemplate a partir del container Dashboard.
Aquest component contè els elements amb distribució CSS grid i components flex. Veiem la
distribució seguida i el seu comportament en diferents mides de pantalla.
Figura 19. Posició dels elements en el panell.
40
Un cop realitzada la maquetació de les tarjetes i el seu posicionament en la pantalla
s’utilitzen varis components o “atoms” extrets de la llibrería privada de JCM per a crear les
tarjetes, els botons, els inputs, les icones i altres elements.
Al carregar la pàgina es faran dos trucades a la API per obtenir les dades del panell. Una
per els comptadors i la informació general del panell i una per a obtenir les estadístiques del
client.
Per a mostrar les estadístiques de client s’utilitza la llibreria de components react de kendo
amb la llicéncia corresponent i s’utilitzen els components Chart, ChartSeries, ChartSeriesItem,
ChartTitle, ChartCategoryAxis i ChartCategoryAxisItem.
Notificacions
Al canviar l’estat d’alguna propietat del layout o al canviar de ruta, es farà una crida a la api
per obtenir el llistat de notificacions per aquell client. Aquest component es visible des de totes
les pàgines de l’aplicació menys les de iniciar sessió. Al polsar la icona de notificacions es
mostrarà el llistat de notificacions pendents i es podrà realitzar les accions de marcar totes com
a llegides, o veure-les individualment, que portarà a la instal·lació responsable de la notificació.
Sempre que es rebi una notificació per WebSocket (SignalR) automàticament el comptador
de la icona de notificacions s’incrementarà i es mostrarà un “toast” o un avís a cantonada
superior dreta de la pantalla.
Alarmes
En aquest cas no s’ha realitzat cap component en sí. El que s’ha fet es modificar els
components de les entitats “Facilities”, “Equipments”, “Groups” i “Fobs” per mostrar una icona
d’alarma en el cas de que la resposta de la API contingui un llistat d’alarmes. Ara per ara les
alarmes només les generen els emissors, però es propaguen fins a l’entitat pare que és la
instal·lació en el qual aquell emissor esta entrat.
En cada entitat filla d’instal·lació es mostrarà el resum de les alarmes i no serà fins a
l’entitat “FOB” o emissor que es podrà clicar a l’alarma per marcar-la com a vista. Al marcar-la
com a vista aquesta desapareixerà de tots els elements anteriors.
La visualització de les alarmes és molt simple, només es mostrarà una icona en la
capçalera de l’element (instal·lació, equip, grup) i en la taula d’emissors. Aquesta icona al
passar per sobre mostrarà un “tooltip” o un títol amb el qual mostrarà més informació del llistat
d’alarmes.
En l’element emissor, les alarmes es mostren dividides per els dos tipus d’alarma actual,
que són emissor clonat i emissor amb bateria baixa. Com s’ha comentat anteriorment al clicar
una de les dos icones disponibles apareixerà un avís de confirmació per marcar l’alarma com a
vista.
41
Serveis
Per a mostrar els serveis únicament s’utilitza el component GsmPopup, el qual després de
clicar la icona de connexió de l’equip, farà una crida a la API per demanar els serveis i la
connexió de l’equip en concret. Un cop obtinguda la resposta s’obrirà per pantalla un “pop up”
amb la informació de connexió, i les dades del contracte i de la targeta SIM si existeixen.
Entitat usuari
Per implementar aquesta nova entitat en l’aplicació s’han creat varis components. Al
carregar un grup d’usuaris anteriorment carregava el component amb tota la informació. Aquest
component IndividualInstallationGroupForm s’ha modificat perquè només mostri el llistat
d’emissors d’un grup, quan anteriorment també mostrava la informació del grup. Al entrar en
aquest component es fa una crida a la API per obtenir els emissors d’aquest grup i mostrar-los
en una taula.
S’han afegit les rutes “/users” i “/info” per a completar les noves funcionalitats. En la ruta
“/info” si accedeix a partir de una pestanya en la capçalera del grup i mostra la informació que
abans es mostrava en el component IndividualInstallationGroupForm en el component
IndividualInstallationInformationForm, que només conté dos inputs de text.
En la ruta “/users”, que s’accedeix a partir d’una pestanya a la capçalera de l’equip,
carregarà el component IndividualInstallationUsersForm que farà una crida a la API per obtenir
els usuaris d’un grup.
Per afegir un usuari s’utilitzarà el component PopUpAddUser, que és un pop up molt
simple amb un formulari que fa un POST a la API.
Per consultar els emissors d’un usuari es farà clic sobre la icona “+” de la taula d’usuaris i
aquesta icona mostrarà el component FobsAndLicensesPopup el qual mostrarà en dos taules
que s’accedeixen a partir de dos pestanyes de navegació, la informació dels emissors
assignats a un usuari i les llicències comprades per aquell usuari des de l’aplicació mòbil.
Des de el mateix component anterior apareixerà un botó per afegir emissors a un usuari,
que al ser polsat farà una trucada a la API per demanar els emissors disponibles en aquell grup
i els mostrarà en el component PopUpAddFobs, el qual serà una taula d’emissors disponibles
amb un “check-box” per a seleccionar-los. Un cop seleccionats apareixerà un botó per afegir
que farà un POST a la API.
Per últim en la pestanya de llicències apareixeran un llistat de llicències comprades per
l’usuari en una taula, la qual tindrà una icona per bloquejar o desbloquejar la llicència fent un
PUT directament a la API.
Per a totes les taules utilitzades s’utilitza el component “data grid” de kendo per tal de
facilitar el desenvolupament.
42
8.2.3 Redux
Tota la informació de l’aplicació retornada per la API es guardarà en l’estat de l’aplicació
utilitzant el patró REDUX. Per aconseguir això s’han generat les accions, els reducers i les
sagas corresponents de cada crida a la API. S’explicarà mínimament els arxius que s’utilitzen i
l’estat en el que es guarda la informació referent als elements creats o modificats.
Figura 20. Redux-sagas.
Les accions es trobaran dins la carpeta “actions”. En aquesta carpeta trobarem les accions
per obtenir i guardar en l’estat totes les trucades a la api realitzades i altres elements que
modifiquen l’estat de l’aplicació.
Els arxius creats o modificats dins la carpeta d’actions són els següents:
- Dashboard.js (panell)
- GroupUsers.js (entitat usuari)
- Notifications.js (notificacions)
- SignalrFront.js (web socket)
- Statistics.js (panell)
- Instalations.js (alarmes)
- Equipments.js (serveis)
-
Les sagas (“effects”) les trobem dins la carpeta “sagas”. Les sagas són les encarregades
de realitzar les trucades a la api accionades per les accions anteriors. Els fitxers de sagas
creats o modificats són els següents:
- Dashboard.js
- Equipments.js
- GroupUsers.js
- Installations.js
- Notifications.js
- Statistics.js
43
Per últim els reducers seran els encarregats de modificar l’estat de l’aplicació. Sense
passar per els reducers no es podrà modificar l’estat de l’aplicació aconseguint així una gran
consistència de dades si s’utilitza bé el patró REDUX. Els reducers es trobaran a la carpeta
“reducers” i els arxius creats o modificats vindrien a ser els mateixos que en els casos anteriors:
- Dashboard.js
- Euquipments.js
- GroupUsers.js
- Instalations.js
- Notifications.js
- SignalrFront.js
- Statistics.js
8.2.4 WebSocket
Per implementar les notificacions push en l’aplicació s’ha utilitzat la llibreria signalR de
Microsoft.
El servei el podem trobar en el fitxer signalrFront.js en la carpeta “comon/utils”. Aquest
servei te les funcions necessàries per obrir una connexió nova tancar una connexió i rebre
missatges. Per obrir una connexió s’utilitza el “customerId” de l’usuari autentificat i l’accés token
per tal d’autenticar la resposta i tenir control de quins usuaris estan connectats al Hub.
Per obrir la connexió s’utilitza la funció createHubConnectionBuilder del fitxer signalrFront
de la carpeta “src/services”.
Un cop es rep un missatge, o es realitza una connexió o un canvi en el signalR es criden
les accions corresponents per guardar en l’estat de l’aplicació l’identificador de connexió de
l’usuari, l’estat de la connexió i al rebre una notificació des del back-end s’actualitza l’estat del
store de les notificacions de tal manera que al rebre una notificació automàticament s’actualitza
el component de les notificacions per a mostrar la notificació acabada de rebre.
8.2.4 APIs utilitzades
El projecte utilitza moltes llibreries i APIs externes, però només es citaran les utilitzades
directament en aquest projecte. Aquestes son:
Kendo React de Telerik:
S’ha utilitzat per les taules i els gràfics principalment, tot i que també s’utilitza en alguns
altres components com pop-up’s, desplegables etc...
React Redux i React Saga:
S’han utilitzat per controlar l’estat de l’aplicació. Ja estaven incorporades en el projecte.
44
Llibreria JCM UIKIT
Llibreria pròpia de l’empresa JCM-Technologies amb àtoms i components petits com
botons, icones, inputs entre d’altres.
i18next
Llibreria utilitzada per globalitzar l’aplicació, és a dir les traduccions dels texts en diferents
idiomes. En aquest cas espanyol i anglès tot i que l’aplicació suporta també francès, italià,
alemany i txec.
45
9. Diagrames
En aquest apartat es definiran els diferents diagrames creats per a poder realitzar el
projecte. Aquests són els arbres de navegació de les parts modificades o noves de l’aplicació i
els diagrames de flux d’aquests. En els diagrames mostrats no es posa molt èmfasi en les parts
de inici de sessió i altres funcionalitats de l’aplicació ja que en aquestes no es farà cap tipus de
modificació.
9.1 Arbres de navegació
L’aplicació té varis tipus d’usuari, alguns amb funcionalitats complertes i alguns amb
funcionalitats parcials. No obstant les parts modificades de l’aplicació no es veuen afectades
per els rols d’usuari. Les parts noves o modificades es marquen amb una caixa amb negreta.
S’ha dividit l’arbre de navegació en cinc diagrames per a fer-lo més fàcil d’entendre. El
primer diagrama mostra la primera pantalla després d’iniciar sessió o el “layout” de l’aplicació.
Des de totes les pantalles es podrà accedir a les pantalles mostrades en aquest diagrama.
Figura 21. Arbre de navegació primera pantalla.
46
Dins de la pantalla del panell es carregaran en blocs les parts que es veuen a continuació, al
fer clic sobre els elements que ho permetin es redirigirà a la pantalla d’instal·lacions filtrada en
funció de l’ítem que s’ha seleccionat.
Figura 22. Arbre de de navegació del panell.
Al fer clic sobre instal·lacions redirigirà al llistat d’instal·lacions des de on es podrà afegir,
clonar i eliminar una instal·lació. Al fer clic sobre una instal·lació aquesta es desplega i es podrà
accedir a informació, dispositius i grups d’usuaris. Aquesta part no s’ha modificat, simplement
s’exposa per a poder entendre millor el funcionament de tot el sistema.
Figura 23. Arbre de de navegació de instal·lacions.
47
Dins una instal·lació al fer clic sobre els grups es desplegarà el llistat de grups. En aquest
es podrà crear i eliminar grups. Al fer clic sobre un grup aquest es desplega i es podrà accedir
a la pantalla d’emissors, usuaris de la APP mòbil, afegir emissors, afegir usuaris i configurar un
grup.
Figura 24. Arbre de de navegació de grups d’usuaris.
Al fer clic sobre equips dins una instal·lació es mostrarà el llistat d’equips o receptors, els
quals des de aquí es podran crear eliminar i clonar. Al fer clic sobre un equip aquest es
desplega i es podrà accedir a varies seccions de l’equip.
Figura 25. Arbre de de navegació d’equips o receptors.
48
9.2 Diagrames de flux
En aquest punt es definiran els fluxos de navegació que seguiran els usuaris per poder
realitzar les accions noves que s’incorporen en aquesta versió.
9.2.1 Fluxos des del panell principal
Des de la pantalla principal, un cop fet el login correcte l’usuari visualitzarà un panell amb
tot d’informació com estadístiques, alarmes actives, equips on-line, equips des actualitzats
connectats, equips des actualitzats desconnectats, instal·lacions amb manteniment pendent,
cerca avançada i accions ràpides. Al fer la cerca avançada si els camps són correctes es
mostraran les instal·lacions filtrades correctament. En els altres casos, la majoria d’accions
porten a instal·lacions filtrades en funció de l’ítem seleccionat. En el cas de les estadístiques
només es mostra un pop up amb les estadístiques ampliades. En el cas de les alarmes es
mostra un pop-up amb el resum d’alarmes i si es clica veure més redirigirà a la pantalla
d’instal·lacions i sortiran només les que tingui alarmes actives.
Figura 26. Flux de navegació des del panell.
9.2.2 Flux de notificacions
De cara al flux de notificacions, aquestes poden arribar per dos camins. Quan l’usuari entre
a la pàgina després de fer login es farà una crida a la API per demanar si aquest usuari té
notificacions pendents. Per altre banda al fer login també s’obrirà un canal per WebSocket per
a que el back-end pugui enviar notificacions en temps real al front-end.
49
Figura 27. Flux de notificacions.
9.2.3 Flux de grup d’usuaris.
Figura 28. Flux de creació d’usuaris dins un grup.
50
9.2.4 Flux de consulta de serveis activats de l’equip.
Figura 29 . Flux de consulta de serveis activats a l’equip.
51
10. Prototips
El prototipat es una etapa molt important del desenvolupament de totes les aplicacions
web. D’aquesta manera ajuda a entendre com serà l’aplicació. En el nostre cas al ja tenir uns
colors i estructures definits per l’aplicació actual que no es poden trencar, s’ha decidit passar
directament a un prototip de més alta definició de les pantalles que s’afegiran o es modificaran.
Aquestes pantalles són la del “panell”, “notificacions”, “instal·lacions”, “llistat equips / receptors”,
“llistat de grups dins una instal·lació”, “detall d’equip”, “configuració paràmetres d’equip”, “detall
de grup - emissors”, “detall de grup – usuaris d’aplicació mòbil”, “detall de grup – informació”,
“alta d’usuaris d’aplicació mòbil”.
El desenvolupament del prototip s’ha realitzat amb Adobe XD. La idea inicial del prototip
era també incloure les pantalles per a dispositius mòbils i tauletes, però per decisió d’empresa i
com els usuaris utilitzen la nostra aplicació (sempre necessiten un port sèrie amb un programa
d’escriptori de windows) s’ha decidit no invertir recursos en aquesta part ara per ara. Per tant
només es farà el prototipat amb versió d’escriptori deixant l’aplicació del mínim producte viable
per els dispositius petits a lliure elecció del programador.
L’aplicació sempre te un header estàtic a dalt la pàgina en el qual conté les notificacions el
menú d’usuari, l’ajuda i la cerca global. Al costat esquerra i haurà el menú principal per accedir
a les 5 pantalles principals del sistema.
10.1 Hi-Fi
Figura 30. Pantalla del panell.
52
Figura 31. Visualització de les notificacions.
Figura 32. Llistat d’instal·lacions.
53
Figura 33. Llistat d’equips d’una instal·lació.
Figura 34. Detall d’equip.
54
Figura 35. Configuració de paràmetres de l’equip.
Figura 36. Llistat de grups de una instal·lació.
55
Figura 37. Opció per escollir quin tipus d’usuari es vol donar d’alta.
Figura 38. Detall d’emissors d’un grup.
56
Figura 39. Detall d’usuaris d’aplicació mòbil d’un grup.
Figura 40. Detall d’informació d’un grup.
57
Figura 41. Alta d’un usuari d’aplicació mòbil.
Figura 42. Detall d’emissors assignats a un usuari.
58
Figura 43. Afegir emissors a un usuari.
Figura 44. Consultar i editar les llicències d’un usuari.
59
11. Validació d’usabilitat
Pel que fa a la usabilitat del sistema, com que és un sistema ja en producció el qual
estan utilitzant els clients i amb unes regles d’usabilitat establertes, l’únic que s’ha fet ha estat
realitzar un test real d’usabilitat observant usuaris amb un perfil similar que realitzessin varies
tasques que solen ser comunes per l’usuari final, per així poder veure com els usuaris utilitzen
el sistema i si es prou usable per ells.
11.1 Criteris de distribució
La prova s’ha realitzat a un grup reduït de tres usuaris “target” que compleixen els requisits
per a realitzar aquest test. Al ser un sistema complex que requereix un mínim de coneixement
de productes de l’empresa i del funcionament del sistema s’ha escollit 3 persones que coneixen
el software però que l’han utilitzat molt poc, s’han descartat tots els possibles usuaris que han
treballat molt amb la pàgina com els propis desenvolupadors o “product managers”. Aquests
usuaris tenen un rang d’edat d’entre 45 i 55 anys, com la majoria dels instal·ladors de porta o
distribuïdors que utilitzen aquest software. S’han seleccionat expressament els usuaris amb
coneixements diferents, en aquest cas un comercial, un enginyer i el responsable d’atenció al
client.
11.2 Objectius de la prova
Els objectius de la prova són estudiar i validar si la interfície actual és prou usable en el dia
a dia dels nostres usuaris. S’ha posat especial èmfasi en intentar reproduir les accions que fan
els nostres clients de manera més freqüent i amb unes condicions reals, com per exemple
utilitzar un compte amb moltes instal·lacions, ja que d’altre manera no ho podríem reproduir
correctament. S’ha intentat veure com els usuaris busquen les coses que volen, quin tipus de
cerca fan i com naveguen entre pantalles, com tornen enrere i si saben localitzar les coses que
se’ls demana amb facilitat.
11.3 Tasques a realitzar
Tasca 1: Crear una instal·lació amb un nom concret i els altres paràmetres al gust, crear
dos equips de tipus diferent un connectat i l’altre no, però només amb un relé activat. Un cop fet
això crear 2 grups amb assignacions un al relé 1 d’algun dels equips i l’altre grup al relé 2 d’un
dels equips.
Objectiu de la tasca: Validar com creen els ítems més comuns dins el software i els
relacionen entre ells.
60
Tasca 2: Tornar a la pantalla d’inici i a partir d’aquí afegir 30 emissors (“mandos”) aleatoris
i el codi 89354 amb dispositiu GO-PRO4 a un grup i 300 reserves a un altre grup.
Objectiu de la tasca: Observar com des de la pantalla d’inici cerquen la instal·lació creada
anteriorment i com afegeixen emissors i naveguen per les pantalles.
Tasca 3: Crear un grup universal ( grup de tècnics) amb nom “Universal grup test UX”,
crear 10 codis seqüencials en aquest grup i assignar-lo a la instal·lació creada anteriorment.
Objectiu de la tasca: Veure com entenen els grups universals i els relacionen amb els
altres components.
Tasca 4: Crear un horari i assignar-lo a un relé (per tots els grups) de la configuració de
l’equip amb connectivitat creat anteriorment per aconseguir que la porta es quedi sempre
oberta en l’interval de temps seleccionat.
Objectiu de la tasca: Observar com relacionen els horaris amb els relés dels equips amb
connectivitat.
Tasca 5: Assignar l’horari creat anteriorment a només un relé de un grup en concret de la
configuració perquè els usuaris del grup només puguin entrar en aquelles franges horàries.
Objectiu de la tasca: Veure si els usuaris saben diferenciar que hi ha dos tipus de
funcionaments d’horaris diferents.
Tasca 6: Tornar a l’inici i modificar la configuració d’assignacions de grups a relés i canals
de qualsevol dels grups.
Objectiu de la tasca: Fer una navegació completa fins arribar a modificar les assignacions
dels grups d’usuaris a els equips.
Tasca 7: Tornar a la pantalla d’inici i cercar el codi 89354 creat anteriorment i fes-li una
substitució.
Objectiu de la tasca: Observar com cerquen un codi i troben l’acció de substitució
Tasca 8: Esborrar 3 codis aleatoris d’un dels grups de la instal·lació creada anteriorment.
Objectiu de la tasca: Observar com eliminen els codis, si utilitzant la icona o la selecció i el
botó d’esborrar
61
Tasca 9: Tornar a l’inici i grava la memòria (encara que no la tinguis físicament) d’alguns
dels equips de la instal·lació creada anteriorment.
Objectiu de la tasca: Veure si els usuaris saben trobar aquesta acció, que és de les més
importants de totes
Tasca 10: Assigna el grup universal ja existent “Universal tecnicos” a tots els equips de la
instal·lació creada anteriorment.
Objectiu de la tasca: Veure com relacionen un grup ja existent a una instal·lació.
Tasca 11: Fes veure que compares la memòria de sense connectivitat creat anteriorment.
Objectiu de la tasca: Veure si els usuaris saben trobar aquesta acció.
Tasca 12: Fes veure que esborris la memòria de l’equip sense connectivitat creat
anteriorment.
Objectiu de la tasca: Veure si els usuaris saben trobar aquesta acció.
Tasca 13: Prohibeix la programació manual per ràdio de l’equip sense connectivitat creat
anteriorment.
Objectiu de la tasca: Observar com naveguen els usuaris fins als paràmetres de
configuració d’un equip
Tasca 14: Canvia la configuració d’un dels relés de l’equip amb connectivitat creat
anteriorment a la instal·lació per a que funcioni amb mode normalment tancat.
Objectiu de la tasca: Validar que els usuaris sàpiguen distingir entre els paràmetres de
l’equip de la configuració dels relés.
11.4 Resultats
Els resultats de la prova han set satisfactoris, s’ha pogut trobar varis punts a millorar en la
usabilitat del producte i s’ha pogut estudiar com els usuaris utilitzaven la interfície.
62
S’ha comprovat que els usuaris al veure un botó de “volver”, ja no utilitzen el “breadcrumb”
per a tornar enrere i moure’s per l’aplicació, també en les pantalles que aquest botó no hi era
s’han vist una mica perduts i han estat obligats a utilitzar el “breadcrumb”.
En algunes pantalles, en concret en la de relés hi ha dos botons de guardar i això fa dubtar
als usuaris.
Quan han de buscar un ítem concret no saben ven bé com fer-ho, hi ha una cerca global
en el layout de l’aplicació que a vegades volen fer servir de filtre en algunes llistes. Alguns
desplegables contenen molts elements i és molt difícil trobar el que busques.
Hi ha pantalles que la iconografia fa un tipus d’acció que l’usuari té associat amb una altre
acció del programa, com per exemple executar el netejar una memòria té la mateixa icona que
configurar un grup.
Encara que l’equip tingui accions ràpides en l’element abans de desplegar-lo els usuaris
sempre el despleguen per executar una acció.
El tema de tenir dos tipus d’assignacions d’horaris (per relé independentment dels usuaris)
i per grup d’usuari fa que els usuaris es perdin.
La configuració de l’equip i la configuració dels relés és un concepte que provoca confusió,
a vegades busquen les coses als llocs que no toca.
En la pantalla d’usuaris d’un grup i ha la icona per esborrar un emissor i un checkbox per
seleccionar els emissors i després poder fer accions. Al voler-ne esborrar tres primer els
seleccionen i llavors no saben si polses les icones de esborrar de cada element o la general.
Després de fer una cerca global, depenent de si tornes a l’inici per el “breadcrumb” o per el
menú principal queda guardada la cerca anterior la cercador i l’usuari es perd.
La majoria de llistes d’elements generals (horaris, equips, grups, instal·lacions, equips) es
despleguen com un acordió, però hi ha algun punt com en la configuració d’una instal·lació a un
grup universal que l’element és igual que els altres comentats anteriorment però aquest no es
desplega, sinó que hi ha una icona de configuració.
El tema dels grups universals confon els usuaris ja que hi ha varis camins per arribar al
mateix lloc i des de alguns dels camins no s’indica del tot l’acció que farà l’usuari, per tant
considero que en aquest punt i en el punt de l’assignació d’horaris a instal·lacions és el punt
més feble del programa. També considero que un altre punt urgent per resoldre és el tema de
63
filtres en les llistes, ja que els clients amb moltes instal·lacions, usuaris i grups no els hi és fàcil
trobar el que busquen en cada moment.
64
12. Canvis en la planificació
Al ser un projecte en funcionament era d’esperar trobar problemes en la definició i en
l’execució del projecte. En aquest cas, al ser un gran canvi per l’empresa a nivell de model de
negoci, ja que s’està passant de vendre equips a vendre serveis, els responsables de producte
i de model de negoci de l’empresa han amb molta cura i indecisions, cosa que ha provocat un
endarreriment en la definició del projecte i canvis en les definicions que com a resposta han
provocat un endarreriment de la planificació. Al tenir aquest desplaçament en la planificació el
temps de desenvolupament o de programació de l’aplicació s’han vist molt reduïts i no s’han
pogut assolir tots els objectius esperats.
Els punts més crítics que han afectat en la definició del projecte han estat la monetització
de les llicències venudes als usuaris i com els instal·ladors de portes de garatge gestionaven
aquestes llicències i usuaris. Aquest punt ha afectat a la UI del sistema i sobretot al back-end,
ja que els canvis en aquest punt han obligat a redissenyar una mica com els instal·ladors
gestionaven els usuaris assignats a un grup des de l’aplicació i com el Back-End gestionava
aquests usuaris i llicències a la base de dades. Fins que no s’han tingut aquests punts clars no
s’ha pogut acabar la definició de la UI i prototips de l’aplicació ni el desenvolupament del Back-
End, cosa que com es veu en la següent taula, ha endarrerit principalment l’estudi d’interfície i
el disseny final dels prototips, amb la qual cosa tots els altres punts següents s’han vist
afectats.
Inici Duració dies Fi Fi planificació inicial
Definició del projecte 22-feb 5 26-feb 26-feb
Definició del funcionalitats 25-feb 5 01-mar 01-mar
Planificació 27-feb 4 02-mar 02-mar
Diagrames de flux 03-mar 6 08-mar 08-mar
Arbre de navegació 03-mar 6 08-mar 08-mar
Estudi d'usabilitat 08-mar 19 26-mar 26-mar
Estudi d'interfície 16-mar 26 10-abr 29-mar
Disseny del prototip 19-mar 40 20-abr 30-mar
Inici del desenvolupament 25-mar 7 31-mar 31-mar
Documentació 25-mar 7 31-mar 31-mar
Desenvolupament backend 10-abr 20 30-abr 15-abr
Estructures de dades 15-abr 5 20-abr 09-abr
Refactorització del framework
Canal de notificacions 30-abr 8 14-abr 14-abr
Desenvolupament frontend noves pantalles 30-abr 15 14-may 28-abr
Modificació de la interfície antiga 07-may 10 17-may 09-may
Correcció d'errors 18-may 3 21-may 03-may
Inici revisió responsive
65
Documentació 01-may 6 07-may 07-may
Adaptació a dispositius mòbils 20-may 7 27-may 24-may
Proves funcionals 20-may 5 24-may 22-may
Correcció d'errors 20-may 5 24-may 24-may
Documentació 15-may 24 07-jun 07-jun
Presentació 28-may 11 07-jun 07-jun
Taula 3. Planificació final.
Figura 45. Diagrama de Gantt final.
26-feb 18-mar 07-abr 27-abr 17-may 06-jun
Definició del projecte
Planificació
Diagrames de flux
Estudi d'usabilitat
Disseny del prototip
Documentació
Desenvolupament backend
Refactorització del framework
Desenvolupament frontend noves pantalles
Correcció d'errors
Documentació
Adaptació a dispositius mòbils
Correcció d'errors
Presentació
Diagrama de Gantt
66
13. Tests funcionals
Durant tot el desenvolupament s’han realitzat tests funcionals tant del codi del servidor com
de la part de client.
Pel que fa al servidor, s’ha comprovat que el back-end resolgués bé les noves rutes
creades per a les modificacions de l’aplicació, s’ha comprovat el funcionament de les crides
amb la mateixa interfície de la API amb Swagger. S’ha comprovat la recepció de missatges
d’alarmes al Service Bus per a posteriorment poder enviar notificacions via SignalR. Tots
aquests casos d’ús han estat satisfactoris.
Pel que fa a la part de client, s’ha comprovat el funcionament i l’aspecte de tots els
components creats i modificats per tal d’assegurar el resultat esperat. S’ha posat especial
èmfasi en validar el funcionament de la recepció de missatges en temps real a partir de
SignalR. Per a fer això s’han injectat missatges simulats al Service Bus que han estat tractats
com a alarmes i s’han enviat com a notificació a l’aplicació.
La part de client només s’ha testejat amb Google Chrome ja que és l’únic navegador amb
el qual és obligatori que funcioni l’aplicació com a directiva d’empresa.
Per últim s’ha testejat l’adaptació de les pantalles noves a dispositius petits.
67
14. Requisits i instruccions d’instal·lació
14.1 Requisits:
És necessari tenir instal·lat NodeJs a la versió 14.16.1 o superior. S’ha provat amb
versions superiors i funciona, tot i així la versió de NodeJs amb la que s’ha desenvolupat és la
14.16.1. També cal tenir instal·lat NPM a la versió 5.5.1 o superior.
- NPM: https://www.npmjs.com/get-npm
- NodeJs: https://nodejs.org/en/download/
Pel que fa al back-end no s’entrega una versió per a compilar en local, ja que és propietat
de l’empresa on s’ha realitzat el projecte. La API està hostejada a la següent URL:
https://jcm-api-ca-v4-dev.azurewebsites.net/swagger/index.html
Per accedir a la pàgina demana usuari i contrasenya. Aquestes temporalment per accedir a
la documentació de la API són les següents:
Usuari: Jaca Paca
Contrasenya: C0c0!!
14.2 Preparació:
En la carpeta CloudassistantV4_app s’han d’executar les següents comandes per instal·lar
les dependències del projecte REACT.
- npm install
El projecte depèn d’una llibreria de components privada de NPM creada per JCM-
Technologies. Per tant, al no poder donar un usuari i contrasenya per accedir a aquesta
llibreria privada en el directori principal del projecte hi ha un arxiu .npmrc amb un token
d’autentificació només de lectura per a poder descarregar els paquets requerits.
14.3 Execució:
Un cop es tinguin totes les dependències instal·lades es pot engegar el front-end amb la
seguent comanda:
- npm start
Aquesta comanda aixecarà a la URL “localhost:3000” l’aplicació del projecte. Per a poder
realitzar les proves es necessita un compte d’usuari ja creat, ja que el sistema no deixa
68
registrar usuaris nous, aquest han d’estar convidats per a poder entrar al sistema. Per tant per
realitzar les proves s’utilitzarà el següent usuari:
Usuari: [email protected]
Contrasenya: [email protected]
Si es vol utilitzar la versió publicada es pot trobar a la url:
https://jcm-web-ca-v4-dev.azurewebsites.net/login
69
15. Errors
15.1 Memòria dels filtres de les instal·lacions
S’ha detectat que les pastilles dels filtres aplicats en les instal·lacions al seleccionar un
element del panell es queden sempre activades fins que l’usuari no les elimina manualment.
Això en alguns casos pot portar un punt de confusió.
15.2 Connexió Web-Socket
L’aplicació es connecta a dos Hub’s per SignalR. Un autentificat i un sense autentificació.
El sense autentificació no ens afecta en les modificacions d’aquest projecte. El servei afegit per
a rebre notificacions amb el Hub autentificat, en la primera connexió amb el paràmetre
acces_token ens retorna un error 401 de no autoritzat, però a partir d’aquí ell sol es connecta i
funciona perfectament.
15.3 Errors de UI/UX
S’han detectat alguns errors en la UI provocats en aquest entregable. El component que
s’utilitza com a botó per afegir alguns elements amb un símbol “+” en el seu interior s’ha vist
desplaçat.
El format de la data en les estadístiques del panell no respecte el format de data
seleccionat en les preferències d’usuari.
El pop-up de serveis o informació de la targeta SIM no està del tot ben maquetat. En
pantalles grans es veu be, però en pantalles petites alguns elements es sobreposen
70
16. Projecció a futur
16.1 Funcions no implementades
En la planificació inicial es van definir funcionalitats i millores en el codi final que no s’han
pogut assolir. En la continuació del projecte s’intentarà incloure les següents funcionalitats o
millores definides prèviament.
- Tests unitaris.
- Actualitzar el framework per evitar elements obsolets.
- Ampliació de les estadístiques en el panell.
- Actualitzar les llibreries de tercers utilitzades per evitar elements obsolets.
- Aplicar el redisseny pertinent als components dels equips.
- Aplicar el redisseny pertinent als components de la configuració dels relés i
paràmetres d’un equip.
- Aplicar el redisseny pertinent als filtres de les instal·lacions.
- Aplicar les millores detectades en el test d’usabilitat.
- Afegir la UI per les estadístiques dels equips, aprofitant el component del panell i
les crides API ja creades.
16.2 Millores
Les millores i funcionalitats addicionals vindran donades per el client i per el responsable
del projecte. No obstant es detecten algunes millores a aplicar a l’aplicació per fer-la més
usable.
- Millorar l’adaptació de l’aplicació a diferents mides de pantalla, sobretot per a
tauletes ja que els instal·ladors solen utilitzar-les al anar a les instal·lacions.
- Aprofitar l’entitat usuari creada en aquest projecte i afegir un ítem al menú principal
d’usuaris, amb el qual podràs cercar un usuari i veure a totes les portes que pot
entrar.
- Afegir estadístiques de negoci, que aporten molt valor als nostres clients. Aquestes
podrien ser per exemple, estadístiques d’emissors venuts amb períodes de temps,
estadístiques d’instal·lacions realitzades, estadístiques d’equips més utilitzats
etc…En definitiva, valors que els clients puguin transformar en diners.
- Afegir Horaris anuals, ara mateix l’aplicació només suporta horaris setmanals.
- Lligar directament les instal·lacions amb un mapa.
- Xat directa al servei d’assistència tècnica de JCM-Technologies per poder resoldre
problemes amb temps real.
- Poder compartir / traspassar instal·lacions d’un client a un altre.
71
16.3 Manteniment futur
S’ha de replantejar el futur de l’aplicació front-end, ja que actualment ha passat per moltes
mans i el codi no es gens fàcil d’entendre. A més a més moltes de les llibreries utilitzades estan
obsoletes i al actualitzar-les deixen de funcionar moltes coses, per tant cal replantejar si val la
pena seguir fent créixer aquesta aplicació o en el següent canvi important començar-la de zero
amb una arquitectura més neta i definida.
72
17. Conclusions
L’objectiu principal d’aquest treball ha estat desenvolupar l’adaptació del portal de gestió de
control d’accés CloudAssistant, en el qual ja porto molts anys treballant, a l’arribada dels equips
connectats de control d’accés al nostre mercat.
El motiu per el qual s’ha seleccionat aquest projecte ha estat principalment que és un projecte
amb el qual he estat treballant varis anys desenvolupant back-end principalment i ja feia temps
que el projecte requeria petites modificacions per assolir notificacions en temps real i
estadístiques entre altres, per a poder donar més valor al producte de cara als nostres clients.
En el moment que s’havia de plantejar el treball es va donar la casualitat que en l’empresa
començava un projecte de desenvolupament de hardware nou amb connectivitat amb el qual
es té moltes esperances de futur i es va pensar que seria un bon moment per fer modificacions
en la part de client.
Ha estat el meu primer projecte real amb React i estic molt satisfet amb els coneixements
obtinguts sobre aquest framework, ja que els podré aplicar directament al meu dia a dia a
l’empresa i espero poder seguir-los aprofundint.
Un dels punts importants vist en el desenvolupament del projecte, és que al ser un aplicació de
gran magnitud que ha passat per moltes mans, el codi en moltes parts del projecte és molt
diferent i no esta documentat, cosa que dificulta el desenvolupament quan agafa el projecte
una persona nova. També s’ha comés un error important en els dos anys que porta aquesta
versió del projecte amb React que és que no s’han actualitzat les llibreries utilitzades, ni tant
sols les versions de React. Això provoca que ara mateix el projecte conté moltes llibreries
obsoletes sense suport, que al intentar-les actualitzar a la última versió trenquen moltes parts
del codi, i arribarà un dia que tot això s’haurà de refer de nou.
Pel que fa a la gestió del projecte, ja havia portat algun projecte treballant amb la metodologia
AGILE-SCRUM de magnitud més petita i enfocat a aplicacions mòbil, per tant en aquest camp
ja tenia l’avantatge de l’experiència dels projectes anteriors. Tot i així al ser un projecte d’una
empresa privada, la presa de decisions a vegades no es tant ràpida i tant precisa com
agradaria als desenvolupadors o als responsables del projecte, cosa que en aquest cas s’ha
vist reflectit en el retard en la planificació del projecte. En projectes reals sempre ens trobarem
retards i imprevistos i lo important és aprendre a fer planificacions realistes en les quals es
tinguin en compte aquests possibles imprevistos i poder-los gestionar correctament quan
arriben.
Tot i que no s’han complert tots els punts que es volien treballar, com per exemple no s’ha
pogut aplicar les millores d’usabilitat, el redisseny d’algunes parts i els tests unitaris estic molt
73
satisfet amb el resultat obtingut al final del projecte i l’aplicació dels coneixements que s’han
obtingut en el màster.
De cara al futur, el CloudAssistant és un dels projectes més importants de l’empresa JCM-
Technologies, per tant aquest projecte anirà avançant dia a dia per arribar a aconseguir més
aviat que tard la millor aplicació de control d’accés del mercat.
74
Bibliografia
Esteban H. Understanding redux-saga: From action creators to sagas. (12 d’octubre de 2017),
https://blog.logrocket.com/understanding-redux-saga-from-action-creators-to-
sagas-2587298b5e71/
KendoReact Charts Overvier. (s.d.). https://www.telerik.com/kendo-react-
ui/components/charts/
KendoReact Data Grid (Table) Overview. (s.d.). https://www.telerik.com/kendo-react-
ui/components/grid/
Brock A. & Dominick B. (s.d.). The Big Picture.
https://docs.identityserver.io/en/release/intro/big_picture.html
Patrick F. (6 d’octubre de 2018). Introduction to SignalR. https://docs.microsoft.com/en-
us/aspnet/signalr/overview/getting-started/introduction-to-signalr
Npmrc. (s.d.). https://docs.npmjs.com/cli/v7/configuring-npm/npmrc
.NET Core. (11 de maig de 2021). https://es.wikipedia.org/wiki/.NET_Core
ReactJS. (19 de maig de 2021). https://ca.wikipedia.org/wiki/ReactJS
I18nect Introduction. (s.d.). https://www.i18next.com/
75
Annex 1. Lliurables del projecte
S’ha entregat el codi desenvolupat per l’aplicació front-end, el codi de la llibreria privada de
components i àtoms, diferents fitxers del codi back-end explicats en l’annex 3 i l’executable en
XD adobe del prototip inicial de l’aplicació. Tots els fitxers estan dins una carpeta anomenada
“PAC_FINAL_prj_PratPladevall_Gil” dins l’entrega del projecte.
76
Annex 2. Captures de pantalla
Figura 46. Panell principal i notificacions.
Figura 47. Panell principal i estadístiques.
Figura 48. Llistat de instal·lacions.
77
Figura 49. Alarmes
Figura 50. Serveis d'un equip.
Figura 51. Emissors i alarmes d'un grup.
78
Figura 52. Usuaris d'un grup
Figura 53. Afegir usuari.
Figura 54. Llistat d'emissors per usuari.
79
Figura 55. Afegir emissors a un usuari.
Figura 56. Veure llicències d'un usuari.
80
Annex 3. Codi Back-End
Controladors nous:
Codi corresponent al fitxer entregat (GroupUsersController.cs)
namespace CloudAssistantApi.ControllersBase
{
/// <summary>
/// Product families Controller v4
/// </summary>
[Route("api/v{version:apiversion}/facilities/{facilityId}/groups")]
public class GroupUsers : BaseControllerV4
{
readonly IFacilityGroupsUsersDbSet _facilityGroupsUsersContext;
/// <summary>
/// GroupUsers Controller
/// </summary>
public GroupUsers(IFacilityGroupsUsersDbSet facilityGroupsUsersDbSet)
{
_facilityGroupsUsersContext = facilityGroupsUsersDbSet;
}
[HttpGet("{groupId}/users")]
public async Task<IEnumerable<ContactDTO>> GetFacilityGroupUsersByGroupId([FromRoute] Guid facilityId,
groupId)
{
return await _facilityGroupsUsersContext.ReadByGroupId(await _userId(), groupId, facilityId);
}
[HttpPost("{groupId}/user")]
public async Task<ActionResult> PostFacilityGroupUser([FromBody] Contact user, Guid groupId)
{
await _facilityGroupsUsersContext.Create(await _userId(), user, groupId);
return CreatedAtAction("PostFacilityGroupUser", null, user);
}
[HttpDelete("{groupId}/users/{userId}")]
public async Task<ContactDTO> DeleteFacilityGroupUser(Guid groupId, Guid userId)
{
var toBeErased = await _facilityGroupsUsersContext.GetGroupUserById(userId, groupId);
await _facilityGroupsUsersContext.Delete(await _userId(), groupId, userId);
return toBeErased;
}
[HttpDelete("{groupId}/users")]
public async Task<Guid> DeleteFacilityGroupUsersList(Guid groupId, List<Guid> userIds)
81
{
await _facilityGroupsUsersContext.DeleteList(await _userId(), groupId, userIds);
return groupId;
}
[HttpPut("{grouId}/users/{userId}")]
public async Task<ContactDTO> PutFacilityGroupUser([FromBody] ContactDTO user, Guid groupId,
Guid userId)
{
// CAUTION! THIS NOT WILL BE AVAIABLE BECAUSE ALL USER IS UPDATED
await _facilityGroupsUsersContext.Update(await _userId(), user, userId, groupId);
return user;
}
[HttpGet("{groupId}/users/fobs")]
public async Task<ActionResult> GetGroupUserFreeFobs(Guid groupId)
{
return Ok(await _facilityGroupsUsersContext.GetAvaiableFobs(await _userId(), groupId));
}
[HttpPost("{groupId}/users/{userId}/fob")]
public async Task<ActionResult> PostFobToUserGroup(Guid groupId, Guid userId, List<Guid> fobIds)
{
await _facilityGroupsUsersContext.AssignFob(await _userId(), groupId, userId, fobIds);
return CreatedAtAction("PostFobToUserGroup", null, fobIds);
}
[HttpGet("{groupId}/users/{userId}/fobs")]
public async Task<IEnumerable<FacilityFob>> GetGroupUserFobs(Guid userId, Guid groupId)
{
return await _facilityGroupsUsersContext.GetUserFobsForGroup(await _userId(), userId, groupId);
}
[HttpDelete("{groupId}/users/{userId}/fob/{fobId}")]
public async Task<ContactDTO> DeleteGroupUserFob(Guid groupId, Guid userId, Guid fobId)
{
var toBeErased = await _facilityGroupsUsersContext.GetGroupUserById(userId, groupId);
await _facilityGroupsUsersContext.UnassignFob(await _userId(), groupId, userId, fobId);
return toBeErased;
}
[HttpGet("{groupId}/users/{userId}/licenses")]
public async Task<IEnumerable<License>> GetGroupUserLicences(Guid userId, Guid groupId)
{
return await _facilityGroupsUsersContext.GetUserLicences(await _userId(), userId, groupId);
}
82
[HttpPut("{groupId}/users/{userId}/licenses/{licenseId}/lock")]
public async Task<License> LockGroupUserLicence(Guid groupId, Guid userId, Guid licenseId)
{
var toBeUpdated = await _facilityGroupsUsersContext.GetUserLicenceById(licenseId);
await _facilityGroupsUsersContext.LockLicense(await _userId(), licenseId, userId, groupId);
return toBeUpdated;
}
[HttpPut("{groupId}/users/{userId}/licenses/{licenseId}/unlock")]
public async Task<License> UnockGroupUserLicence(Guid groupId, Guid userId, Guid licenseId)
{
var toBeUpdated = await _facilityGroupsUsersContext.GetUserLicenceById(licenseId);
await _facilityGroupsUsersContext.UnlockLicense(await _userId(), licenseId, userId, groupId);
return toBeUpdated;
}
async Task<Guid> _userId()
{
try
{
return new Guid(HttpContext.User.Claims.First(x => x.Type == "sub").Value);
}
catch { /* do nothing */ }
return Guid.Empty;
}
}
}
Codi corresponent al fitxer entregat (DashboardController.cs)
namespace CloudassistantApi.ControllersBase
{
[Route("api/v{version:apiversion}/dashboard")]
[Authorize]
public class DashboardController : Controller
{
private readonly IDashboardDbSet _dashboardDbSet;
public DashboardController(IDashboardDbSet dashboardDbSet)
{
_dashboardDbSet = dashboardDbSet;
}
[HttpGet()]
public async Task<IActionResult> GetAll()
{
var userId = await UserId();
Dashboard response = new Dashboard();
83
response.PendingMaintenance = await _dashboardDbSet.GetPendingMaintenance(userId);
response.OnlineStatus = await _dashboardDbSet.GetDevicesConnectionStatus(userId);
response.MissconfiguredDevices = await _dashboardDbSet.GetMissconfiguredDevices(userId);
response.Alarms = await _dashboardDbSet.GetActiveAlarms(userId);
return Ok(response);
}
/// <summary>
/// Get devices with pending maintenance
/// </summary>
/// <returns></returns>
[HttpGet("maintenance")]
public async Task<IActionResult> GetPendingMaitenance()
{
var userId = await UserId();
return Ok(await _dashboardDbSet.GetPendingMaintenance(userId));
}
/// <summary>
/// Get active alarms
/// </summary>
/// <returns></returns>
[HttpGet("alarms")]
public async Task<IActionResult> GetActiveAlarms()
{
var userId = await UserId();
return Ok(await _dashboardDbSet.GetActiveAlarms(userId));
}
/// <summary>
/// Get devices online status
/// </summary>
/// <returns></returns>
[HttpGet("onlinestatus")]
public async Task<IActionResult> GetDevicesStatus()
{
var userId = await UserId();
// Connected 0,1,2
return Ok(await _dashboardDbSet.GetDevicesConnectionStatus(userId));
}
/// <summary>
/// Get devices missconfigured online status
/// </summary>
/// <returns></returns>
[HttpGet("devices/missconfigured")]
public async Task<IActionResult> GetMissconfiguredDevices()
{
84
var userId = await UserId();
return Ok(await _dashboardDbSet.GetMissconfiguredDevices(userId));
}
/// <summary>
/// Get devices missconfigured online status
/// </summary>
/// <returns></returns>
[HttpGet("filters")]
public async Task<IActionResult> GetFilters()
{
return Ok(Filters.getFilters());
}
}
}
Codi corresponent al fitxer entregat (StatisticsController.cs)
namespace CloudassistantApi.ControllersBase
{
[Route("api/v{version:apiversion}/statistics")]
// [Authorize]
public class StatisticsController : Controller
{
private readonly IStatisticsDbSet _statisticsDbSet;
public StatisticsController(IStatisticsDbSet statisticsDbSet)
{
_statisticsDbSet = statisticsDbSet;
}
[HttpGet("type/{statisticsType}")]
public async Task<IActionResult> Statistics(DashboardStatisticsType statisticsType =
DashboardStatisticsType.r1)
{
//tipus de query
var userId = await UserId();
userId = Guid.Empty;
return Ok( await _statisticsDbSet.GetForCustomer(userId, statisticsType));
}
[HttpGet("type/{statisticsType}/equipment/{equipmentId}")]
public async Task<IActionResult> StatisticsForEquipment(Guid equipmentId, DashboardStatisticsType
statisticsType = DashboardStatisticsType.r1)
{
//tipus de query
var userId = await UserId();
return Ok( await _statisticsDbSet.GetForDevice(userId, equipmentId, statisticsType));
}
85
}
}
Codi corresponent al fitxer entregat (NotificationsController.cs)
namespace CloudassistantApi.ControllersBase
{
[Route("api/v{version:apiversion}/notifications")]
[Authorize]
public class NotificationsController : Controller
{
private readonly INotificationsDbSet _notificationsDbSet;
public NotificationsController(INotificationsDbSet notificationsDbSet)
{
_notificationsDbSet = notificationsDbSet;
}
[HttpGet]
public async Task<IActionResult> Notifications()
{
var userId = await UserId();
return Ok( await _notificationsDbSet.GetPendingNotifications(userId));
}
[HttpPost("clear/{id}")]
public async Task<IActionResult> ClearNotification(Guid id)
{
var userId = await UserId();
await _notificationsDbSet.Clear(userId, id);
return Ok();
}
[HttpPost("clear/all")]
public async Task<IActionResult> ClearAllNotifications()
{
var userId = await UserId();
await _notificationsDbSet.ClearAll(userId);
return Ok();
}
}
}
Codi corresponent al fitxer entregat (AlarmsController.cs)
namespace CloudassistantApi.ControllersBase
{
[Route("api/v{version:apiversion}/alarms")]
[Authorize]
86
public class AlarmsController : Controller
{
private readonly IAlarmsDbSet _alarmsDbSet;
private readonly IUsersDbset _usersDbSet;
private readonly ICustomersDbSet _customersDbSet;
private readonly string _hubConnectionString;
readonly IFacilityEquipmentsDbSet _facilityEquipmentsDbSet;
public AlarmsController(IAlarmsDbSet alarmDbSet, IUsersDbset usersDbset,
ICustomersDbSet customersDbSet, IOptions<ApiConfigModel> apiConfig,
IFacilityEquipmentsDbSet facilityEquipmentsDbSet)
{
_alarmsDbSet = alarmDbSet;
_usersDbSet = usersDbset;
_customersDbSet = customersDbSet;
_hubConnectionString = apiConfig.Value.Hub_ConnString;
_facilityEquipmentsDbSet = facilityEquipmentsDbSet;
}
[HttpDelete("{alarmId}")]
public async Task Clear(Guid alarmId)
{
var user = await _usersDbSet.GetUserById(
new Guid(HttpContext.User.Claims.First(x => x.Type == "sub").Value));
var customerIds = await _customersDbSet.GetCustomersTree(
await _customersDbSet.GetCustomerId(user.Id));
var customers = customerIds.Select(x => x.Id).ToList();
customers.Add(user.CustomerId);
await _alarmsDbSet.Clear(customers, user.Id, alarmId);
}
// TODO: Remove, sensor alarms should be reported as real alarms and cleared using
// standard method, also should not be at controller level !!!!!!!
public class AlarmResetResponse
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("payload")]
public dynamic Payload { get; set; }
}
/// <summary>
/// Clear sensor alarm
/// WARNING: This is a temporary fix.Sensor alarms should be reported as real alarms and cleared using
87
/// standard method when correctly implemented.
/// </summary>
/// <param name="equipmentId">Device unique identifier</param>
/// <param name="sensorIndex">Sensor index</param>
/// <param name="alarmCode">Alarm code</param>
/// <returns></returns>
[HttpDelete("sensor/{equipmentId}/{sensorIndex}/{alarmCode}")]
public async Task<IActionResult> ClearSensor(Guid equipmentId, uint sensorIndex,
AlarmCode alarmCode)
{
var user = await _usersDbSet.GetUserById(
new Guid(HttpContext.User.Claims.First(x => x.Type == "sub").Value));
// Get device name for IoTHub
string deviceName = "";
try
{
deviceName = await _facilityEquipmentsDbSet.ReadEquipmentHubName(user.Id, equipmentId);
}
catch
{
throw new Exception(nameof(HttpStatusCode.NotFound),
LogTrace.ComposeException(ApiMessages.IoTHubResponse));
}
DeviceServices hub = new DeviceServices(_hubConnectionString);
var res = new AlarmResetResponse { Status = "---" };
if (alarmCode == AlarmCode.FobLowBattery)
{
res = JsonConvert.DeserializeObject<AlarmResetResponse>(
await hub.InvokeMethod(deviceName, "resetLowBatt", $"{{\"sensor\": { sensorIndex }}}"));
}
switch (res.Status)
{
case "---":
throw new Exception(HttpStatusCode.BadRequest.ToString(),
LogTrace.ComposeException(ApiMessages.EquipmentParamsConfigurationError,
"ERROR: Invalid alarm code"));
case "201":
return Ok();
case "404":
throw new Exception(HttpStatusCode.BadRequest.ToString(),
LogTrace.ComposeException(ApiMessages.EquipmentParamsConfigurationError,
$"ERROR: {res.Payload.error.code.ToString()} -
{res.Payload.error.message.ToString()}"));
88
default:
throw new Exception(HttpStatusCode.InternalServerError.ToString(),
LogTrace.ComposeException(ApiMessages.EquipmentParamsConfigurationError,
$"ERROR: {JsonConvert.SerializeObject(res.Payload)}"));
}
}
[HttpPost("fob/{vertexId}/{fobNumber}/{alarmCode}")]
public async Task<IActionResult> RaiseFob(string vertexId, int fobNumber, AlarmCode alarmCode)
{
await _alarmsDbSet.RaiseFob(vertexId, fobNumber, alarmCode);
return Ok();
}
[AllowAnonymous]
[HttpPost("fobAlarmDummy/{equipmentId}/{fobId}/{alarmCode}")]
public async Task<IActionResult> FobTest(Guid equipmentId, Guid fobId, AlarmCode alarmCode)
{
await _alarmsDbSet.RaiseFobTest(equipmentId, fobId, alarmCode);
return Ok();
}
}
}
Modificacions de controladors existents:
Modificació del controlador d’equips per afegir una ruta per retornar els serveis activats
d’un equip
[HttpGet("{equipmentId}/sim")]
public async Task<ActionResult> GetFacilityEquipmentSimStatus([FromRoute] Guid equipmentId)
{
var serialnumber = await _facilityEquipmentsContext.GetEquipmentSerialNumber(equipmentId,
_apiConfig.Value.Uri_Honoa);
var connectivity = await _facilityEquipmentsContext.ReadEquipmentConnectivity(equipmentId);
var response = new CslGetDeviceStatusResponse();
try
{
response = await _simService.GetSimStatus(serialnumber);
}
catch
{
throw new Exception(HttpStatusCode.NotFound.ToString(),
LogTrace.ComposeException(ApiMessages.CslSimInfoFailed));
}
89
response.FacilityEquipmentConnected = connectivity.connected == "OnLine";
return Ok(response);
}
Modificació del controlador d’instal·lacions per acceptar els nous filtres aplicats en el panel
inicial.
/// <summary>
/// Get facilities page for new search
/// </summary>
[HttpGet("field/{fieldId}")]
[CheckAttribute("MaxItems=100")]
public async Task<dynamic> GetFacilitiesPageNewFilter([FromRoute]facilitiesFilter fieldId,
[FromQuery] string queryText = "", int pagesize = 10, int pagenumber = 1)
{
return await _facilitiesContext.ReadPageFilters(fieldId, await _userId(),
_functions.WrapSqlSpecialChars(queryText), await ReadA5KCommStatus(), pagesize, pagenumber);
}
Accés a la base de dades dels nous controladors
Al ser fitxers molt extensos no s’inclourà el codi en l’annex. Aquest es podrà veure en els fitxers
entregats:
- FacilityGroupUsersDbSet.cs corresponent al controlador GroupUsersController.cs.
- DashboardDbSet.cs corresponent al controlador DashboardController.cs.
- NotificationsDbSet.cs corresponent al controlador NotificationsController.cs
- AlarmsDbSet corresponent al controlador AlarmsController.cs
- StatisticsDbSet.cs corresponent al controlador StatisticsController.cs.
Modificació d’accés a la base de dades de controladors existents
Modificació de les respostes de les entitats FacilityEquipment, Facility, Fob i FacilityGroup per a
poder retornar les alarmes corresponents a aquestes entitats. Es mostra la modificació bàsica
realitzada a cada context de dades de les entitats per separat.
// facility context
facility.Alarms = await _alarmsDbSet.GetSummaryForEntity(facility.CustomerId, AlarmEntity.Facility,
facility.Id, language);
// facilityEquipment context
equipment.Alarms = await _alarmsbSet.GetSummaryForEntity(equipment.CustomerId, Models_Dapper.AlarmEntity.Equi
pment, equipment.Id, user.Language);
//Fob context
fob.Alarms = awiat _alarmDbSet.GetForEntity(fob.CustomerId, AlarmEntity.Fob, fob.Id, user.Language);
90
//FacilityGroup context
group.Alarms = await _alarmDbSet.GetSummaryForEntity(group.CustomerId,Models_Dapper.AlarmEntity.Group, group.
Id, user.Language);
Modificació del context de dades de Facilities (Instal·lacions) per a poder gestionar les cerques
i els nous filtres del panell:
async Task<PageList<Facilities>> PageRequestFilters(Guid CustomerId, facilitiesFilter fieldId, string queryFie
ld, List<DevicesConnection> devicesConnected, int pageSize, int pagenumber)
{
List<Guid> CustomerIds = new List<Guid>();
CustomerIds.Add(CustomerId);
using (var dbContext = await _sqlClient.GetDbConnection())
{
var fieldRegex = new Regex("^[A-Za-z-ZÀ-ÿ0-9\\s]{1,30}$");
string queryTextFilter = "";
string queryTextFilter2 = "";
bool searchInAlarms = false;
bool searchInEquipments = false;
switch (fieldId)
{
case facilitiesFilter.Name:
queryField = "%" + queryField + "%";
queryTextFilter = "AND F.Name LIKE @fieldValue";
break;
case facilitiesFilter.Address:
queryField = "%" + queryField + "%";
queryTextFilter = "AND F.Address LIKE @fieldValue";
break;
case facilitiesFilter.City:
queryTextFilter = "AND F.City = @fieldValue";
break;
case facilitiesFilter.Zip:
queryTextFilter = "AND F.Zip = @fieldValue";
break;
case facilitiesFilter.Country:
queryField = "%" + queryField + "%";
queryTextFilter = "AND F.Country LIKE @fieldValue";
break;
case facilitiesFilter.Uniqueidentifier:
queryTextFilter = "AND F.UniqueIdentity = @fieldValue";
break;
case facilitiesFilter.ActiveAlarms:
searchInAlarms = true;
queryTextFilter = " AND TargetType = 5";
break;
91
case facilitiesFilter.ConnectedDevices:
queryTextFilter2 = " FE.Connected = 2";
queryTextFilter = " AND F.Id IN(SELECT FacilityId FROM FacilityEquipments
WHERE CustomerId IN @CustomerIds AND FacilityEquipments.Connected = 2)";
searchInEquipments = true;
break;
case facilitiesFilter.DisconnectedDevices:
queryTextFilter2 = " FE.Connected = 1";
queryTextFilter = " AND F.Id IN(SELECT FacilityId FROM FacilityEquipments
WHERE CustomerId IN @CustomerIds AND FacilityEquipments.Connected = 1)";
searchInEquipments = true;
break;
case facilitiesFilter.MissconfiguredDevices:
queryTextFilter2 = "FE.IsUpdated = 'False'";
queryTextFilter = " AND F.Id IN(SELECT FacilityId FROM FacilityEquipments
WHERE CustomerId IN @CustomerIds AND FacilityEquipments.IsUpdated = 0)";
searchInEquipments = true;
break;
case facilitiesFilter.PendingMaintenance:
queryTextFilter = "AND F.MaintenanceDate < GETDATE()";
break;
case facilitiesFilter.MissconfiguredConnected:
queryTextFilter2 = "FE.Connected = 2 AND FE.IsUpdated = 'False'";
queryTextFilter = " AND F.Id IN(SELECT FacilityId FROM FacilityEquipments
WHERE CustomerId IN @CustomerIds AND FacilityEquipments.IsUpdated = 0
AND FacilityEquipments.Connected = 2)";
searchInEquipments = true;
break;
}
// Queries builded
List<string> CustomerString = CustomerIds.Select(x => x.ToString()).ToList();
string sqlCmd_SelectFilterRowsCount = "";
string sqlCmd_SelectFacilities = "";
if (searchInEquipments)
{
sqlCmd_SelectFilterRowsCount = string.Format("Select SUM(FilterRows.Count) as
OverallRows " +
"FROM (Select CustomerId, Count(*) as Count From Facilities AS F WHERE F.Id IN " +
"(SELECT FacilityId From FacilityEquipments FE WHERE CustomerId IN @CustomerIds AND {0} )
Group by CustomerId) as FilterRows", queryTextFilter2);
sqlCmd_SelectFacilities = string.Format(
"SELECT C.Name AS CustomerName, F.*, C.Id AS CustomerId, FE.*, FA.* FROM Facilities " +
"AS F left Join Customers AS C ON F.CustomerId = C.Id left JOIN FacilityEquipments AS FE
ON FE.FacilityId = F.Id" +
" left JOIN FacilityAttributes AS FA ON FA.FacilityId = F.Id WHERE F.Id IN (SELECT F.Id
92
From Facilities as F " +
"LEFT JOIN Customers as C on C.Id=CustomerId " +
"WHERE CustomerId IN @CustomerIds {0} " +
" ORDER BY C.Name, F.Name OFFSET @pageSize* (@pagenumber -
1) ROWS FETCH NEXT @pageSize ROWS ONLY) " +
"ORDER BY C.Name, F.Name", queryTextFilter);
}
else if (searchInAlarms)
{
sqlCmd_SelectFilterRowsCount = string.Format("Select SUM(FilterRows.Count) as OverallRows
FROM (Select CustomerId, Count(*) as Count From Facilities AS F " +
"WHERE F.Id IN (SELECT TargetId From Alarms WHERE CustomerId IN @CustomerIds {0} )
Group by CustomerId) as FilterRows", queryTextFilter);
sqlCmd_SelectFacilities = string.Format("SELECT C.Name AS CustomerName, F.*, C.Id AS
CustomerId, FE.*, FA.* FROM Facilities " +
"AS F left Join Customers AS C ON F.CustomerId = C.Id left JOIN FacilityEquipments
AS FE ON FE.FacilityId = F.Id" +
" left JOIN FacilityAttributes AS FA ON FA.FacilityId = F.Id WHERE F.Id
IN (SELECT F.Id From Facilities as F " +
"LEFT JOIN Customers as C on C.Id=CustomerId " +
"WHERE CustomerId IN @CustomerIds AND F.ID
IN(SELECT TargetId From Alarms WHERE CustomerId IN @CustomerIds {0}) " +
" ORDER BY C.Name, F.Name OFFSET @pageSize* (@pagenumber -
1) ROWS FETCH NEXT @pageSize ROWS ONLY) " +
"ORDER BY C.Name, F.Name", queryTextFilter);
}
else
{
sqlCmd_SelectFilterRowsCount = string.Format("Select SUM(FilterRows.Count) as OverallRows
FROM (Select CustomerId, Count(*) as Count From Facilities AS F WHERE F.Id
IN (SELECT Id From Facilities WHERE CustomerId IN @CustomerIds)
{0} Group by CustomerId) as FilterRows", queryTextFilter);
sqlCmd_SelectFacilities = string.Format("SELECT C.Name AS CustomerName, F.*, C.Id
AS CustomerId, FE.*, FA.* FROM Facilities " +
"AS F left Join Customers AS C ON F.CustomerId = C.Id left JOIN FacilityEquipments
AS FE ON FE.FacilityId = F.Id" +
" left JOIN FacilityAttributes AS FA ON FA.FacilityId = F.Id WHERE F.Id IN
(SELECT F.Id From Facilities as F " +
"LEFT JOIN Customers as C on C.Id=CustomerId WHERE CustomerId IN @CustomerIds {0}
ORDER BY C.Name, F.Name OFFSET @pageSize* (@pagenumber - 1)
ROWS FETCH NEXT @pageSize ROWS ONLY) " +
"ORDER BY C.Name, F.Name", queryTextFilter);
}
// Building JSON
PageList<Facilities> readPageResult =
(await dbContext.QueryAsync<PageList<Facilities>>(sqlCmd_SelectFilterRowsCount,
93
new { CustomerIds = CustomerString, fieldValue = queryField,
pageSize, pagenumber })).FirstOrDefault();
readPageResult.PageSize = pageSize;
if (readPageResult.OverallRows <= (readPageResult.PageSize *
(pagenumber - 1))) pagenumber = 1;
readPageResult.CurrentPage = pagenumber;
// Populate items
var lookup = new Dictionary<Guid, Facilities>();
var lookupAttributes = new Dictionary<Guid, FacilityAttributes>();
readPageResult.PageItems = (await dbContext.QueryAsync<Facilities, FacilityEquipment,
FacilityAttributes, Facilities>(sqlCmd_SelectFacilities, (Facilities,
FacilityEquipments, FacilityAttributes) =>
{
if (!lookup.TryGetValue(Facilities.Id, out Facilities facility))
lookup.Add(Facilities.Id, facility = Facilities);
if (facility.FacilityEquipments == null)
{
facility.FacilityEquipments = new List<FacilityEquipment>();
}
if (facility.FacilityAttributes == null)
{
facility.FacilityAttributes = new List<FacilityAttributes>();
}
if (FacilityEquipments != null)
{
facility.FacilityEquipments.Add(FacilityEquipments);
}
if (FacilityAttributes != null)
{
if (!lookupAttributes.TryGetValue(FacilityAttributes.Id,
out FacilityAttributes attribute))
{
lookupAttributes.Add(FacilityAttributes.Id, attribute = FacilityAttributes);
facility.FacilityAttributes.Add(FacilityAttributes);
}
}
return facility;
},
new { CustomerIds = CustomerString, fieldValue = queryField, pageSize, pagenumber }))
.Distinct();
_logger.LogWarning(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
+ " -> ConnectivityStatus, devices : " + devicesConnected.Count());
foreach (Facilities facilities in readPageResult.PageItems)
{
94
facilities.AllEquipmentsConnected =
(await CheckIfEquipmentsConnected(dbContext, facilities.FacilityEquipments,
devicesConnected)) ? true : false;
facilities.ConnectedDevicesAmount =
await GetCountEquipmentsConnectivity(dbContext, facilities.FacilityEquipments);
}
_logger.LogWarning(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") +
" - pageRequest -> Finish");
return readPageResult;
}
}
Servei per accedir a la API externa per consultar els serveis activats
d’un dispositiu
S’entrega el codi del fitxer SimService.cs encarregat d’autentificar-se contra una API interna
anomenada CSL la qual és l’encarregada d’obtenir els serveis activats o utilitzats per els equips
dels nostres clients. Aquest servei el consumeix la modificació del controlador d’equips amb la
funció GetFacilityEquipmentSimStatus
Comunicació amb Web-Sockets
Codi corresponent al fitxer FrontHub.cs, encarregat de gesitonar el Web-Socket amb SignalR
injectat al StartUp del projecte.
namespace CloudAssistantApi.SignalR
{
[Authorize]
public class FrontHub : Hub
{
public override async Task OnConnectedAsync()
{
string BBid = Context.GetHttpContext().Request.Query["userid"];
var userId = Context.GetHttpContext().Request.HttpContext.User.Claims.
First(x => x.Type == "sub").Value;
string customerId = Context.GetHttpContext().Request.Query["customerId"];
if(BBid != null)
{
await Groups.AddToGroupAsync(Context.ConnectionId, BBid);
}
if (customerId != null)
{
await Groups.AddToGroupAsync(Context.ConnectionId, customerId);
}
await Clients.Client(Context.ConnectionId).SendAsync("Alarm", "ConnectionId",
Context.ConnectionId);
95
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
public void Send(string name, string message)
{
string[] clientId = name.Split(new char[] { ':', ':' });
if (clientId.Length >= 2)
{
if (clientId[0] != "")
{
Clients.Group(clientId[0]).SendAsync("Alarm", name, message);
Console.WriteLine(clientId[0]);
}
}
else
{
Clients.Client(name).SendAsync("Alarm", name, message);
}
}
}
}
ServiceBus
S’entrega el codi del fitxer VertexServiceBusService.cs encarregat de tractar els missatges
filtrats de la telemetria de IoT Hub d’Azure, enviats al nostre service bus per tòpics, amb el qual
es poden tractar quests missatges en el back-end i d’aquesta manera tractar les alarmes i
altres events que generen els dispositius.
StartUp
S’entrega el codi del fitxer StartUp.cs per a poder veure mínimament la injecció de
dependències de tot el projecte.
96
Annex 4. Guia d’usuari
Per utilitzar l’aplicació s’ha de tenir coneixements dels productes de l’empresa i com
funcionen mínimament. En la guia d’usuari s’explicarà només els passos essencials per a
poder utilitzar l’aplicació de tal manera que es puguin observar les pantalles realitzades i les
modificacions fetes. Al ser una aplicació que funciona amb instal·lacions i equips reals,
s’ensenyarà com crear-les però es donarà una sèrie d’instal·lacions ja fetes a un usuari creat
anteriorment per a poder provar l’aplicació. L’usuari per fer les proves s’indica en l’apartat de
requisits i instruccions d’ús.
- Login:
Al accedir a la url base https://jcm-web-ca-v4-dev.azurewebsites.net es redirigirà a la
pantalla de login per iniciar sessió.
Al entrar les dades de l’usuari i la contrasenya correctament es polsarà el botó d’entrar.
- Dashboard
Un cop iniciada la sessió la primera pantalla en aparèixer és el panell. Des del panell es
poden visualitzar la cerca de instal·lacions avançades i diferents estadístiques i valors
en les targetes en funció dels elements del sistema. En aquest cas les estadístiques
són d’equips reals forçats per el servidor per a poder visualitzar dades, ja que al ser
dades reals d’equips, per fer la prova complerta s’hauria d’instal·lar un equip,
connectar-lo a internet i deixar-lo uns dies funcionant.
Pel que fa a les altres targetes des de les fletxes de cada element o els requadres en el
cas de dispositius desconfigurats i estat dels dispositius, es redirigirà al llistat de
instal·lacions filtrades per l’element seleccionat.
- Instal·lacions
En la pestanya d’instal·lacions podem observar el llistat d’instal·lacions del client.
Cada instal·lació es pot desplegar polsant la fletxeta en direcció cap avall o polsant a
l’element. Un cop desplegada es podran visualitzar, editar i crear la informació de la
instal·lació, els equips i els grups.
Per crear una instal·lació nova en el llistat d’instal·lacions s’ha de clicar el botó flotant
amb el símbol “+” de baix a la dreta de la pantalla.
- Equips
Per visualitzar un equip només es pot fer des de dins una instal·lació, per tant al crear o
anar a una instal·lació existent s’ha de navegar fins a la pestanya de “equipos”. En
aquesta pestanya s’observa el llistat d’equips i el seu estat, si esta desconnectat,
connectat, si està configurat etc...
97
Per crear un equip s’ha de clicar el botó amb el símbol “+” de baix a la dreta de la
targeta.
Al clicar la capçalera de l’equip s’obrirà aquest equip i es podrà veure i editar la
informació d’aquest.
En el cas de ser un equip amb connectivitat apareixerà una icona de Wi-Fi a la
capçalera de l’equip. Clicant aquesta icona s’obrirà un pop-up amb la informació dels
serveis associats a aquest equip si n’hi ha.
- Grups
Els grups funcionen similar als equips. Per anar a veure els grups des de dins una
instal·lació s’ha de clicar la pestanya de “grupos”, des d’aquest pestanya s’observarà
un llistat de grups si n’hi ha i s’en podrà crear un de la mateixa manera que en la
pestanya d’equips.
Un cop creat un grup et redirigirà automàticament a la pantalla d’assignació de relés. Si
no s’assigna un grup a un relé d’un equip, en aquest grup no s’hi podrà afegir emissors.
Per a veure un grup, des del llistat de grups s’ha de clicar a la capçalera o a la icona de
desplegar el grup. Un cop fet aixó apareixerà per pantalla els emissors d’aquell grup i
dos pestanyes més, “Usuarios” i “Informacion”. En la pestanya de Fobs es podrà crear,
modificar, esborrar emissors del grup i configurar el grup.
Per configurar el grup s’ha de clicar a la icona de “setttings” de baix a la dreta. Per
entrar emissors a un grup s’ha de clicar a la icona de “alta de código de baix a la dreta”
En la pestanya de “usuarios” es veuran els usuaris assignats a un grup. Aquests es
podran esborrar crear i afegir. Per afegir un usuari s’ha de clicar a la icona de baix a la
dreta “añadir usuario”.
Per veure els emissors i llicències que te un usuari, s’ha de polsar la icona “+” de
l’usuari en la taula d’usuaris. S’obrirà un “pop-up” en el qual es podrà visualitzar els
emissors assignats i amb un botó per afegir emissors. En la pestanya de llicències es
visualitzaran les llicències de l’usuari si en té, i es podran bloquejar i desbloquejar. En
aquest cas no es poden afegir llicencies ja que les afegeix l’usuari real pagant amb
l’aplicació mòbil. Per a fer les proves es pot navegar a la instal·lació “test UOC”, en
aquesta instal·lació obrir el grup “professors uoc” i en la pestanya d’usuaris apareixerà
l’usuari [email protected] amb una llicència assignada.
- Notificacions
Les notificacions apareixeran sempre a l’entrar a qualsevol pantalla si l’usuari te
notificacions pendents per llegir. Al clicar a la icona de la campana de notificacions es
desplegarà un llistat de notificacions. En aquest llistat es podrà veure una notificació en
concret (i ja es marcarà com a vista) o marcar-les totes com a vistes.
98
Recommended