scieee AI-readable full text Open interactive document viewer

Desarrollo de aplicación móvil para telelectura de contadores de agua

Rodríguez Mateo, Fernando

Abstract

Actualmente se está produciendo un aumento considerable de dispositivos IoT que se disponen para mejorar el nivel de vida actual de las personas. Uno de los aspectos que actualmente se encuentran en desarrollo es el del control y mantenimiento de la cantidad de agua que se consumen en el hogar. Debido al cambio climático, es fundamental que se racione la cantidad de agua que consume la población. Además, este raciocinio ayuda a economizar el gasto que se genera del mismo, por lo que es una clara ventaja para la población. Por otro lado, el aumento de dispositivos móviles que actualmente se utilizan aporta una clara ventaja al objetivo marcado anteriormente. Sin embargo, no existen muchas aplicaciones móviles destinadas al control y la telelectura de contadores de agua. El objetivo de este proyecto es el desarrollo de una aplicación que permita la lectura de contadores de agua en el dispositivo móvil, permitiendo el manejo de cualquier contador de agua IoT gracias al servicio de una plataforma que permite integrar diferentes tipos de contadores y unificarlos, permitiendo una rápida accesibilidad y manejabilidad.

Full text

Equation Chapter 1 Section 1 Proyecto Fin de Grado Ingeniería de Telecomunicación Desarrollo de aplicación móvil para telelectura de contadores de agua Autor: Fernando Rodríguez Mateo Tutor: Jose Manuel Fornés Rumbao Dpto. de Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2021 iii Proyecto Fin de Grado Ingeniería de Telecomunicación Desarrollo de aplicación móvil para telelectura de contadores de agua Autor: Fernando Rodríguez Mateo Tutor: Jose Manuel Fornés Rumbao Profesor titular Dpto. de Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2021 v Proyecto Fin de Carrera: Desarrollo de aplicación móvil para telelectura de contadores de agua Autor: Fernando Rodríguez Mateo Tutor: Jose Manuel Fornés Rumbao El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: Presidente: Vocales: Secretario: Acuerdan otorgarle la calificación de: Sevilla, 2013 El Secretario del Tribunal vii A mi familia A mis maestros ix Agradecimientos Quiero agradecer en estas líneas a todos los que me apoyan día a día y me han apoyado durante estos años para llegar aquí. A mi familia por estar siempre conmigo, confiar en mí, apoyarme y animarme siempre para seguir luchando ya que ellos saben cuánto he sufrido por llegar hasta aquí. A mis compañeros por ayudarme de muchas maneras en Sevilla, especialmente a Pablo, Manu y Fran, que sin su apoyo no habría podido seguir adelante en este proyecto. A mis amigos por hacer más ameno el día a día y haber estado en los buenos y en los malos momento. Por último, a mi tutor por dejarme hacer realidad este proyecto. Fernando Rodríguez Mateo Sevilla, 2021 xvii ÍNDICE DE TABLAS Tabla 3-1. Tipos de mensajes 13 xix ÍNDICE DE FIGURAS Figura 1-1. Número de dispositivos conectados 1 Figura 1-2. Evolución esperada frente a la real. 2 Figura 3-1. Arquitectura ThingsBoard 5 Figura 3-2. Motor de Reglas de ThingsBoard 6 Figura 3-3. Interfaz de Web de ThingsBoard 7 Figura 3-4. Estructura de entidades 8 Figura 3-5. Posibles Relaciones de entidades 9 Figura 3-6. Atributos del lado del servidor 10 Figura 3-7. Atributos compartidos 10 Figura 3-8. Atributos del lado del cliente 10 Figura 3-9. Cadena de reglas 12 Figura 3-10. Cadena de reglas 14 Figura 3-11. Dashboard 15 Figura 3-12. Biblioteca de Widgets 16 Figura 3-13. API REST de ThingsBoard 17 Figura 3-14. API para motor de reglas 19 Figura 4-1. Gráfico Global del Proyecto 20 Figura 4-2. Gráfico de la Aplicación 21 Figura 4-3. Gráfico del Servidor 21 Figura 4-4. Gráfico del Generador de datos 22 Figura 4-5. Estructura de la aplicación en React Native 22 Figura 4-6. Líneas de import del proyecto 23 Figura 4-7. Creación de la pila 24 Figura 4-8. Estructura de la navegación de App.js 24 Figura 4-9. Importar el componente BarChart 25 Figura 4-10. Componente BarChart 25 Figura 4-11. Componente YAxis 26 Figura 4-12. Componente Image 26 Figura 4-13. Importar el componente KeyboardAwareScrollView 26 Figura 4-14. Componente KeyboardAwareScrollView 27 Figura 4-15. Importar MaterialComunityIcons 27 Figura 4-16. Componente Icon 28 Figura 4-17. Variable del icono 28 Figura 4-18. Cambio de icono 28 Figura 4-19. Importar RadioButtonRN 28 Figura 4-20. Componente RadioButtonRN 28 Figura 4-21. Componente ScrollView 29 Figura 4-22. Componente StatusBar 29 Figura 4-23. Importar el componente Svg 30 Figura 4-24. Componente Svg 30 Figura 4-25. Componente Switch 30 Figura 4-26. Activación del Switch 31 Figura 4-27. Importar el componente Table 31 Figura 4-28. Componente Table 32 Figura 4-29. Componente Text 32 Figura 4-30. Component TextInput 33 Figura 4-31. Componente TouchableOpacity 33 Figura 4-32. Componente View 34 Figura 4-33. API Alert 34 Figura 4-34. API Animated 35 Figura 4-35. API KeyBoard 35 Figura 4-36. API Platform 36 Figura 4-37. API StyleSheet 36 Figura 4-38. Importar estilos 36 Figura 4-39. Componente ToastAndroid 37 Figura 4-40. Creación de la API 37 Figura 4-41. Cambio de cabecera 37 Figura 4-42. Método async/await 38 Figura 4-43. Panel de control de ThingsBoard 43 Figura 4-44. Grupo de cadenas de reglas creadas 44 Figura 4-45. Comprobación del dispositivo 44 Figura 4-46. Comprobación del nivel 45 Figura 4-47. Creación del email 45 Figura 4-48. Cadena de reglas de la alarma. 46 Figura 4-49. Cadena de reglas raíz. 46 Figura 4-50. Jerarquía de clientes 47 Figura 4-51. Usuario del cliente 47 Figura 4-52. Cuenta de usuario activado 48 Figura 4-53. Contador asignado al usuario 49 Figura 4-54. Grupo de dispositivos del cliente. 49 Figura 4-55. Atributos del servidor 50 Figura 4-56. Atributos compartidos 50 Figura 4-57. Última telemetría registrada 51 xxi Figura 4-58. Alarmas generadas por el contador 51 Figura 4-59. Inicio de Sesión 52 Figura 4-60. Mensajes de error 52 Figura 4-61. Registro del usuario 53 Figura 4-62. Mensajes de error 53 Figura 4-63. Usuario creado y cuenta activada 54 Figura 4-64. Menú de la aplicación 54 Figura 4-65. Mensaje de error 55 Figura 4-66. Registrar Contador 55 Figura 4-67. Mensaje de error 56 Figura 4-68. Dispositivo creado correctamente 56 Figura 4-69. Pantalla de perfil 57 Figura 4-70. Pantalla del contador 57 Figura 4-71. Corte o Activación del agua 58 Figura 4-72. Distintas gráficas de barras 58 Figura 4-73. Tabla de alarmas y el correo 59 Figura 4-74. Pantallas de configuración 60 Figura 4-75. Cambio de configuración 60 Figura 4-76. Mensaje de error 61 Figura 4-77. Cambios del usuario y contador 61 Figura 5-1. Incorporar fetch al código 62 Figura 5-2. Petición a login 62 Figura 5-3. Petición al dispositivo 63 Figura 5-4. Entrega del dato 63 Figura 5-5. Código del generatorDaily.js 65 Figura 5-6. Ejecución del código 65 Figura 5-7. Código de generatorMonth.js 67 Figura 5-8. Ejecución del código 67 xxiii Notación API Interfaz de Programación de Aplicaciones (Application Programming Interface) CoAP Constrained Application Protocol HTTP Protocolo de transferencia de hipertexto (Hypertext Transfer Protocol) IoT Dispositivos de las Cosas (Internet of Things) JSON Notación de Objeto de JavaScript (JavaScript Object Notation) MQTT Protocolo de mensajería estándar de para IoT REST Transferencia de Estado Representacional (Representational State Transfer) RPC Llamada a procedimiento remoto (Remote Procedure Call) SQL Lenguaje de Consulta Estructurada (Structured Query Language) 1 1 INTRODUCCIÓN medida que se va expandiendo el alcance de los dispositivos de IoT, la demanda de los mismos también aumenta, lo que hace que se desarrollen tecnologías que permitan el acceso y control a dichos dispositivos. Actualmente, el avance de la tecnología IoT se encuentra centralizado en los suministros básicos (Agua, electricidad…), por lo que se espera que haya una gran cantidad de datos a gestionar. Debido a esto, se espera que las empresas desarrollen diferentes estrategias para abordarlo. Para ello mostraremos cómo se encuentran los dispositivos IoT en general, así como el aumento de medidores digitales de agua que hay en el mercado. 1.1 Estado Actual Debido al gran aumento de las tecnologías a nivel global, las empresas deben modernizarse para poder seguir siendo competitivos, esto se ha incrementado debido a la introducción de los dispositivos IoT. El término IoT se ha acuñado en 1999 por Kevin Ashton, aunque no ha sido hasta el 2010 cuando se ha visto la utilidad a los dispositivos IoT. Desde entonces ha habido un aumento exponencial de la cantidad de dispositivos utilizados, llegando a tener más del 50% de los dispositivos conectados actualmente. [1] Figura 1-1. Número de dispositivos conectados El aumento de dispositivos IoT ha sido aún más grande en el año 2020 debido a la pandemia COVID-19. [2] Ya que la mayoría de los trabajos se han tenido que realizar desde casa, se ha vuelto acuciante que se puedan manejar los dispositivos y aparatos externamente. Esto da lugar a implementar soluciones IoT. A No hay un sustituto para el trabajo duro. - Thomas Edison - 8 3.2.3 Conceptos clave ThingsBoard posee una serie de elementos que son fundamentales para la comprensión de la plataforma y que en este apartado vamos a desglosar para su mayor comprensión. Estos conceptos sirven para que la aplicación se comunique con el servidor y nos ayude a diseñar la estructura de esta. 3.2.3.1 Entidades y Relaciones ThingsBoard provee a la interfaz de usuario y a las API REST administrar múltiples tipos de entidades y sus relaciones en su aplicación de IoT. Las entidades admitidas son: • Tenant: Es un individuo u organización que posee o produce dispositivos y activos. El tenant puede tener varios usuarios administradores de tenant y millones de clientes, dispositivos y activos; • Clientes: El cliente también es una entidad comercial separada, individuo u organización que compra o usa dispositivos y/o activos del tenant; El cliente puede tener varios usuarios y millones de dispositivos y/o activos; • Usuarios: los usuarios pueden navegar por paneles y administrar entidades; • Dispositivos: entidades básicas de IoT que pueden producir datos de telemetría y manejar comandos RPC. Por ejemplo, sensores, actuadores, interruptores; • Activos: entidades abstractas de IoT que pueden estar relacionadas con otros dispositivos y activos. Por ejemplo, fábrica, campo, vehículo; • Vistas de entidad: útil si desea compartir solo una parte de los datos del dispositivo o de los activos con los clientes; • Alarmas: eventos que identifican problemas con sus activos, dispositivos u otras entidades; • Paneles de control: visualización de sus datos de IoT y capacidad para controlar dispositivos particulares a través de la interfaz de usuario; • Nodo de reglas: unidades de procesamiento para mensajes entrantes, eventos del ciclo de vida de la entidad, etc. • Cadena de reglas: define el flujo del procesamiento en el motor de reglas. Puede contener muchos nodos de reglas y enlaces a otras cadenas de reglas. Figura 3-4. Estructura de entidades 9 Cada entidad posee varias características, que son las siguientes: • Atributos: Son conceptos clave-valor estáticos y semiestáticos que describen características de las entidades. Por ejemplo, el número de serie, modelo, firmware… • Datos de serie de tiempos (Timeseries): Datos asociados a un tiempo concreto disponibles para la visualización, consulta y almacenamiento. Por ejemplo, temperatura, humedad… • Relaciones: Conexiones entre dos entidades, pueden ser de producir, administrar, poseer… A continuación, vamos a observar las relaciones. Las relaciones se definen entre dos entidades de este tenant, de modo que tienen un tipo arbitrario que puede ser contiene, soporta, gestiona… Las relaciones de ThingsBoard son del tipo direccionales, similar a las relaciones de la programación orientada a objetos. Las relaciones ayudan a entender las relaciones de las entidades del mundo físico en ThingsBoard. En el siguiente diagrama se muestran las posibles relaciones. Figura 3-5. Posibles Relaciones de entidades 3.2.3.2 Atributos ThingsBoard permite asignar atributos personalizables a sus entidades y trabajar con ellos. Estos atributos se pueden almacenar en la base de datos para que se puedan utilizar en el procesamiento de datos o visualizar más adelante. Se muestran mediante un par de clave-valor. Este formato permite una mayor flexibilidad e integración de los dispositivos IoT existentes en el mercado. La clave es siempre una cadena y es básicamente un nombre de atributo, mientras que el valor del atributo puede ser cadena, booleano, doble, entero o JSON. Los nombres de los atributos son totalmente personalizables, sin embargo, ThingsBoard recomienda utilizar el formato CamelCase ya que permite una mayor facilidad de integración a las funciones JavaScript. En ThingsBoard existen tres tipos de atributos. 3.2.3.2.1 Atributos del lado del servidor Es compatible con cualquier entidad que tiene la plataforma (clientes, usuarios, dispositivos, activos…). Son las que se pueden configurar a través de la interfaz del usuario o de las API. Sin embargo, el dispositivo no 10 puede acceder al atributo. Figura 3-6. Atributos del lado del servidor 3.2.3.2.2 Atributos compartidos Este tipo de atributos solo está disponible para los dispositivos. Es similar a los atributos del lado del servidor, pero el dispositivo puede solicitar el valor del atributo o suscribirse a las actualizaciones de este. Los dispositivos que se comunican mediante MQTT u otros protocolos de comunicación bidireccionales pueden suscribirse a las actualizaciones del atributo en tiempo real. Mientras, los dispositivos con HTTP u otros protocolos de comunicación solicitud-respuesta pueden pedir periódicamente el valor del atributo. Figura 3-7. Atributos compartidos 3.2.3.2.3 Atributos del lado del cliente Estos atributos solo están disponibles para los dispositivos, se utiliza para informar de varios datos semiestáticos desde el dispositivo a ThingsBoard. Es similar a los atributos compartidos, pero el dispositivo puede enviar valores a la plataforma. Figura 3-8. Atributos del lado del cliente 11 3.2.3.3 Datos de serie de tiempos (Timeseries) ThingsBoard trabaja con datos de timeseries como pares clave-valor con marca de tiempo. Como los atributos descritos en el apartado anterior, las claves son cadenas de caracteres mientras que el valor puede ser una cadena de caracteres, booleano, doble, entero o JSON. ThingsBoard proporciona una amplia gama de funciones relacionadas como pueden ser: • Recopilar los datos de los dispositivos mediante varios protocolos e integraciones. • Almacenar los datos en bases de datos SQL y NoSQL. • Consultar el dato más reciente o consultar los datos en un rango de tiempo más específico. • Visualizar los datos en dashboards configurables y personalizables. • Filtrar y analizar los datos mediante el motor de reglas. • Generar alarmas basadas en datos recopilados • Reenviar datos a sistemas externos. 3.2.3.4 Alarmas La plataforma permite crear y administrar alarmas relacionadas con sus entidades (dispositivos, activos, clientes…). Se puede configurar, por ejemplo, para que salte cuando cierto sensor esté por encima de cierto umbral. Este es un caso muy sencillo, pero puede llegar a ser mucho más complejo. Las alarmas tienen varias características principales que son las siguientes: 3.2.3.4.1 Autor El originador de la alarma es aquella entidad que la provoca. 3.2.3.4.2 Tipo El tipo de alarma ayuda a identificar cuál es la causa de que la alarma salte. 3.2.3.4.3 Gravedad Cada alarma tiene una gravedad que puede ser Crítica, Mayor, Menor, Advertencia o Indeterminada (clasificadas por prioridad en orden descendente). 3.2.3.4.4 Ciclo de Vida La alarma puede estar activada o borrada. Cuando ThingsBoard crea la alarma, persiste la hora de inicio y finalización de esta. De forma predeterminada, la hora de inicio y la hora de finalización son las mismas. Si la condición de activación de la alarma se repite, la plataforma actualiza la hora de finalización. ThingsBoard puede borrar automáticamente la alarma cuando ocurre un evento que coincide con una condición de borrado de alarma. Un usuario puede borrar la alarma manualmente. Además del estado de alarma activa y borrada, ThingsBoard también realiza un seguimiento de si alguien ha reconocido la alarma. Para resumir, hay 4 valores posibles del campo "estado": • Activa no reconocida (ACTIVE_UNACK): la alarma no se borra y aún no se reconoce. • Activo reconocido (ACTIVE_ACK): la alarma no se borra, pero ya se reconoció. • Borrado no reconocido (CLEARED_UNACK): la alarma ya se borró, pero aún no se reconoció. • Borrado reconocido (CLEARED_ACK) - la alarma ya fue borrada y reconocida. 3.2.3.4.5 Unicidad de la alarma ThingsBoard reconoce la alarma usando una combinación del autor, tipo y la hora de inicio de esta. Por lo tanto, solo puede haber una alarma con el mismo autor, tipo y hora. 12 3.2.3.4.6 Propagacio n de la alarma ThingsBoard admite la propagación de la alarma. Cuando se crea la alarma, podemos especificar si debe ser visible para las entidades principales o no. También podemos especificar opcionalmente las relaciones que deben estar presentes entre las entidades padre y el autor para que se propague la alarma. 3.2.4 Motor de reglas Es un marco de ThingsBoard para crear flujos de trabajos basados en eventos. Con el motor de reglas, podemos filtrar, enriquecer y transformar los mensajes entrantes originados por dispositivos de IoT y activos relacionados. También podemos activar varias acciones, por ejemplo, notificaciones o comunicación con sistemas externos. Se compone de tres elementos principales. • Mensaje: Cualquier evento entrante. Puede ser un dato de dispositivo, eventos de ciclo de vida del dispositivo, eventos de API REST, solicitud de RPC, etc. • Nodo de reglas: una función que se ejecuta en un mensaje entrante. Hay muchos tipos de nodos diferentes que veremos más adelante. • Cadena de reglas: los nodos están unidos entre sí mediante relaciones, por lo que el mensaje saliente del nodo de reglas se envía a los siguientes nodos conectados. Figura 3-9. Cadena de reglas El motor de reglas de ThingsBoard es un marco altamente personalizable. Algunos casos de uso comunes que se pueden configurar a través de las cadenas de reglas son: • Validar y modificar datos para la telemetría o los atributos antes de guardarlos en la base de datos. • Copiar la telemetría o los atributos de los dispositivos a los activos relacionados para que pueda agregar telemetría. • Crear / actualizar / borrar alarmas según las condiciones definidas. • Activar acciones basadas en eventos del ciclo de vida del dispositivo. • Cargar los datos adicionales necesarios para el procesamiento. • Activar llamadas a la API REST a sistemas externos. • Enviar correos electrónicos cuando ocurra un evento. • Tener en cuenta las preferencias del usuario durante el procesamiento del evento. 3.2.4.1 Mensaje El mensaje del motor de reglas es una estructura de datos que puede representar varios mensajes en el sistema. Contiene la siguiente información: • Id del mensaje: Identificador único universal basado en el tiempo. • Originador del mensaje: Entidad que produce el mensaje (Dispositivo, Activo u otra entidad). 13 • Tipo de mensaje: Característica del mensaje que representa la acción de este. • Carga útil del mensaje: Cuerpo JSON con carga útil real del mensaje. • Metadatos: lista de pares clave-valor con datos adicionales sobre el mensaje. Los diferentes tipos de los mensajes se muestran en la siguiente tabla: Tabla 3-1. Tipos de mensajes Tipo de Mensaje Nombre mostrado Descripción POST_ATTRIBUTES_REQUEST Atributos de publicación Solicitud del dispositivo para publicar atributos del lado del cliente POST_TELEMETRY_REQUEST Publicar telemetría Solicitud del dispositivo para publicar telemetría TO_SERVER_RPC_REQUEST Solicitud de RPC desde el dispositivo Solicitud de RPC desde el dispositivo RPC_CALL_FROM_SERVER_TO_DEVICE Solicitud de RPC al dispositivo Solicitud de RPC del servidor al dispositivo ACTIVITY_EVENT Evento de actividad Evento que indica que el dispositivo se activa INACTIVITY_EVENT Evento de inactividad Evento que indica que el dispositivo se vuelve inactivo CONNECT_EVENT Conectar evento Evento producido cuando el dispositivo está conectado DISCONNECT_EVENT Desconectar evento Evento producido cuando se desconecta el dispositivo ENTITY_CREATED Entidad creada Evento producido cuando se creó una nueva entidad en el sistema ENTITY_UPDATED Entidad actualizada Evento producido cuando se actualizó la entidad existente ENTITY_DELETED Entidad eliminada Evento producido cuando se eliminó la entidad existente ENTITY_ASSIGNED Entidad asignada Evento producido cuando la entidad existente fue asignada al cliente ENTITY_UNASSIGNED Entidad sin asignar Evento producido cuando la entidad existente no se asignó al cliente ADDED_TO_ENTITY_GROUP Agregado al grupo Evento producido cuando la entidad se agregó al Grupo de entidades REMOVED_FROM_ENTITY_GROUP Eliminado del grupo Evento producido cuando la entidad se eliminó del Grupo de entidades ATTRIBUTES_UPDATED Atributos actualizados Evento producido cuando se realizó la actualización de los atributos de la entidad ATTRIBUTES_DELETED Atributos eliminados Evento producido cuando se eliminaron algunos de los atributos de la entidad ALARM Evento de alarma Evento producido cuando se creó, actualizó o eliminó una alarma 3.2.4.2 Nodo de regla El nodo de regla es un componente básico que procesa un solo mensaje entrante a la vez y produce uno o más 14 mensajes de salida. Es una unidad lógica básica que puede filtrar, transformar o añadir mensajes entrantes, realizar acciones o comunicarse con sistemas externos. Pueden estar relacionados con otros nodos de reglas. Cada relación tiene un tipo, una etiqueta que se usa para identificar el significado lógico de la relación. Cuando el nodo de reglas produce el mensaje saliente, siempre se especifica el tipo de relación que se usa para enrutar el mensaje a los siguientes nodos. Las relaciones típicas de los nodos son “Éxito” y “Fallo”. Los nodos de reglas que representan operaciones lógicas utilizan “Verdadero” o “Falso”. Algunos nodos de reglas específicos pueden usar tipos de relación más complejos. Los diferentes nodos de reglas se agrupan de acuerdo con su naturaleza: • Los nodos de filtro: se utilizan para el filtrado y enrutamiento de mensajes. • Los nodos de enriquecimiento: se utilizan para cambiar campos de mensajes como el originador, tipo, carga útil, metadatos. • Los nodos de acción: ejecutan acciones basados en el mensaje entrante. • Los nodos externos: se utilizan para interactuar con sistemas externos. 3.2.4.3 Cadena de reglas La cadena de reglas es un grupo lógico de nodos de reglas y sus relaciones. El tenant administrador puede definir una cadena de reglas raíz y, opcionalmente varias cadenas de reglas adicionales. La cadena de regla raíz maneja todos los mensajes entrantes y puede reenviarlas a otras cadenas para procesamiento adicional. Las otras cadenas también pueden reenviar mensajes. Figura 3-10. Cadena de reglas Hay tres posibles resultados del procesamiento de mensajes en una cadena de reglas: éxito, error y tiempo de espera. El intento de procesamiento de mensajes sale como “Éxito” si el nodo ha procesado correctamente el mensaje. Si no lo ha procesado correctamente se produce un “Error” y no hay nodo para manejar este error. Si el procesamiento sobrepasa un cierto umbral configurable. 3.2.5 Dashboards ThingsBoard brinda la capacidad de crear y administrar cuadros de mando, estos cuadros de mando posibilitan al usuario mostrar de manera eficaz y visual las diferentes entidades y los datos asociados a estos. Los diferentes paneles se asignan a los diferentes clientes. Para crear un panel, el usuario puede añadir diferentes tipos de widgets de distintos tipos que muestran los diferentes datos asociados a las entidades que se quieran mostrar. Además, es posible exportar un tablero o un widget específico como un archivo de configuración en formato JSON. Puede utilizar este archivo para transferir la configuración de su panel o widget a otra instancia. 15 Figura 3-11. Dashboard Para determinar que entidades se muestran en el panel, ThingsBoard configura diferentes alias que sirven como una referencia a las entidades que se pueden mostrar. Estos alias pueden ser estáticas o dinámicas. Un ejemplo de alias estático es el alias de entidad única. Una entidad se configura una vez en el cuadro de diálogo de alias. Todos los usuarios ven los mismos datos si tienen permiso para acceder a este dispositivo. Un ejemplo de un alias dinámico es el alias de tipo de dispositivo, que muestra todos los dispositivos de un tipo determinado. Este alias es dinámico porque la lista de dispositivos depende del usuario que usa el panel. Si ha iniciado sesión como tenant administrador, este alias se resolverá en todos los dispositivos de ese tipo. Sin embargo, si ha iniciado sesión como usuario del Cliente, este alias se resolverá en los dispositivos que sean asignados/sean propiedad de ese Cliente. 3.2.5.1 Widgets Todos los paneles se construyen utilizando widgets de ThingsBoard que se muestran en la biblioteca. Cada widget proporciona diferentes funciones para el usuario final, como visualización de datos, control remoto de dispositivos, gestión de alarmas y visualización de contenido. Hay cinco tipos de widgets: • Los widgets de timeseries muestran datos para una ventana de tiempo específica. La ventana de tiempo puede ser en tiempo real (por ejemplo, durante las últimas 24 horas) o histórica (diciembre de 2020). • Los widgets de valores más recientes muestran los valores más recientes de un atributo particular o claves de timeseries. • Los widgets de control le permiten enviar comandos RPC a sus dispositivos. • Los widgets de alarma le permiten mostrar alarmas. • Los widgets estáticos están diseñados para mostrar datos estáticos. 16 Figura 3-12. Biblioteca de Widgets 3.2.6 API REST La API REST de ThingsBoard se puede explorar mediante la interfaz de usuario de Swagger. Puede explorar la API REST del servidor usando la siguiente URL: http://207.180.221.115:8080/swagger-ui.html#/, que es la dirección IP proporcionada por el profesor. 17 Figura 3-13. API REST de ThingsBoard ThingsBoard utiliza JWT para la autenticación de solicitudes. Para que las solicitudes a la API sean correctas deberemos completar el encabezado "X-Authoritation". Para solicitar el código JWT debemos solicitar las credenciales mediante la API. API login: http://THINGSBOARD_URL/api/auth/login' Donde THINGSBOARD_URL es la dirección IP dada por el profesor 207.180.221.115:8080. Para recibir el token JWT, tenemos que añadir a la API mencionada los datos del email del usuario y la contraseña correspondiente. Recibiremos un JSON con el token correspondiente que añadiremos a las posteriores solicitudes para autorizar la solicitud. 3.2.6.1 Atributos Una vez que ya estamos autorizados, podemos solicitar o cambiar los atributos de las distintas entidades mediante las distintas APIs: API Atributos del servidor: http://207.180.221.115:8080/api/plugins/telemetry/$ENTITY_TYPE/$ENTIT Y_ID/SERVER_SCOPE API Atributos compartidos: 24 Figura 4-7. Creación de la pila Para que todo funcione, NavigationContainer es un componente que administra nuestro árbol de navegación y contiene el estado de navegación. Este componente debe envolver la estructura de todos los navegadores. Figura 4-8. Estructura de la navegación de App.js Una vez que iniciamos sesión, vamos al menú de la aplicación. Como este elemento es otro navegador diferente, para poder llegar desde App.js a AppMenu.js anidamos el navegador del menú dentro de la pila de App.js. Para ello simplemente añadimos en el atributo “component” del navegador principal al navegador secundario. Al final, la estructura de navegadores que está siguiendo la aplicación es la siguiente: • Stack.Navigator o Login (Screen Principal) o Register (Screen) o Menu (Screen) ▪ FirstUser ▪ CounterRegister ▪ Profile ▪ Configuration ▪ ConfigurationInform ▪ ConfigurationUser ▪ Inform ▪ Counter Esta navegación permite que se pueda seguir la aplicación de forma fluida y ordenada, de modo que la pila pueda rellenarse por orden y permitir la navegación entre pantallas. 25 4.2.2 Componentes de React Native Dentro de los ficheros de la aplicación utilizamos distintos componentes que aportan la estructura de la aplicación, es decir, los elementos que nos ayudan a que la aplicación se utilice correctamente. Cada componente realiza una acción característica sobre la aplicación general. [7] Los distintos componentes que se añaden en esta aplicación son las siguientes: 4.2.2.1 BarChart Este componente se utiliza para generar un gráfico de barras. Para ello tenemos que añadir a nuestro proyecto el módulo correspondiente a este componente, que sería el componente “react-native-svg-charts”. [8] Para instalarlo ponemos dentro del cuadro de mando del proyecto: Paquete de react-native-svg-charts: expo install react-native-svg-charts Una vez instalado el paquete tenemos que importar los elementos correspondientes al gráfico de barras que es el que vamos a utilizar en esta aplicación. Para ello utilizamos la siguiente línea: Figura 4-9. Importar el componente BarChart Una vez importado, podemos utilizarlo. Para ello incorporamos el elemento BarChart a nuestra aplicación. Figura 4-10. Componente BarChart Dentro del componente hay un par de atributos que hay que aclarar. El atributo spacingInner nos permite manejar el espacio entre las barras mientras que el atributo contentInset nos permite manejar el posicionamiento del gráfico dentro del componente. El atributo contentInset indica la cantidad de inserción del contenido desde los bordes. Además, podemos añadir al gráfico el número de datos distintos que queramos, que en nuestro caso nos permite aplicar una comparativa de barras del mismo contador en diferentes momentos. Para poder decorar el gráfico hemos añadido a la izquierda de este el elemento YAxis, que es un componente auxiliar para diseñar las etiquetas del eje Y en las mismas coordenadas que su gráfico. Es muy importante que el componente tenga exactamente los mismos límites del gráfico si no el eje y estará descuadrado con los elementos del gráfico de barras. 26 Figura 4-11. Componente YAxis 4.2.2.2 Image Componente de React para mostrar diferentes tipos de imágenes, incluidas imágenes de red, recursos estáticos, imágenes locales temporales e imágenes del disco local, como el carrete de la cámara. En nuestro caso, utilizamos este componente para manejar las diferentes imágenes que tendrá la aplicación, todas las imágenes se encuentran guardadas en la carpeta Images dentro del directorio assests, donde se guardan los diferentes activos dentro de la aplicación. Figura 4-12. Componente Image Esto se logra mediante la propiedad del componente source, que puede buscar elementos tanto en local como en remoto, es decir, aplicando URL. 4.2.2.3 KeyboardAwareScrollView Este componente se utiliza para controlar la apariencia del teclado y se desplaza automáticamente hasta enfocar la pantalla en el TextInput que estamos centrados. Para ello tenemos que añadir a nuestro proyecto el módulo correspondiente a este componente, que sería el componente “react-native-keyboard-aware-scroll- view”. [9] Para instalarlo ponemos dentro del cuadro de mando del proyecto: Paquete de react-native-keyboard-aware-scroll-view: expo install react-native-keyboard-aware-scroll-view Una vez instalado el paquete tenemos que importar el componente que vamos a utilizar en esta aplicación. Para ello utilizamos la siguiente línea: Figura 4-13. Importar el componente KeyboardAwareScrollView Una vez importado, añadimos el elemento a la pantalla correspondiente. Nos aseguramos de que todos los elementos de la pantalla se encuentran recogidos dentro del componente para que funcione. Además, este componente funciona como un View y, por lo tanto, no puede tener un View inmediatamente antes del componente. 27 Figura 4-14. Componente KeyboardAwareScrollView Normalmente, este componente se ocupará solo de manejar el contenido insertado. Si desea que KeyboardAwareScrollView se desplace automáticamente a un TextInput que obtiene el foco (por lo que se asegura que sea visible), puede agregar un atributo llamado getTextInputRefs: una devolución de llamada en la que puede devolver una matriz de referencias a los componentes TextInput que se desplazan automáticamente para ser manejado. KeyboardAwareScrollView buscará el TextInput enfocado en la matriz y se asegurará de que sea visible desplazándose hasta su ubicación. 4.2.2.4 MaterialCommunityIcons Este componente se utiliza para añadir iconos que se utilizan para mostrar elementos y es perfecto para botones, logotipos y barras de navegación/pestañas. Para ello tenemos que añadir a nuestro proyecto el módulo correspondiente a este componente, que sería el componente “@expo/vectors-icons” [10]. Para instalarlo ponemos dentro del cuadro de mando del proyecto: Paquete de @expo/vectors-icons: expo install @expo/vectors-icons Una vez instalado el paquete tenemos que importar el componente que vamos a utilizar en esta aplicación. Para ello utilizamos la siguiente línea: Figura 4-15. Importar MaterialComunityIcons Una vez importado, añadimos el elemento a la pantalla correspondiente. En nuestro caso, el elemento que vamos a añadir es el ojo que se añaden en las contraseñas. De modo que cuando pulsen, se cambie al icono de un ojo tachado permitiendo que la contraseña se visualice. 28 Figura 4-16. Componente Icon Para manejar el estado del ojo en cada momento, utilizamos la función useSate() de React Native, permitiendo de manera sencilla implementar los iconos a instalar. Figura 4-17. Variable del icono Una vez realizado la aplicación, cuando pulsamos el icono, tenemos que cambiar la variable “eye” al valor de la variable con el ojo tachado, de modo que se cambia el icono. Figura 4-18. Cambio de icono 4.2.2.5 RadioButtonRN Este componente se utiliza para añadir un botón de radio animado. Para ello tenemos que añadir a nuestro proyecto el módulo correspondiente a este componente, que sería el componente “radio-buttons-react-native” [11]. Para instalarlo ponemos dentro del cuadro de mando del proyecto: Paquete de radio-buttons-react-native: expo install radio-buttons-react-native Una vez instalado el paquete tenemos que importar el componente que vamos a utilizar en esta aplicación. Para ello utilizamos la siguiente línea: Figura 4-19. Importar RadioButtonRN Una vez importado, añadimos el elemento a la pantalla correspondiente. Figura 4-20. Componente RadioButtonRN Este componente nos permitirá seleccionar el nivel de agua máximo que se consumirá sin que salte una alerta en la aplicación. 29 4.2.2.6 ScrollView Componente que envuelve la plataforma al tiempo que proporciona integración con el sistema de "respuesta" de bloqueo táctil. Hay que tener en cuenta que ScrollView debe tener una altura limitada para funcionar. El ScrollView es un contenedor de desplazamiento genérico que puede contener varios componentes y puntos de vista. Los elementos desplazables pueden ser heterogéneos y puede desplazarse tanto vertical como horizontalmente. Figura 4-21. Componente ScrollView En la aplicación nos sirve para mostrar la tabla de alertas, ya que la tabla es muy grande para la pantalla, este componente nos permite mostrar los datos sin que se tenga que empequeñecer la tabla para que quepa en la pantalla. 4.2.2.7 StatusBar Componente para controlar la barra de estado de la aplicación. Nos permite guardar el espacio de la barra de notificaciones y que la aplicación no se solape con la misma. Figura 4-22. Componente StatusBar En la aplicación usamos el atributo backgroundColor para que la barra de estado sea del dispositivo móvil poniéndolo transparente. 4.2.2.8 Svg Este componente se utiliza para generar un gráfico de donut. Para ello tenemos que añadir a nuestro proyecto el módulo correspondiente a este componente, que sería el componente “react-native-svg” [12]. Para instalarlo ponemos dentro del cuadro de mando del proyecto: Paquete de react-native-svg: expo install react-native-svg Este componente genera elementos gráficos básicos como círculos y elementos primitivos que en conjunto podemos crear elementos gráficos complejos (en nuestro caso la gráfica donut.) Una vez instalado el paquete tenemos que importar los elementos correspondientes al gráfico que es el que 30 vamos a utilizar en esta aplicación. Para ello utilizamos la siguiente línea: Figura 4-23. Importar el componente Svg Una vez importado, podemos utilizarlo. Para ello incorporamos el elemento BarChart a nuestra aplicación. Figura 4-24. Componente Svg Para crear el donut, dentro de la gráfica tenemos que añadir los componentes Circle para que tenga la forma de círculos. Una vez creado el donut, lo animamos con el componente Animated para que le dé la forma de gráfica. Además, podemos añadir al gráfico el número de datos distintos que queramos, que en nuestro caso nos permite darle la suma del contador para los diferentes días. 4.2.2.9 Switch Muestra una entrada booleana. Este es un componente controlado que requiere una devolución de llamada que actualice el accesorio value para que el componente refleje las acciones del usuario. Si el accesorio value no se actualiza, el componente seguirá representando el accesorio value proporcionado en lugar del resultado esperado de las acciones del usuario. En la aplicación utilizamos este componente para que muestre los distintos botones de comparativa, si es que queremos comparar los datos. Si el Switch se encuentra apagado, la gráfica mostrada no tendrá la comparativa de los datos del contador. Si se encuentra encendido podemos ver como las gráficas realizan una comparativa. Figura 4-25. Componente Switch Para que se muestren los botones, hemos utilizados dos variables de estado que indican si el switch se encuentra activo y si los botones están escondidos. De este modo cuando activamos el componente, los 31 botones se muestran y si se desactiva, se vuelven a esconder. Figura 4-26. Activación del Switch 4.2.2.10 Table Este componente se utiliza para generar una tabla. Para ello tenemos que añadir a nuestro proyecto el módulo correspondiente a este componente, que sería el componente “react-native-table-component”. [13] Para instalarlo ponemos dentro del cuadro de mando del proyecto: Paquete de react-native-table-component: expo install react-native-table-component Una vez instalado el paquete tenemos que importar los elementos correspondientes a la tabla que vamos a utilizar en esta aplicación. Para ello utilizamos la siguiente línea: Figura 4-27. Importar el componente Table Una vez importado, podemos utilizarlo. Para ello incorporamos el elemento Table a nuestra aplicación para generar la estructura de la tabla, para añadir elementos a la tabla, utilizamos el componente Row que nos permite crear filas de elementos. 32 Figura 4-28. Componente Table En nuestra aplicación, tenemos una primera tabla que contiene la cabecera de esta. A continuación, generamos otra tabla que contiene las alarmas que va generando la aplicación. Los elementos de esta segunda tabla son dinámicos y se añaden a medida que se van generando alarmas. 4.2.2.11 Text Un componente de React para mostrar texto. En la aplicación lo usamos para manejar los diferentes strings que se desarrollan en el fichero “strings.js” del directorio “config”. Figura 4-29. Componente Text 4.2.2.12 TextInput Un componente fundamental para ingresar texto en la aplicación a través de un teclado. Los accesorios brindan capacidad de configuración para varias funciones, como autocorrección, uso automático de mayúsculas, texto de marcador de posición y diferentes tipos de teclado, como un teclado numérico. El caso de uso más básico es dejar caer un TextInput y suscribirse a los eventos onChangeText para leer la entrada del usuario. También hay otros eventos, como onSubmitEditing y a los onFocus que se puede suscribir. 33 Figura 4-30. Component TextInput En la aplicación usamos este componente para realizar los formularios tanto de registro del usuario y del contador como para iniciar sesión de la aplicación. Uno de los atributos que se utilizan es el de secureTextEntry, que se utiliza para ocultar el texto en la entrada de las contraseñas. 4.2.2.13 TouchableOpacity Un envoltorio para hacer que las vistas respondan correctamente a los toques. Al presionar hacia abajo, la opacidad de la vista envuelta se reduce, atenuándola. La opacidad se controla envolviendo a los hijos en un Animated.View, que se agrega a la jerarquía de vistas. En la aplicación sirve para saber si hemos pulsado un botón. Una vez que se utiliza, todos los elementos que contienen se verán afectados al pulsarlo, por lo que sirve para crear botones con varios elementos (imágenes, texto…). Figura 4-31. Componente TouchableOpacity 4.2.2.14 View El componente más fundamental para crear una interfaz de usuario. View está diseñado para anidarse dentro de otras vistas y puede tener otros componentes en su interior. En la aplicación, hemos usado este elemento para poder separar la aplicación en contenedores y que a cada uno le apliquemos un estilo diferente 40 El parámetro deviceToken nos permite acceder al contador mediante su token de acceso y de ahí obtener los valores mediante los parámetros opcionales clientKeys y sharedKeys, que pasando el nombre del atributo podemos buscar su valor. • /api/plugins/telemetry/{entityType}/{entityId}/{scope}{?keys} Método POST donde le pasamos como parámetro un objeto con los distintos atributos que queremos añadir al dispositivo. Los parámetros entityType y entityId nos permite identificar el contador al que le añadiremos los atributos y el parámetro scope identifica a qué lado del dispositivo le añadiremos los atributos. Esta API permite tanto cambiar atributos existentes identificándolo por el parámetro keys como añadir nuevos atributos en la parte que se desea del contador. • /api/plugins/telemetry/{entityType}/{entityId}/values/timeseries{?agg,keys,starTs,endTs} Método GET que devuelve una cadena de objetos donde vienen los datos históricos de las telemetrías del dispositivo. En la aplicación se utiliza para obtener los datos del agua del contador hasta un máximo de un mes de retroceso. Los parámetros admitidos son los siguientes. El parámetro keys muestra la lista separada por comas de claves de telemetría para recuperar. StartTs marca de tiempo de Unix que identifica el inicio del intervalo en milisegundos. EndTs marca de tiempo de Unix que identifica el final del intervalo en milisegundos. El intervalo indica el intervalo de agregación, en milisegundos. Agg es la función de agregación. Puede ser no de MIN, MAX, AVG, SUM, COUNT, NONE. Por último, el límite indica la cantidad máxima de puntos de datos para devolver o intervalos para procesar. 4.2.3.2.5 Controlador del dispositivo En estas APIs vamos a realizar todas las peticiones relativas a los dispositivos creados por el usuario. En la aplicación las utilizamos para crear o cambiar los dispositivos asociados a cada usuario. También obtenemos las credenciales asociadas al dispositivo creado debido para que se puedan realizar diversas acciones sobre el mismo. Dentro de este controlador utilizamos las siguientes APIs: • /api/device/{deviceId}/credentials: Método GET que devuelve un objeto JSON donde viene las credenciales asociadas a un dispositivo. Lo usamos para obtener el token de acceso al contador del usuario para que después podamos utilizarlo para encontrar los atributos. El parámetro deviceId nos permite identificar un único contador por su id y así obtener sus credenciales. • /api/device{?accessToken,entityGroupId}: Método POST donde le pasamos como parámetro device un objeto JSON y te crea el dispositivo asociado al usuario. Si la petición es correcta, te devuelve un objeto con los datos generados al crear el dispositivo. Si al pasar el objeto device le pasamos un objeto con la misma id que un dispositivo creado, el dispositivo se actualiza al que se le ha pasado. Esto es útil a la hora de cambiar el nombre del contador que queremos implementar sin que se borren los datos asociados al mismo. Si el elemento ya se encuentra creado da un mensaje de error 401 diciendo que el título ya se encuentra en uso. El resto de los parámetros son opcionales. • /api/user/devices{?type,textSearch,idOffset,textOffset,limit}: Método GET que devuelve una cadena de objetos donde vienen los dispositivos que tiene el usuario. Lo usamos para obtener los datos del contador que el usuario tiene registrado. Si no tiene ninguno, el API devuelve una cadena vacía. El parámetro limit es obligatorio e indica el número máximo de dispositivos que queremos buscar. Como cada usuario tiene un dispositivo. El límite es de un contador. El resto de los parámetros son opcionales y sirven para buscar con mayor precisión el dispositivo a 41 buscar. 4.2.3.2.6 Controlador de grupos de entidades En estas APIs vamos a realizar todas las peticiones relativas a los grupos de entidades creadas en el servidor. En la aplicación las utilizamos para obtener los distintos grupos de entidades y así coger las identificaciones para que posteriormente se puedan añadir usuarios en ellas. Dentro de este controlador utilizamos las siguientes APIs: • /api/entityGroup/{ownerType}/{ownerId}/{groupType}/{groupName}: Método GET que devuelve una cadena de objetos donde vienen los distintos grupos que se encuentran en el dueño de esos grupos. En nuestro caso, lo utilizamos para obtener el id del grupo Customer- Administrator y así poder meter en él el usuario que se asocie con el cliente. Todos los parámetros son obligatorios. Los parámetros ownerType y ownerId sirven para identificar al cliente dueño del grupo. Los parámetros groupType y groupName sirven para identificar el grupo del cual queremos coger las credenciales. 4.2.3.2.7 Controlador de la cadena de reglas En estas APIs vamos a realizar todas las peticiones relativas a las cadenas de reglas que se van a crear en el servidor de ThingsBoard. En la aplicación, manejamos una cadena de reglas que permite generar alarmas si el contador se mide más agua consumida que en el nivel marcado. También modificamos la regla raíz para que cuando termine de guardar la medida, acceda a la cadena de alarmas. Dentro de este controlador utilizamos las siguientes APIs: • /api/ruleChain: Método POST donde le pasamos al parámetro ruleChain un objeto JSON y te crea en el servidor la cadena de reglas. También crea una cadena nueva con los datos establecidos para generar la alarma del contador. Si el elemento ya se encuentra creado da un mensaje de error 401 diciendo que el título ya se encuentra en uso. • /api/ruleChain/metadata: Método POST donde le pasamos al parámetro ruleChainMetadata un objeto JSON donde le metemos las conexiones de la cadena de reglas, los nodos que se encuentran en ellas y las conexiones con las demás cadenas de reglas, es decir, llenamos la cadena de reglas con datos y nodos para que ejecute su función. Nos sirve tanto para actualizar la cadena de la alarma del contador como para cambiar el nivel de la alarma como en la cadena raíz para añadir el acceso a la cadena de la alarma. Si la petición es correcta te devuelve la nueva cadena de reglas que se ha implementado. • /api/ruleChains{?textSearch,idOffset,textOffset,limit}: Método GET que devuelve una cadena de objetos donde vienen las cadenas de reglas que se encuentran en el servidor. En nuestro caso, lo utilizamos para obtener los id de las cadenas raíz y la alarma correspondiente a nuestro contador. Esto lo logramos mediante el parámetro opcional textSearch que busca dentro de la cadena de objetos un objeto con el mismo nombre que el parámetro. El resto de los parámetros también son opcionales. • /api/ruleChain/{ruleChainId}/metadata: Método GET que devuelve una cadena de objetos donde vienen los datos de las cadenas de reglas que se encuentran en el servidor. Sirve para que la aplicación pueda actualizar las diferentes cadenas de reglas al cambiar los datos devueltos en esta petición. El parámetro ruleChainId nos permite escoger la cadena de reglas de la que queremos obtener los datos, para así poder añadir nodos o cambiar datos y descartar el resto de las cadenas de reglas. 42 4.2.3.2.8 Controlador de usuario En estas APIs vamos a realizar todas las peticiones relativas a las distintas acciones que se va a realizar con respecto al usuario, en nuestro caso sería la creación del usuario, obtener los usuarios que se han creado en el servidor y la obtención de los datos relativos a un usuario. Dentro de este controlador utilizamos las siguientes APIs: • /api/customer/{customerId}/users{?textSearch,idOffset,textOffset,limit}: Método GET que devuelve una cadena de objetos donde vienen los usuarios que tiene el cliente. Lo usamos para obtener el id del usuario asociado a ese cliente mediante su email. Si no tiene ninguno, el API devuelve una cadena vacía. El parámetro limit es obligatorio e indica el número máximo de usuarios que queremos buscar. Como cada cliente tiene un usuario. El límite es de uno. El resto de los parámetros son opcionales y sirven para buscar con mayor precisión el usuario a buscar • /api/user/users{?textSearch,idOffset,textOffset,limit}: Método GET que devuelve una cadena de objetos donde vienen los usuarios que tiene el cliente. Lo usamos para obtener los datos del usuario. Si no tiene ninguno, el API devuelve una cadena vacía. Esto lo logramos mediante el parámetro opcional textSearch que busca dentro de la cadena de objetos un objeto con el mismo email que el parámetro. El resto de los parámetros también son opcionales. El parámetro limit es obligatorio e indica el número máximo de usuarios que queremos buscar. Como cada cliente tiene un usuario. El límite es de uno. El parámetro customerId sirve para identificar el cliente por su identificación única. El resto de los parámetros son opcionales y sirven para buscar con mayor precisión el usuario a buscar. • /api/user/{userId}/activationLink: Método GET que devuelve un string que contiene el link para activar la cuenta del usuario. El parámetro userId nos sirve para identificar el usuario que queremos activar. De este link sacamos el token de activación que luego usaremos para activar la cuenta. • /api/user{?sendActivationMail,entityGroupId}: Método POST donde le pasamos como parámetro user un objeto JSON y te crea el usuario. Si la petición es correcta, te devuelve un objeto con los datos generados al crear el usuario. Si al pasar el objeto user le pasamos un objeto con la misma id que un usuario creado, el usuario se actualiza al que se le ha pasado. Esto es útil a la hora de cambiar los datos del usuario que queremos implementar sin que se borren los datos asociados al mismo. El parámetro semActivationMail lo ponemos como falso ya que queremos que la aplicación active la cuenta sin que tenga el usuario de activarlo por correo. El parámetro entityGroupId sirve para identificar el grupo donde queremos meter el usuario. Además, para que el usuario se asocie con el cliente, tenemos que darle la autoridad al usuario como “CUSTOMER_USER” y luego asociarlo con el cliente que se ha creado anteriormente. Si el elemento ya se encuentra creado da un mensaje de error 401 diciendo que el título ya se encuentra en uso. El resto de los parámetros son opcionales. 4.3 ThingsBoard Hasta ahora hemos visto que elementos en el lado de la aplicación se han utilizado hasta ahora. Sin embargo, como ya hemos en el apartado 3. La aplicación se conecta con la plataforma ThingsBoard, pero no utiliza todos los elementos de esta ya que es una plataforma que sirve para múltiples dispositivos inteligentes. 43 Para acceder a la plataforma, la aplicación realiza una petición a la URL http://207.180.221.115:8080. Si accedemos a esta URL mediante el navegador llegaremos a la plataforma de ThingsBoard donde, tras meter el usuario y la contraseña, accederemos a nuestro panel de control de esta. Figura 4-43. Panel de control de ThingsBoard Por lo tanto, en este apartado veremos qué aspectos de la plataforma son las que la aplicación maneja, de forma que miramos como lo trabaja y cuál es el resultado final de esta. Para ello, hemos dividido este apartado en los diferentes aspectos que tiene la plataforma a la que accede la aplicación. 4.3.1 Cadenas de reglas Una vez que se ha creado el dispositivo, la aplicación crea una cadena de reglas que genera una alarma cada vez que se sobrepasa cierto nivel de agua. Una vez creado la alarma, esta aparece en el apartado de cadenas de reglas de la plataforma. Para que la identificación de la alarma sea más sencilla, a la cadena se la nombra de “Alarm” seguida del nombre del contador de modo que queda una lista de alarmas con todos los contadores creados. 44 Figura 4-44. Grupo de cadenas de reglas creadas Si accedemos a la cadena de reglas de una alarma veremos el flujo que sigue la cadena de esta. Una vez que el mensaje entra, vemos que el primer nodo comprueba si es el contador correcto, esto sirve para identificar si es el contador correcto el que envía la telemetría. Figura 4-45. Comprobación del dispositivo Si es el contador, comprueba si la cantidad de agua es superior a la indicada. Si no lo supera, se limpia la alarma y se acaba la cadena. 45 Figura 4-46. Comprobación del nivel Sin embargo, si la cantidad supera el nivel, se crea un script con los datos y se crea la alarma. Una vez creada la alarma creamos el email a enviar al usuario y lo enviamos. Figura 4-47. Creación del email 46 Figura 4-48. Cadena de reglas de la alarma. Sin embargo, se accede a esta cadena de reglas mediante la cadena de reglas raíz, que es el que maneja la entrada y desde esta cadena se accede a la cadena de reglas correspondiente. Por lo tanto, tenemos que añadir a la cadena raíz el acceso a la cadena alarma para que le pueda pasar el mensaje. Esto la aplicación lo realiza añadiendo un nodo de cadena de reglas a la cadena raíz. Figura 4-49. Cadena de reglas raíz. 4.3.2 Jerarquía de clientes Para que la aplicación funcione, crea un cliente por cada persona que se registra. Cuando se ha creado el cliente, la aplicación asigna un usuario al cliente y le autoriza. Luego asigna a este usuario un dispositivo que es de tipo “wáter-meter” y al que le añade una serie de atributos. Cuando accedemos al apartado de jerarquía de clientes, este despliega todos los clientes que se han creado en el servidor de modo que tenemos un panel al que acceder a todos los apartados de los distintos clientes. 47 Figura 4-50. Jerarquía de clientes Una vez que accedemos a los grupos de usuarios asignados a cada cliente podemos ver los grupos de los usuarios, para que el usuario pueda manejar los datos de los dispositivos, la aplicación lo asignó al grupo de Customers Administratos, que tiene la mayoría de los permisos. En este grupo se encuentran todos los usuarios asignados al cliente que la aplicación ha creado. Estos usuarios se identifican por el email, el nombre y los apellidos. Figura 4-51. Usuario del cliente 48 Una vez que se ha creado el usuario, la aplicación es la que gestiona la activación de la cuenta, por lo que no necesita que el usuario active la cuenta en el servidor de ThingsBoard. Si accedemos a la cuenta del usuario, vemos que tiene menos elementos que el administrador, ya que goza de menos privilegios y permisos. Figura 4-52. Cuenta de usuario activado 4.3.3 Dispositivos Una vez que se ha creado el usuario, la aplicación crea el contador en la cuenta de este. Para comprobarlo accedemos al apartado de grupo de dispositivos donde en el grupo de todos podemos observar el dispositivo creado. 49 Figura 4-53. Contador asignado al usuario El contador, al estar asignado al usuario y este asignado a un cliente, puede ser visto desde la cuenta del administrador en la jerarquía de clientes. Para ello, nos vamos al cliente del cual tenemos el dispositivo y nos vamos al grupo de dispositivos que maneja, donde podemos observar el dispositivo. Figura 4-54. Grupo de dispositivos del cliente. 56 Figura 4-67. Mensaje de error Si se ha realizado la creación de un contador correctamente, la aplicación vuelve a la pantalla de menú con una notificación indicando que el dispositivo se ha creado correctamente. Figura 4-68. Dispositivo creado correctamente Una vez que el dispositivo ha sido creado, en el apartado de perfil podemos ver una pantalla con los datos de tanto del usuario como del contador. Además, se observa un botón para salir de la aplicación que nos permite volver a la pantalla de inicio de sesión saliendo de nuestra cuenta. 57 Figura 4-69. Pantalla de perfil En el apartado de Contador podemos observar tres gráficas. En la primera aparece la suma de la cantidad de agua que se ha consumido por litros en durante una semana. En la segunda, aparece la cantidad de agua que se ha consumido en un mes. Por último, en la tercera se observa la cantidad de agua que se ha consumido en el día hasta el momento. Figura 4-70. Pantalla del contador Debajo de estas gráficas, aparece un botón que sirve para cortar o activar el agua. Esto se realiza cambiando el atributo Active en el lado servidor del dispositivo en el servidor ThingsBoard. Este cambio se produce a la vez de una notificación indicando la acción realizada. 58 Figura 4-71. Corte o Activación del agua En el menú, cuando accedemos a la pantalla de informes mediante el botón correspondiente, aparece la pantalla que muestra una gráfica de barras indicando el consumo de los últimos 7 días. Debajo de la gráfica nos muestran dos botones que se utilizan para cambiar entre la gráfica de barras a la tabla de alarmas y un switch que nos permite aplicar comparativas, que si se activa nos muestran las opciones de aplicar una comparativa visual de los datos de esta semana con los datos de la semana anterior o con respecto hace una quincena. Figura 4-72. Distintas gráficas de barras Si activamos el botón de alarmas, aparecerá una tabla con las alarmas que se han activado al consumir el agua. Como la tabla es muy grande para la pantalla del dispositivo móvil, se puede realizar un scroll horizontal para ver todos los datos. La alarma también se notifica por correo. 59 Figura 4-73. Tabla de alarmas y el correo En el apartado de configuración tenemos dos botones para poder configurar dos elementos fundamentales. El primero accede a la configuración de los informes de consumo, es decir, sirve para configurar el nivel en el que el contador genera una alarma. El segundo caso tiene la configuración tanto del usuario como del contador asociado a él. 60 Figura 4-74. Pantallas de configuración En la pantalla de configuración del informe tenemos dos opciones: o aplicamos el nivel por defecto o aplicamos el nivel personalizado, permitiendo poner la cantidad de litros máximo por el que la aplicación genera una alerta. Al pulsar el botón de configuración, la aplicación cambia el atributo de NivelAlerta por el que establecemos en la aplicación. Cuando cambiamos el nivel, se vuelve a la pantalla del menú con una notificación de que la configuración ha sido modificada. Figura 4-75. Cambio de configuración En el apartado de la configuración del usuario aparece un formulario con los distintos elementos que se pueden modificar tanto del usuario como del contador. Del usuario tenemos el Nombre, los apellidos, el alias y el email. Del contador podemos cambiar la marca el Nombre, la Marca y la Dirección de instalación. En este caso, no hace falta llenar toda la configuración para poder cambiarla, basta con llenar los campos que se quieren modificar para poder realizar el cambio. Solo se produce un mensaje de error si todos los campos se encuentran vacíos, provocando un mensaje de error indicándolo. 61 Figura 4-76. Mensaje de error Si el cambio se ha producido correctamente, se han cambiado los datos puestos en el servidor de ThingsBoard. Luego, se ha vuelto a la pantalla del menú con una notificación que indica que la configuración ha sido modificada. Estos cambios lo podemos ver de nuevo en la pantalla de perfil. Figura 4-77. Cambios del usuario y contador 62 5 GENERACIÓN DE DATOS Ya hemos hablado de los elementos que componen la aplicación, tanto de la parte de React Native como de la parte de ThingsBoard. También hemos hablado del servidor ThingsBoard en sí mismo y como la aplicación es capaz de comunicarse con ella. Por último, hemos visto globalmente la aplicación. Sin embargo, no hemos hablado de como los contadores generan los datos y se los comunican al servidor. Como este proyecto no tiene contadores reales, hemos tenido que simular los efectos que tendría uno sobre la aplicación. Para ello hemos creado códigos que generen datos que simulen una lectura de agua que luego hemos enviado a ThingsBoard para que la aplicación pueda recogerlos. En este apartado vamos a desarrollar los códigos producidos y como estos se han conectado a ThingsBoard. 5.1 Conexión con ThingsBoard Para poder enviar los datos hemos realizados peticiones API a la URL del servidor de ThingsBoard. Estas peticiones se realizan mediante el protocolo HTTP y con ellos hemos enviado los datos necesarios para que la aplicación sea funcional. Cómo el código ha sido realizado en JavaScript, hemos realizado las peticiones mediante fetch. Un elemento que nos permite hacer peticiones HTTP a las diferentes URL junto con las API que se vayan a utilizar. Para instalar este elemento tenemos que realizar: Paquete de fetch: npm install -g node-fetch Una vez instalado, en la aplicación se utiliza aplicando el siguiente procedimiento: Figura 5-1. Incorporar fetch al código Una vez aclarado el método para realizar las peticiones. A continuación, veremos las distintas APIs que se van a utilizar dependiendo del efecto que se tiene en la aplicación la llamada a los mismos. 5.1.1 /api/auth/login Método POST al que le tenemos que pasar como datos el email del usuario y la contraseña de este y que si es correcto nos devuelve un objeto con el token que nos permite autorizar las diferentes acciones de nuestro usuario y autenticarnos. Figura 5-2. Petición a login 63 5.1.2 /api/plugins/telemetry/DEVICE/{deviceId}/values/attributes/SERVER_SCOPE Este método GET nos permite obtener los atributos del Contador del servidor ThingsBoard para así comprobar si se encuentra activo o no. Para ello, le pasamos como parámetros el id del dispositivo que queremos que genere datos y el token obtenido al logearnos por el método anterior. Figura 5-3. Petición al dispositivo Si todo sale correcto, tendrás una cadena con los atributos el cual tendrás que sacar el que corresponda a Active. 5.1.3 /api/v1/{accessToken}/telemetry Es un método POST que genera los datos que queremos entregar. Como parámetros le pasas el token de acceso del dispositivo que genera los datos y de ahí le entregamos un JSON donde le pasamos la variable que se va a generar con el dato producido y opcionalmente, el timeseries con el tiempo en UNIX del momento donde se genera el dato. Figura 5-4. Entrega del dato Si todo es correcto, en el servidor ThingsBoard se habrá actualizado los elementos que se han pasado como variables, en este caso la variable watercounter. 5.2 Códigos del generador de datos Una vez que ya hemos analizado las peticiones que se han producido entre el contador simulado y el servidor ThingsBoard, vamos a proceder con analizar los códigos que se han creado para simular los datos del dispositivo. Hemos creado dos códigos que, aunque son ciertamente parecidos, producen dos efectos diferentes. El primero es un generador de datos del día, este código genera datos desde las 00:00 hasta la hora actual en periodos de una hora. El segundo es un generador de datos mensual, es decir, genera datos diariamente durante 30 días desde hace un mes atrás de la fecha actual. 64 A continuación, desarrollamos ambos códigos. 5.2.1 Generador de datos del día Como se ha dicho anteriormente, este código genera un dato cada hora hasta la hora actual. Para ello, le pasamos al código el token de acceso al dispositivo y el id de este. Una vez que se ejecuta, el código comprueba mediante peticiones API si el dispositivo se encuentra activo. Si el dispositivo no se encuentra activo, el código devuelve por pantalla un mensaje de error. Si el dispositivo se encuentra activo, lo primero que realiza es la obtención del momento actual en tiempo UNIX. Esto se realiza mediante el constructor Date. [16] El constructor Date permite trabajar con fechas y horas. Para hacerlo creamos un objeto fecha y con el método now obtenemos el tiempo actual UNIX en milisegundos. A continuación, calculamos el tiempo de inicio del código obteniendo la fecha actual, cogiendo la fecha y poniéndole las 00:00:00. Mediante el método getTime que devuelve ese tiempo en milisegundos. Por último, enviamos datos aleatorios del dispositivo que se van acumulando a medida que avanza el bucle, que dura desde que empieza hasta la fecha actual añadiendo una hora en milisegundos al tiempo en UNIX 65 Figura 5-5. Código del generatorDaily.js Al ejecutar el código en la pantalla de la consola irán apareciendo los momentos que van generando los datos y el valor de estos en la línea de abajo. Figura 5-6. Ejecución del código