Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo...

161
Equation Chapter 1 Section 1 Proyecto Fin de Carrera Ingeniería de Telecomunicación Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos Autor: Alfredo Enrique Sáez Pérez de la Lastra Tutor: Antonio Jesús Sierra Collado Departamento de Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2016

Transcript of Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo...

Page 1: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Equation Chapter 1 Section 1

Proyecto Fin de Carrera

Ingeniería de Telecomunicación

Desarrollo de aplicación IoMT sobre Raspberry Pi

para monitorización de datos biomédicos

Autor: Alfredo Enrique Sáez Pérez de la Lastra

Tutor: Antonio Jesús Sierra Collado

Departamento de Ingeniería Telemática

Escuela Técnica Superior de Ingeniería

Universidad de Sevilla

Sevilla, 2016

Page 2: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura
Page 3: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Proyecto Fin de Carrera

Ingeniería de Telecomunicación

Desarrollo de aplicación IoMT sobre Raspberry Pi

para monitorización de datos biomédicos

Autor:

Alfredo Enrique Sáez Pérez de la Lastra

Tutor:

Antonio Jesús Sierra Collado

Profesor titular

Departamento de Ingeniería Telemática

Escuela Técnica Superior de Ingeniería

Universidad de Sevilla

Sevilla, 2016

Page 4: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura
Page 5: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

ÍNDICE 1 Objetivos ............................................................................................................................................. 11

2 Introducción ........................................................................................................................................ 13 Recolección de datos ................................................................................................................................. 13 Almacenamiento e intercambio de la información procedente de dispositivos clínicos ...................... 14 Visualización de las constantes biomédicas del paciente ....................................................................... 14 Diagrama de componentes implicados .................................................................................................... 14

3 Soluciones IoMT alternativas ............................................................................................................... 17 Capsule ....................................................................................................................................................... 17 Picis Hawkeye ............................................................................................................................................. 19 OpenICE ...................................................................................................................................................... 19 Resumen de las soluciones IoMT alternativas ......................................................................................... 21

4 Análisis de tecnologías ......................................................................................................................... 23 Hardware de integración .......................................................................................................................... 23

4.1.1 Descripción ......................................................................................................................................... 23 4.1.2 Análisis de alternativas ...................................................................................................................... 23 Sistema Operativo del Hardware de integración .................................................................................... 25

4.2.1 Descripción ......................................................................................................................................... 25 4.2.2 Análisis de alternativas ...................................................................................................................... 25

4.2.2.1 SO Linux ...................................................................................................................................... 26 4.2.2.2 SO Windows ............................................................................................................................... 26 4.2.2.3 Otros SO ..................................................................................................................................... 26

Clúster de servidores de mensajes ............................................................................................................ 26 4.3.1 Descripción ......................................................................................................................................... 26 4.3.2 Análisis de alternativas ...................................................................................................................... 27

4.3.2.1 Apache Kafka .............................................................................................................................. 27 4.3.2.2 RabbitMQ ................................................................................................................................... 29

Base de datos ............................................................................................................................................. 30 4.4.1 Descripción ......................................................................................................................................... 30 4.4.2 Análisis de alternativas ...................................................................................................................... 30

4.4.2.1 Oracle .......................................................................................................................................... 31 4.4.2.2 MySQL......................................................................................................................................... 32 4.4.2.3 SQL Server .................................................................................................................................. 32

Entorno de desarrollo para BBDD............................................................................................................. 32 4.5.1 Descripción ......................................................................................................................................... 32 4.5.2 Análisis de alternativas ...................................................................................................................... 33

4.5.2.1 Oracle SQL Developer ................................................................................................................ 33 4.5.2.2 TOAD ........................................................................................................................................... 34

Lenguaje de programación ....................................................................................................................... 34 4.6.1 Descripción ......................................................................................................................................... 34 4.6.2 Análisis de alternativas ...................................................................................................................... 34

4.6.2.1 Java ............................................................................................................................................. 34 4.6.2.2 Python......................................................................................................................................... 35

Capa de persistencia .................................................................................................................................. 36 4.7.1 Descripción ......................................................................................................................................... 36 4.7.2 Análisis de alternativas ...................................................................................................................... 36

4.7.2.1 Bajo nivel de abstracción .......................................................................................................... 36 4.7.2.2 ORM: Object-Relational mapping............................................................................................. 36 4.7.2.3 Soluciones mixtas ...................................................................................................................... 38

Gestor de dependencias y construcción del proyecto ............................................................................. 38

Page 6: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

4.8.1 Descripción ........................................................................................................................................ 38 4.8.2 Análisis de alternativas...................................................................................................................... 39

4.8.2.1 Ant .............................................................................................................................................. 39 4.8.2.2 Maven ........................................................................................................................................ 39 4.8.2.3 Gradle ......................................................................................................................................... 39

Entorno de desarrollo software ................................................................................................................ 40 4.9.1 Descripción ........................................................................................................................................ 40 4.9.2 Análisis de alternativas...................................................................................................................... 40

4.9.2.1 Eclipse ......................................................................................................................................... 41 4.9.2.2 IntelliJ IDEA ................................................................................................................................ 44 4.9.2.3 NetBeans .................................................................................................................................... 45 4.9.2.4 JDeveloper ................................................................................................................................. 45 Resumen del análisis de tecnologías empleadas en el proyecto............................................................ 46

5 Descripción de la propuesta ................................................................................................................. 47 Arquitectura ............................................................................................................................................... 47

5.1.1 Diseño funcional ................................................................................................................................ 47 5.1.2 Prototipo inicial de la arquitectura del proyecto ............................................................................ 48 5.1.3 Modelo definitivo .............................................................................................................................. 50 Hardware de integración con biodispositivos ......................................................................................... 53

5.2.1 El estándar HL7 .................................................................................................................................. 53 5.2.2 Protocolos propietarios .................................................................................................................... 54 5.2.3 Adaptación entre puertos estándares ............................................................................................. 56 Base de datos ............................................................................................................................................. 58

5.3.1 Tablespace ......................................................................................................................................... 58 5.3.2 Usuarios / Esquemas ......................................................................................................................... 59 5.3.3 Tablas ................................................................................................................................................. 61

5.3.3.1 Información común a todas las tablas ..................................................................................... 62 5.3.3.2 Esquema HEALTH ...................................................................................................................... 63 5.3.3.3 Esquema DATA_ACQ ................................................................................................................. 66

5.3.4 Secuencias .......................................................................................................................................... 71 5.3.5 Índices ................................................................................................................................................ 73 5.3.6 Permisos ............................................................................................................................................. 74 Sistema de intercambio de datos: Kafka ................................................................................................. 76

5.4.1 Nodos ................................................................................................................................................. 77 5.4.2 Topics ................................................................................................................................................. 78 5.4.3 DTOs ................................................................................................................................................... 80 5.4.4 Modelo ............................................................................................................................................... 81 5.4.5 Producers ........................................................................................................................................... 82 5.4.6 Consumers ......................................................................................................................................... 85 Componentes software ............................................................................................................................. 88

5.5.1 Estructura del software del proyecto .............................................................................................. 88 5.5.2 MEDIPI Suite ...................................................................................................................................... 92 5.5.3 MEDIPi-DOM ..................................................................................................................................... 94

5.5.3.1 CORE-DOM ................................................................................................................................. 96 5.5.3.2 HEALTH-DOM .......................................................................................................................... 103 5.5.3.3 DATACQ-DOM ......................................................................................................................... 107

5.5.4 MEDIPI-CLUSTER ............................................................................................................................. 108 5.5.4.1 CORE-CLUSTER ......................................................................................................................... 109

5.5.5 MEDIPI-APP ...................................................................................................................................... 113 5.5.5.1 CORE-APP ................................................................................................................................. 116 5.5.5.2 DDA ........................................................................................................................................... 120 5.5.5.3 SAVER ....................................................................................................................................... 135 5.5.5.4 CHART ....................................................................................................................................... 139

Page 7: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Resumen de la descripción de la propuesta ........................................................................................... 145

6 Validación ........................................................................................................................................... 147 Funcionamiento de la solución ............................................................................................................... 147 Resumen de la validación ........................................................................................................................ 150

7 Planificación........................................................................................................................................ 151 Fases de la planificación .......................................................................................................................... 151 Resumen de la planificación.................................................................................................................... 153

8 Conclusiones y líneas futuras .............................................................................................................. 155 Conclusiones ............................................................................................................................................. 155 Líneas futuras ........................................................................................................................................... 156

Referencias ................................................................................................................................................ 157

Page 8: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura
Page 9: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

ÍNDICE DE FIGURAS FIGURA 2-1. PRIMER ESQUEMA GENERAL DEL PROYECTO.................................................................................................... 14 FIGURA 3-1. ESQUEMA DE SMARTLINX, DE CAPSULE TECH, INC ....................................................................................... 17 FIGURA 3-2. MODELOS DE LA SERIE SMARTLINX AXON ...................................................................................................... 18 FIGURA 3-3. SMARTLINX IQ ............................................................................................................................................ 18 FIGURA 3-4. LOGO DE HAWKEYE, DE LA COMPAÑÍA PICIS CLINICAL SOLUTIONS .................................................................. 19 FIGURA 3-5. INTERFAZ DE USUARIO DE HAWKEYE CON LAS CONSTANTES DE UN PACIENTE. .................................................. 19 FIGURA 3-6. ASTM F-2761 VS IMPLEMENTACIÓN DE OPENICE ......................................................................................... 20 FIGURA 3-7. INTERFAZ SUPERVISOR DE OPENICE .............................................................................................................. 20 FIGURA 3-8. INTERFAZ DISPOSITIVO OPENICE .................................................................................................................. 21 FIGURA 4-1. CATÁLOGO DE SISTEMAS OPERATIVOS PARA LA RASPBERRY PI 2 ....................................................................... 25 FIGURA 4-2. LOGO DE APACHE KAFKA .............................................................................................................................. 27 FIGURA 4-3. ARQUITECTURA BÁSICA JAVA ........................................................................................................................ 27 FIGURA 4-4. CONSUMICIÓN DE MENSAJES DEL CLÚSTER ..................................................................................................... 28 FIGURA 4-5. TOPICS Y PARTICIONES EN KAFKA ................................................................................................................... 28 FIGURA 4-6. LOGO RABBITMQ ....................................................................................................................................... 29 FIGURA 4-7. RANKING DE BASES DE DATOS DE DB-ENGINES. .............................................................................................. 30 FIGURA 4-8. LOGO ORACLE DATABASE ............................................................................................................................. 31 FIGURA 4-9. LOGO MYSQL ............................................................................................................................................ 32 FIGURA 4-10. LOGO SQL SERVER .................................................................................................................................... 32 FIGURA 4-11. LOGO SQL DEVELOPER .............................................................................................................................. 33 FIGURA 4-12. INTERFAZ GRÁFICA SQL DEVELOPER ............................................................................................................ 33 FIGURA 4-13. LOGO DE TOAD ........................................................................................................................................ 34 FIGURA 4-14. LOGO DE JAVA .......................................................................................................................................... 34 FIGURA 4-15. PLATAFORMAS JAVA .................................................................................................................................. 35 FIGURA 4-16. LOGO DE PYTHON ..................................................................................................................................... 35 FIGURA 4-17. LOGO DE JDBC ......................................................................................................................................... 36 FIGURA 4-18. LOGOS DE LAS PRINCIPALES IMPLEMENTACIONES JPA: HIBERNATE, ECLIPSELINK Y OPENJPA ............................ 37 FIGURA 4-19. LOGO DE QUERYDSL ................................................................................................................................. 37 FIGURA 4-20. LOGO DE IBATIS ........................................................................................................................................ 38 FIGURA 4-21. LOGO DE ANT ........................................................................................................................................... 39 FIGURA 4-22. LOGO DE MAVEN ...................................................................................................................................... 39 FIGURA 4-23. LOGO DE GRADLE ...................................................................................................................................... 39 FIGURA 4-24. COMPARATIVA ENTRE LOS IDES JAVA MÁS USADOS ...................................................................................... 41 FIGURA 4-25. ARQUITECTURA DE ECLIPSE. ........................................................................................................................ 41 FIGURA 4-26. INTERFAZ DE ECLIPSE IDE. .......................................................................................................................... 43 FIGURA 4-27. PERSPECTIVAS. .......................................................................................................................................... 43 FIGURA 4-28. VISTA DE GESTIÓN DE PROYECTOS. .............................................................................................................. 43 FIGURA 5-1. TIPOS DE CONSTANTES MÉDICAS, CONTINUAS Y DISCRETAS. .............................................................................. 48 FIGURA 5-2. PRIMER PROTOTIPO DE MEDIPI ................................................................................................................... 48 FIGURA 5-3. LEYENDA PRIMER PROTOTIPO DE MEDIPI ...................................................................................................... 49 FIGURA 5-4. ESQUEMA DEL SISTEMA DE FICHEROS DISTRIBUIDOS HDFS EMPLEADO POR HADOOP. ........................................ 50 FIGURA 5-5. ESQUEMA GENERAL DE LA ARQUITECTURA ..................................................................................................... 51 FIGURA 5-6. LEYENDA ESQUEMA GENERAL DE LA ARQUITECTURA ........................................................................................ 51 FIGURA 5-7. A LA IZQUIERDA, UN SENSOR DE PULSO CARDÍACO. A LA DERECHA, UN VENTILADOR DE GENERAL ELECTRICS ......... 53 FIGURA 5-8. LA RASPBERRY PI 2 B OFRECE 4 PUERTOS USB A BAJO COSTE ........................................................................... 55 FIGURA 5-9. ESQUEMA DE UNA ADAPTACIÓN RS232 (DB9) A USB .................................................................................... 57 FIGURA 5-10. ADAPTADOR EMPLEADO EN EL PROYECTO .................................................................................................... 57 FIGURA 5-11. TABLESPACE INICIALES DE UNA BASE DE DATOS ORACLE XE 11G R2 ................................................................ 58 FIGURA 5-12. PARÁMETROS DE CONEXIÓN POR DEFECTO DE LA BASE DE DATOS ................................................................... 59 FIGURA 5-13. MODELO DE DATOS ................................................................................................................................... 61

Page 10: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

FIGURA 5-14. MODELO DE DATOS SOBRE BIODISPOSITIVOS ................................................................................................ 66 FIGURA 5-15. ARQUITECTURA BÁSICA DE KAFKA ............................................................................................................... 76 FIGURA 5-16. MODELO DEL CLÚSTER ............................................................................................................................... 81 FIGURA 5-17. ESTRUCTURA DE PROYECTOS DOM (DOCUMENT OBJECT MODEL) (BASE DE DATOS) ...................................... 89 FIGURA 5-18. ESTRUCTURA DE PROYECTOS CLUSTER (KAFKA) ............................................................................................ 89 FIGURA 5-19. ESTRUCTURA DE PROYECTOS APP (ELEMENTOS COMUNES DE APLICACIONES MEDIPI) .................................... 89 FIGURA 5-20. ESTRUCTURA DE PROYECTOS MEDIPI. REPRESENTACIÓN GRÁFICA................................................................. 90 FIGURA 5-21. ESTRUCTURA DE PROYECTOS MEDIPI. REPRESENTACIÓN EN CARPETAS .......................................................... 91 FIGURA 5-22. PROYECTO CORE-DOM............................................................................................................................... 96 FIGURA 5-23. PATRÓN DAO EN MEDIPI ...................................................................................................................... 101 FIGURA 5-24. PROYECTO HEALTH-DOM ......................................................................................................................... 104 FIGURA 5-25. PROYECTO DATACQ-DOM ........................................................................................................................ 107 FIGURA 5-26. PROYECTO CORE-CLUSTER ....................................................................................................................... 110 FIGURA 5-27. PROYECTO CORE-APP .............................................................................................................................. 117 FIGURA 5-28. ESTRUCTURA DE UN PROYECTO DURANTE EL DESARROLLO VS COMPILADO ..................................................... 118 FIGURA 5-29. PROYECTO DDA ..................................................................................................................................... 120 FIGURA 5-30. ESQUEMA DE DDA ................................................................................................................................. 123 FIGURA 5-31. PROTOCOLREADER.................................................................................................................................. 130 FIGURA 5-32. COMMANDLISTENER ............................................................................................................................... 133 FIGURA 5-33. DATASENDERMANAGER .......................................................................................................................... 134 FIGURA 5-34. PROYECTO SAVER .................................................................................................................................. 136 FIGURA 5-35. ESQUEMA DE SAVER .............................................................................................................................. 137 FIGURA 5-36. PROYECTO CHART ................................................................................................................................. 140 FIGURA 5-37. ESQUEMA DE CHART ............................................................................................................................. 141 FIGURA 6-1. RASPBERRY PI 2 MODELO B CONECTADA A UN BIODISPOSITIVO MEDIANTE UN ADAPTADOR USB – RS232 ........ 147 FIGURA 6-2. MÓDULO DDA DESPLEGADO EN LA RASPBERRY ........................................................................................... 147 FIGURA 6-3. ENTORNO DE DESARROLLO SQL CONECTADO CORRECTAMENTE A LA BASE DE DATOS........................................ 148 FIGURA 6-4. NODOS ZOOKEEPER, BROKER 1 Y BROKER 2 ARRANCADOS SOBRE UNA MISMA MÁQUINA WINDOWS ................ 148 FIGURA 6-5. LOG DE EJECUCIÓN, EN MODO DEBUG, DE DDA EN LA RASPBERRY ................................................................. 148 FIGURA 6-6. LOG DE UN BROKER KAFKA ........................................................................................................................ 149 FIGURA 6-7. LOG DE SAVER ........................................................................................................................................ 149 FIGURA 6-8. TABLA CONSTANT_INFO CON DATOS INSERTADOS POR SAVER ................................................................. 149 FIGURA 6-9. EJECUCIÓN DE CHART, EN LA QUE PODEMOS VER DATOS (SIMULADOS) A TIEMPO REAL ..................................... 150 FIGURA 7-1. PLANIFICACIÓN PLANTEAMIENTO ................................................................................................................ 151 FIGURA 7-2. PLANIFICACIÓN FASE DE ANÁLISIS ................................................................................................................ 151 FIGURA 7-3. PLANIFICACIÓN PRUEBA DE CONCEPTO ........................................................................................................ 152 FIGURA 7-4. PLANIFICACIÓN DESARROLLO I .................................................................................................................... 152 FIGURA 7-5. PLANIFICACIÓN DESARROLLO II ................................................................................................................... 153 FIGURA 7-6. PLANIFICACIÓN POSTDESARROLLO .............................................................................................................. 153

Page 11: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

11

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

11

1 OBJETIVOS

n la actualidad, la práctica totalidad de los centros sanitarios de países desarrollados o en vías de desarrollo

cuentan con aplicaciones informáticas destinadas a la historia clínica del paciente. Son sistemas enfocados

a sustituir la gestión que se realizaba hasta hace pocos años de forma manual, generalmente mediante el

mantenimiento de archivos físicos en los que ubicar los informes del paciente o las notas de los facultativos. Sin

embargo, estas aplicaciones no son capaces de ir un paso más allá de la mera gestión clínica. En los últimos años

han aparecido nuevos enfoques que apuestan por la integración de los dispositivos cotidianos en Internet y la

explotación de las posibilidades que esto genera. A este concepto se la ha comido como Internet de las cosas,

IoT por sus siglas en inglés (Internet of Things). La aplicación de esta visión al ámbito clínico es poco habitual

en el mercado, de forma que apenas se han explorado sus previsibles beneficios.

Para realizar un proyecto que permita llevar el IoT al ámbito médico se debe partir de que los principales

dispositivos electrónicos vinculados al diagnóstico y tratamiento sanitario son aquellos encargados de medir la

información biomédica de los pacientes. Por tanto, cualquier apuesta por el desarrollo e implantación del IoMT

(Internet of Medical Things) debe sustentarse sobre la conexión de dichos dispositivos a la red gracias a

determinadas soluciones hardware y/o software que permitan su comunicación con otros programas o

aplicaciones.

Partiendo de todo lo anterior, parece razonable aventurar que toda apuesta por el IoMT debe marcarse como

labor fundamental abordar, en mayor o menor grado, los siguientes requisitos:

- El enfoque principal debe girar en torno a los biodispositivos, pues son ellos los que nos permiten hablar

de Internet de las cosas. Para ello se ha de diseñar una solución hardware y/o software que permita la

comunicación entre los dispositivos ya existentes en el mercado y el mayor número posible de

aplicaciones software a través de la red.

- Dichos dispositivos se han de comportar grosso modo como fuente de información. Este

comportamiento es análogo al ya existente en la actualidad, en el que los biodispositivos sirven como

fuente de información a los facultativos. Por tanto, la conexión de dichos dispositivos al Internet de las

cosas pasa por diseñar una herramienta capaz de ofrecer la información biomédica del paciente. Para

realizar tal labor se torna imprescindible conocer los protocolos empleados en la exportación de datos

clínicos.

- Una vez se ofrezca a las aplicaciones de Internet acceder a la información medida por los biodispositivos

se deberá estudiar la posibilidad de establecer una comunicación bidireccional, de forma de que dichas

aplicaciones puedan influir en el comportamiento de los biodispositivos.

- Gracias a la IoMT, la información biomédica puede estar centralizada y ser fácilmente accesible desde

cualquier dispositivo con acceso a Internet. Será necesario abordar algún desarrollo en este sentido, con

el fin de ejemplificar los beneficios más inmediatos de la tecnología empelada.

- Trabajar con biodispositivos va a estar ligado inherentemente a la gestión de grandes cantidades de

datos, dada la alta frecuencia a la que dichos componentes miden las variables clínicas de los pacientes.

Esto abre la puerta al big data, concepto que hace referencia al almacenamiento y procesado de los

datos recuperados en busca de patrones. La posibilidad de añadir big data a todo proyecto IoMT debe

ser tenida en cuenta desde el primer momento, incluso condicionando las decisiones de diseño si es

necesario.

Por tanto, el presente proyecto plantea una solución concreta a la necesidad de implantar el concepto IoT en el

ámbito sanitario, apostando por tomar como elemento central la recolección y centralización de la información

biomédica proporcionada por los múltiples biodispositivos empleados en el tratamiento sanitario de los

pacientes, permitiendo además que toda la información recuperada esté disponible por otras aplicaciones a través

de Internet. Por tanto, el proyecto abarca la intercomunicación con los biodispositivos y la articulación de un

método adecuado para que otras aplicaciones puedan acceder a los datos. Además, se ha fijado como objetivo

proporcionar alguna funcionalidad adicional que nos permita mostrar las utilidades que la IoMT (Internet of

E

Page 12: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Objetivos

12

12

Medical Things) puede llegar a ofrecer a los usuarios. Para ello se ha diseñado una herramienta de visualización

que permita a los facultativos observar en tiempo real todas las constantes de cualquier paciente. De lo expuesto

hasta ahora surgen claramente tres sectores, tres funcionalidades diferentes que conformarán el proyecto

desarrollado:

- Recuperación de la información biomédica

- Almacenamiento e intercambio de dichos datos con cualquier aplicación

- Visualización a tiempo real de la misma.

Como se ha visto en estos objetivos, la introducción del Internet de las cosas en el ámbito médico nos obliga a

alcanzar una serie de hitos, enfocados fundamentalmente a la comunicación con los biodispositivos. A lo largo

de esta memoria se detallará la solución concreta ideada para satisfacerlos, exponiendo en todo momento los

motivos de las decisiones adoptadas.

Page 13: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

13

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

13

2 INTRODUCCIÓN

l presente proyecto plantea una solución concreta a la necesidad de implantar el concepto IoT (Internet de

las cosas) en el ámbito sanitario, apostando por tomar como elemento central la recolección y

centralización de la información biomédica proporcionada por los múltiples biodispositivos empleados en

el tratamiento sanitario de los pacientes, permitiendo además que toda la información recuperada esté disponible

por otras aplicaciones a través de Internet. Por tanto, el proyecto abarca la intercomunicación con los

biodispositivos y la articulación de un método adecuado para que otras aplicaciones puedan acceder a los datos.

Además, se ha fijado como objetivo proporcionar alguna funcionalidad adicional que nos permita mostrar las

utilidades que la IoMT (Internet of Medical Things) puede llegar a ofrecer a los usuarios. Para ello se ha diseñado

una herramienta de visualización que permita a los facultativos observar en tiempo real todas las constantes de

cualquier paciente. De lo expuesto hasta ahora surgen claramente tres sectores, tres funcionalidades diferentes

que conformarán el proyecto desarrollado:

- Recuperación de la información biomédica

- Almacenamiento e intercambio de dichos datos con cualquier aplicación

- Visualización a tiempo real de la misma.

Para mostrar esto de la manera más clara posible, tanto en el proyecto en sí como a lo largo de la presente

memoria se hará alusión constante a esta clasificación.

Recolección de datos

El primer aspecto a considerar es la recuperación de las constantes vitales de los pacientes, núcleo central del

proyecto. La primera tarea es conocer las capacidades de exportación de datos de los dispositivos médicos

existentes actualmente en el mercado. El principal problema a afrontar en esta sección es la amplia diversidad:

existen numerosísimos productos en el sector (desde empresas especializadas hasta gigantes del mercado como

Philips, General Electric, Siemens, etc.) y hay una evidente falta de estandarización tanto a nivel hardware como

software en el terreno de la exportación de la información.

Esto ha ido cambiando con el tiempo, y en la actualidad es cada vez más habitual encontrarse con biodispositivos

del mercado que ofrecen la posibilidad de exportar los datos mediante el protocolo HL7 (Health Level Seven)

[1]. Sin embargo, y a pesar de este y otros esfuerzos realizados por iniciativas como la Integrating the Healthcare

Enterprise [2], HL7 todavía no es un estándar ampliamente usado por las empresas del sector en el ámbito de la

exportación de datos e interoperación con los biodispositivos, y solo los productos más modernos lo soportan.

Esto último no es baladí; dado el alto coste de estos dispositivos su periodo de renovación es amplio, lo que

dificulta su implantación.

Este proyecto constituye la base de un sistema de gestión de información biomédica real, por lo que no se debe

ignorar la realidad del mercado: aunque el estándar HL7 es realmente interesante, es prioritario ofrecer una

solución de recolección de datos que satisfaga las necesidades actuales de los centros sanitarios, obligando a

tratar con los diferentes protocolos propietarios de cada empresa. Además, algunos protocolos propietarios

permiten modificar el funcionamiento del biodispositivo, funcionalidad para la que HL7 no está diseñado.

La inmensa mayoría de los protocolos propietarios empleados por los biodispositivos del mercado para permitir

la exportación de la información clínica medida emplean una comunicación cliente – servidor (a menudo

entendida como maestro – esclavo) a través de interfaces series (RS232 o USB) o paralelo. Por tanto, el escenario

que se ha de abordar es un conjunto de dispositivos diferentes, que necesitan cada uno un cliente específico con

el que establecer una comunicación directa. Para ello, se ha llevado a cabo la tarea de elaborar una solución que

incluye un componente hardware de integración. Por tanto, se necesita un hardware especial para cada

dispositivo (mejor dicho, para un conjunto de ellos) sobre el que correrá un software capaz de transformar la

información a un estándar interno de la suite. Cada hardware contará con una versión del mismo software, que

será totalmente parametrizable, pudiendo indicársele con qué conjunto de dispositivos debe comunicarse. Para

E

Page 14: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Introducción

14

14

cubrir esta necesidad, se ha realizado el diseño de la arquitectura del software, estableciendo un conjunto de

elementos comunes y patrones de diseño enfocados a facilitar el trabajo con protocolos diferentes.

Almacenamiento e intercambio de la información procedente de dispositivos clínicos

La información recuperada deberá almacenarse en algún sistema apropiado que permita a otras aplicaciones

acceder a la mima de forma estructurada. Es por este motivo por el que se ha diseñado una base de datos SQL

sobre la que gestionar no solo las variables clínicas de los pacientes, sino también información administrativa de

los pacientes necesaria para dotar de sentido a los biodatos, parametrización de las aplicaciones, etc. Sin

embargo, esto no cubre uno de los objetivos centrales del proyecto: permitir a otras aplicaciones de Internet

acceder a los datos de la manera más cómoda pasible. Con esto en mente, se ha optado por emplear un clúster

de servidores de mensajes que facilite el intercambio de información entre todos los puntos. Además, este

sistema es más adecuado para soportar el gran volumen de datos procesables y la necesidad de trabajar con

información a tiempo real.

Visualización de las constantes biomédicas del paciente

La última parte del proyecto es una aplicación que permita una visualización sencilla de la información

biomédica de un paciente concreto a tiempo real, ofreciendo así una interfaz de acceso para todos los públicos a

las posibilidades del conjunto de aplicaciones desarrolladas.

Diagrama de componentes implicados

Con todo lo anterior se ha introducido la función básica del proyecto: recuperación, almacenamiento/intercambio

y visualización de la información biomédica de un paciente. La solución ideada se compone de elementos

hardware y software, por lo que es necesario entender cuáles conforman conformar el proyecto y cómo se

relacionan entre sí. Para ello, se ha propone implementar el siguiente esquema esquema.

Figura 2-1. Primer esquema general del proyecto

Como se ha comentado ya, en MEDIPi existirán tres sectores diferentes, cada uno encargado de implementar

una funcionalidad determinada: recolección, almacenamiento/intercambio y visualización. Cada uno de ellos se

corresponde con una aplicación software diferente, que se deberá ejecutar, o no, sobre un hardware concreto:

Page 15: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

15

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

15

- Software de recolección: se ejecutará sobre un hardware de integración con biodispositivos

específico, en concreto, una Raspberry Pi 2 Modelo B configurada para actuar como conector del

biodispositivo a otras aplicaciones; es decir, al Internet de las cosas.

- Software de almacenamiento: se podrá ejecutar sobre cualquier servidor u ordenador personal. Deberá

tener acceso a la base de datos y al clúster para poder realizar su funcionalidad.

- Software de visualización: correrá sobre cualquier ordenador o dispositivo compatible. Recuperará la

información de algún sistema de almacenamiento.

En resumen, MEDIPi se compondrá de tres aplicaciones software, un hardware de integración con

biodispositivos, una base de datos y un sistema de intercambio de mensajes formado por un clúster de servidores.

Todos estos elementos permiten cubrir las necesidades detectadas a la hora de abordar un proyecto que lleva el

IoT al ámbito sanitario, algo prácticamente inexistente en la inmensa mayoría de centros sanitarios. Aun así, sí

que existen ya en el mercado productos que apuestan por la recuperación y explotación de la información

procedente de biodispositivos, enfocando su funcionalidad desde una perspectiva similar a la aquí comentada:

recuperación de datos, almacenamiento/intercambio y visualización, lo que permite comprobar la solidez de los

puntos de partida del proyecto.

Todo lo descrito hasta ahora se detallará a lo largo de esta memoria: el próximo capítulo se dedicará a analizar

las soluciones existentes en el mercado de los productos IoMT, mientras que el siguiente realizará un estudio de

las tecnologías empleadas en el desarrollo, incluyendo una comparativa con el resto de alternativas. A

continuación, llegará el turno de llevar a cabo una descripción detallada del proyecto realizado, comentando

todas las partes implicadas y exponiendo ejemplos concretos de la solución implementada. Tras esto, se validará

el correcto funcionamiento del proyecto y se dedicará un capítulo a la planificación temporal que se ha seguido

durante el desarrollo del mismo. Para terminar, la memoria se cierra con un apartado enfocado a realizar las

conclusiones del proyecto, exponiendo los aspectos más importantes, analizando si se han cumplido o no los

objetivos marcados de partida y poniendo sobre la mesa las posibilidades futuras del proyecto.

Page 16: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Introducción

16

16

Page 17: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

17

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

17

3 SOLUCIONES IOMT ALTERNATIVAS

l conjunto de herramientas y aplicaciones diseñadas nos permite ofrecer una serie de funcionalidades que

giran en torno a la información biomédica de un paciente. El proyecto no busca solo recuperar la

información biomédica, también gestiona su almacenamiento e intercambio y visualización. Encontrar en

el mercado soluciones con este enfoque no es tarea sencilla, pues nos encontramos ante una funcionalidad poco

extendida, pero es posible reconocer algunos productos comparables con la solución MEDIPi aquí diseñada, de

los cuales destacan tres:

- Capsule SmartLinx

- Picis Hawkeye

- OpenICE

Capsule

Figura 3-1. Esquema de SMARTLINX, de Capsule Tech, Inc

La empresa líder en soluciones de centralización e integración de datos procedentes de biodispositivos médicos

es, sin lugar a dudas, Capsule. A través de la marca SmartLinx [3], Capsule ofrece un conjunto variado y sólido

de hardware de integración con los dispositivos médicos compatible con software especializado en el tratamiento

de la información recopilada y con aplicaciones de gestión de historia clínica. La estructura empleada por

Capsule se sustenta en una red propia a la que se conectan todos los dispositivos compatibles. Cuando se trabaje

con protocolos propietarios se deberá emplear un módulo intermedio, que traduzca del protocolo propietario al

interno empleado en la red. Para ello cuenta con varios dispositivos, siendo el más básico las distintas revisiones

de la serie SmartLinx Axon [4]. Para el usuario el dispositivo Axon se comporta como una caja negra con

entradas y salidas. Como interfaces de entrada se ofrecen un conjunto de puertos serie a los que conectar los

biodispositivos, mientras que la salida es una mera interfaz ethernet o incluso WiFi que se debe conectar a la red

de Capsule. El componente Axon será el encargado de recuperar la información y adaptarla al protocolo interno

de la compañía.

E

Page 18: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Soluciones IoMT alternativas

18

18

Figura 3-2. Modelos de la serie SmartLinx Axon

Junto a los productos de la serie Axon Capsule ofrece otras soluciones de integración similares, que suelen

aportar funcionalidades extras a las ya comentadas. Por ejemplo, la serie SmartLinx Vitals Stream [5] permite

visualizar en su pantalla integrada la información recuperada, además de traducirla y enviarla a la red. En la

citada red de dispositivos que necesita la solución SmartLinx se encuentra al menos un servidor HL7 (Health

Level Seven) que procese la información procedente de aquellos biodispositivos que empleen el estándar de

comunicación médica.

Además de la mera recuperación de las variables clínicas de los pacientes, Capsule cuenta con el denominado

SmartLinx Client [6], un software que se comunica con el servidor central de la red para gestionar la selección,

filtrado, transformación y adición de más información a los datos recopilados. Con esta utilidad se pueden

mejorar la calidad de los biodatos de los pacientes, supliendo deficiencias o eliminando aquella información

errónea o incoherente. Sin embargo, estas funcionalidades solo se entienden como pasos previos a la utilización

de las constantes clínicas del paciente junto al resto de su historia médica, permitiendo así que sean útiles en el

diagnóstico de la situación del enfermo. Capsule centra sus esfuerzos en la integración con biodispositivos, más

que en presentar una solución de gestión de historia médica electrónica del paciente (Electronic Medical Record,

EMR). Su modelo de negocio consiste en ofrecer acuerdos con otros proveedores de aplicaciones EMR, que

recibirán los biodatos ya adaptados en formato HL7 o en otro formato acordado. Aun así, Capsule sí ha realizado

algunos movimientos en el ámbito de las interfaces gráficas para usuarios: SmartLinx IQ [7] es una aplicación

de escritorio que provee a los usuarios mecanismos para realizar análisis y generar estadísticas a partir de los

datos de los pacientes.

Figura 3-3. SmartLinx IQ

Page 19: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

19

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

19

Picis Hawkeye

Figura 3-4. Logo de HAWKEYE, de la compañía Picis Clinical Solutions

La solución Hawkeye [8], de Picis, dice integrar datos procedentes de una gran variedad de dispositivos,

soportando varias interfaces de comunicación distintas, gracias a una librería con más de 350 drivers. La

compañía afirma soportar comunicaciones con biodispositivos a través de cables serie (entendiendo por ello

RS232), USB o a través de una red TCP/IP (Ethernet o Wifi), por lo que parece contar con un sistema de

integración propio para establecer las comunicaciones necesarias con protocolos propietarios, aunque luego se

sustente en el estándar HL7. Hawkeye usa interfaces HL7 estándar tanto para recibir información del paciente

(clínica y administrativa) como para enviar información interna en dicho formato, lo que permite conectar el

sistema con otras soluciones del mercado. Además, la información recuperada es centralizada en su sistema de

historia clínica, de forma que desde un solo ordenador se pueda acceder a las constantes clínicas de todos los

pacientes actuales del hospital, complementando esta funcionalidad con notificaciones, elementos de soporte a

la decisión, etc.

Figura 3-5. Interfaz de usuario de HAWKEYE con las constantes de un paciente.

OpenICE

OpenICE [9] es un software libre desarrollado en Java y soportado por el Medical Device Plug-and-Play (MD

PnP) Interoperability Program [10]. Esta iniciativa pretende fomentar el uso de la información procedente de los

biodispositivos mediante la estandarización del mayor número posible de los elementos implicados en la

recolección y procesamiento de la información clínica de los pacientes. Por ello, no solo apuestan por el empleo

de estándares relativamente consolidados como HL7, sino también por la creación y consolidación de otros

como el ASTM F-2761 [11], que define un modelo funcional de categorización y establecimiento de relaciones

entre los diferentes elementos claves que componen un entorno de gestión clínica centralizada enfocada en el

paciente. Es decir, este estándar va mucho más allá de HL7, busca definir un modelo concreto de integración

con biodispositivos clínicos: estructuración en capas, interfaces determinadas, etc.

Page 20: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Soluciones IoMT alternativas

20

20

Figura 3-6. ASTM F-2761 vs implementación de OpenICE

OpenICE se ha diseñado para servir como una posible implementación libre de este estándar, centrándose no

solo en la arquitectura definida por el mismo, sino también desarrollando librerías capaces de entender algunos

de los protocolos propietarios más empleados en el mercado. Llegado a este punto es fácil comprender las

enormes diferencias entre OpenICE y el resto de alternativas comentadas en el siguiente capítulo: hasta ahora se

han tratado soluciones comerciales, que buscaban ofrecer a los centros sanitarios un producto capaz de recuperar

información del mayor número posible de biodispositivos para poder ser incluidos en una aplicación EMR

determinada o ser analizados por determinadas soluciones. Sin embargo, OpenICE solamente pretende servir

como punto de apoyo a la expansión de un determinado patrón de trabajo, no estando enfocado a su implantación

directa en centros sanitarios. Aun así, OpenICE soporta algunas características comparables con el resto de

competidores.

Figura 3-7. Interfaz Supervisor de OpenICE

La ventana principal de OpenICE es la supervisora, que coincide con el elemento ICE Supervisor del estándar

comentado. En ella se debe tener acceso a la información recuperada por cada dispositivo existente en la red,

además de a un conjunto de funcionalidades extra (aquellas ubicadas en la zona izquierda de la ventana). El

estándar ASTM F-2761 implica que este supervisor será el enlace con todos los dispositivos, que deberán enviar

la información que recuperen a través de la red. Para ello, se necesita un adaptador en cada dispositivo que

Page 21: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

21

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

21

conozca el protocolo propietario y lo transmita en el protocolo interno de la red. Para solucionar esto, OpenICE

propone arrancar su software en modo “consola” y seleccionar el dispositivo, de forma que tras establecer la

comunicación enviará los biodatos a la red mediante un sistema de datos distribuido conocido como DDS [12].

Figura 3-8. Interfaz Dispositivo OpenICE

Desde el supervisor bastará con seleccionar el dispositivo para visualizar sus datos a tiempo real, una

funcionalidad similar a la implementada en el presente proyecto.

Resumen de las soluciones IoMT alternativas

Las tres soluciones detalladas a lo largo del capítulo parten de una misma idea: existe la necesidad de recuperar

y poner a disposición de usuarios y terceras aplicaciones la enorme cantidad de información clínica que

proporcionan los dispositivos médicos implicados en el tratamiento de los pacientes. Sin embargo, a pesar de

que todas tienen un objetivo común se pueden observar fácilmente enormes diferencias. No solo tenemos que

establecer una separación entre soluciones propietarias (Capsule y Picis) y open-source (OpenICE), sino que es

imprescindible comprender las diferentes visiones implicadas: OpenICE está orientado a construir una red de

dispositivos con entidad propia mientras que SmartLinx y Hawkeye piensan claramente en integrar sus

soluciones en aplicaciones de historia clínica. Esta visión es menos innovadora, pero facilita la integración de

las soluciones con las aplicaciones informáticas existentes actualmente en centros sanitarios, algo que sin duda

habrá sido tenido en cuenta por las compañías desarrolladoras. Parece evidente que OpenICE está mucho más

cerca que sus competidores de alcanzar los requisitos que se han marcado en este proyecto, ya que comparte un

enfoque parecido. Al ser software libre, es posible realizar una comparativa tecnológica entre esta solución y el

proyecto realizado. En general existen elementos comunes, ya que se han empleado tecnologías para el lenguaje

de programación Java, aunque OpenICE carece de base de datos y apuesta por un sistema de intercambio de

datos mucho menos potente que el empleado en MEDIPi. En cualquier caso, ninguna de las aplicaciones aquí

comentadas abarca al completo el enfoque IoMT (Internet of Medical Things) sobre el que se ha construido el

proyecto.

Page 22: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Soluciones IoMT alternativas

22

22

Page 23: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

23

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

23

4 ANÁLISIS DE TECNOLOGÍAS

ntes de plantearse abordar en detalle la descripción del proyecto realizado es imprescindible dedicar un

capítulo a realizar un estudio de las diferentes tecnologías que serán necesarias para llevarlo a cabo. Para

cada una de ellas se procederá a elaborar un análisis comparativo entre las diferentes opciones existentes

en el mercado, estableciendo sus puntos fuertes y débiles, como paso previo indispensable para elaborar la

justificación de la opción empleada en la suite desarrollada.

El proyecto abarca tres funcionalidades claramente diferenciadas: recuperación de datos, intercambio y

visualización de los mimos. Parece evidente que lo más sencillo es clasificar las tecnologías empleadas de

acuerdo a la función que pretenden satisfacer. Sin embargo, algunas de ellas pueden emplearse en más de un

ámbito, algo que ocurre con facilidad en todo proyecto software. Para aclarar todo este se parte de la siguiente

categorización:

- Tecnologías exclusivas de comunicación con biodispositivos: hardware de integración y sistema

operativo del Hardware de Integración

- Tecnologías exclusivas de intercambio de la información biomédica: clúster de servidores de mensajes,

base de datos y entorno de desarrollo para base de datos

- Tecnologías exclusivas de visualización: no se considera necesario al emplear las librerías de

visualización del lenguaje de programación común.

- Tecnologías comunes a todos los sectores: lenguaje de programación Software, capa de persistencia,

gestor de dependencias y construcción del proyecto y entorno de desarrollo software.

Hardware de integración

4.1.1 Descripción

Para abordar la integración con los biodispositivos se ha optado por un enfoque que nos permita soportar aquellos

dispositivos con protocolos propietarios, al ser la mayoría de los existentes en el mercado. Con este objetivo en

mente, es necesario un hardware de integración al que conectar físicamente los dispositivos mediante interfaces

serie RS232, USB, paralelo, etc. En el presente apartado se realizará un estudio de los principales ordenadores

de placa reducida (SBC, por sus siglas en inglés), que nos permitirán manejar los datos recibidos de cada

dispositivo diferente, basándonos en los criterios justificados en el análisis: versatilidad, escalabilidad, presencia

de interfaces estándar, coste y rendimiento

4.1.2 Análisis de alternativas

En la actualidad, el mercado de los SBCs consta de una gran salud debido a la explosión de popularidad, en

términos de ventas y de soporte por la comunidad, que primero Arduino y después las diferentes versiones de la

Raspberry Pi han cosechado. El número de opciones disponibles ha aumentado considerablemente, sobretodo

siguiendo el modelo de Raspberry, que ofrece un sistema más “completo” que Arduino, no solo enfocado al

desarrollo electrónico. En nuestro caso, nos encontramos ante un proyecto desarrollado en Java, que necesita de

la JVM corriendo sobre el hardware elegido. Conseguir esto sobre Arduino, una placa hardware enfocada a

desarrolladores de microcontroladores, es mucho más costoso que emplear un SBC, que pretende ofrecer la

misma funcionalidad que ordenadores personales o servidores con un bajo tamaño y coste. Es por este motivo

por el que se ha centrado el análisis en las SBCs existentes en el mercado descartando otro tipo de dispositivos

hardware.

A

Page 24: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

24

24

SBC Procesador Almacenamiento RAM Conectividad Precio

Raspberry Pi 2

Model B [13]

ARM Cortex

A7 900 MHz

quad-core

SD 1 GB

4 USB 2.0,

HDMI 1.4 y

Ethernet

45$

Jaguar One [14] Intel Atom

Z3735G 16 GB 1 GB DDR3

3 USB 2.0,

HDMI 1.4 y

Ethernet

70$

Orange Pi [15] ARM A7 4x1.2

Ghz

SD

512 MB

1 USB 2.0,

HDMI y

Ethernet

10$

ODROID-C1+

[16]

ARMv7 1.5

Ghz quad core SD 1 GB DDR3

4 USB 2.0,

HDMI 2.0 y

Ethernet

40$

Hummingboard

[17]

ARM A9 hasta

Dual Core SD 2 GB

2 USB 2.0,

HDMI 2.0 y

Ethernet

70$

Beaglebone

Black [18]

ARM A8 1 Ghz

(TI Sitara

AM3358)

4 GB 512 MB

DDR3

1 USB 2.0,

HDMI 2.0 y

Ethernet

45€

Cubieboard5

[19]

ARM A7 8

núcleos 8 GB + SATA 2 GB DDR3

HDMI, USB,

Displayport,

audio digital,

Wifi, BT 4.2

99$

pcDuino4 [20]

ARM A7 4

núcleos

(Allwinner H3)

8 GB 1 GB DDR3

2 USB 2.0,

HDMI 2.0 y

Ethernet

49$

En la tabla superior se puede observar una comparativa de las principales características de los SBCs con mayor

presencia en el mercado. El primer punto a tener en cuenta es que se va a conectar el hardware escogido con los

biodispositivos del paciente mediante interfaces serie o paralelo. Para ello, se partirá de puertos USB (los más

habituales) empleando adaptadores cuando sea necesario. De cara a reducir los costes del proyecto se ha de

optimizar el número de placas de integración, pasando de una primera lógica 1 dispositivo – 1 SBC a la de 1

puerto – 1 dispositivo. Para ello no solo es necesario un dispositivo hardware con el mayor número de puertos

USB posibles, sino también con la capacidad suficiente como para ejecutar la solución de recolección de datos

con múltiples lectores de protocolos a la vez. La condición anterior nos lleva a reducir las opciones a dos: la

Raspberry Pi 2 Model B y el ODroid-C1+, quienes cuentan con unas características similares: 4 puertos USB,

ARMv7 y 1GB DDR3. ODroid gana en procesador, ofreciendo mayor velocidad de cálculo, mientras que se

produce un empate técnico en el precio. Las características técnicas de ambos SBCs proporcionan la capacidad

suficiente como para ejecutar un sistema operativo ligero (un Linux sin entorno gráfico) y la aplicación de

recolección de datos diseñada con los 4 lectores de protocolos funcionando en paralelo. Por tanto, la decisión

está reñida, pero el gran soporte que la comunidad ofrece a Raspberry decanta la balanza a su favor: los sistemas

operativos diseñados para Raspberry cuentan con una amplia utilización en el mercado, estando

convenientemente pulidos y garantizando una gran disponibilidad. Además, el rendimiento de estas placas

hardware durante largos periodos de tiempo es más que solvente, como han podido comprobar miles de usuarios

en los últimos meses.

Page 25: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

25

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

25

Sistema Operativo del Hardware de integración

4.2.1 Descripción

Una vez se ha elegido a la Raspberry Pi 2 Modelo B como la placa que conformará el hardware de integración

con biodispositivos el siguiente paso lógico es seleccionar el sistema operativo de la SBC, que deberá poder

ejecutar el software de recolección de datos diseñado en el presente proyecto. Como se verá un poco más

adelante, el único requisito que se deriva del software diseñado es la necesidad de soportar la Java Virtual

Machine, pues todos los componentes de la suite MEDIPi se han desarrollado bajo el lenguaje de programación

de Oracle.

4.2.2 Análisis de alternativas

Para ejecutar la aplicación de recuperación de biodatos del paciente solo necesitaremos un sistema operativo

capaz de correr la máquina virtual de Java con soltura suficiente, garantizándonos el rendimiento y fiabilidad

que requiere una tarea tan crítica como la que se va a realizar en la Raspberry.

Figura 4-1. Catálogo de Sistemas Operativos para la Raspberry Pi 2

La imagen superior corresponde con una captura del apartado dedicado a sistemas operativos de la página web

de Raspberry. En la línea superior, encuadrados en un rectángulo negro, se encuentran los sistemas operativos

con soporte oficial, dejando las filas inferiores para los sistemas operativos de terceras compañías.

El primer paso va a ser eliminar de la lista de candidatos a los sistemas operativos que no sean de propósito

general ni estén enfocados a desarrolladores.

- Noobs: sistema operativo de primer contacto. Más que un sistema operativo, puede entenderse como

un conjunto de utilidades básicas que nos permitirán seleccionar el sistema operativo que queremos

instalar de forma sencilla.

Page 26: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

26

26

- OSMC / LibreElec: sistemas operativos enfocados a convertir la Raspberry Pi en centros multimedia.

- PiNet: sistema operativo enfocado a la utilización de la Raspberry en ámbitos educativos, ofreciendo

utilidades para la gestión de múltiples Raspberrys en una misma red escolar.

- Weather Station: versión de Raspbian para llevar a cabo acciones de estación climática.

Una vez descartados los SOs específicos, clasificaremos los restantes en tres grupos:

4.2.2.1 SO Linux

Los Sistemas Operativos Linux dominan las preferencias de los poseedores de los distintos modelos de

Raspberry Pi, gracias a las amplias posibilidades que ofrecen tanto a desarrolladores como a usuarios finales.

Tanto Raspbian [21] como Ubuntu Mate [22] proporcionan un Sistema Operativo Linux completo (incluso con

interfaz gráfica), adaptando respectivamente Debian y Ubuntu Mate a la arquitectura ARM v7. Al hablar de

implementaciones código libre de reputados sistemas operativos no solo podemos contar con la tranquilidad de

encontrarnos frente a SOs sólidos, sino que también tenemos a nuestra disposición una enorme gama de

utilidades, librerías, paquetes, etc. Por ejemplo, la imagen de Raspbian trae por defecto las últimas versiones de

Python y Java, buscando facilitar lo máximo posible las tareas al desarrollado. Esto último, unido al soporte

oficial de la Raspberry Foundation, hacen de Raspberry la opción más lógica para servidor de base a la aplicación

de recolección de biodatos del proyecto.

Ya solo queda una opción por comentar: Snappy Ubuntu Core [23] es el producto de la familia Ubuntu enfocado

al IoT (Internet de las cosas). Se trata de un sistema operativo muy joven que parte de un enfoque totalmente

diferente, hasta el punto de romper con algunos puntos habituales hasta ahora en las distribuciones de Canonical.

Se trata sin duda de una opción interesante, pero no está todavía suficientemente madura, por lo que cualquier

problema podría necesitar de un tiempo de resolución superior al de otras distribuciones Linux.

4.2.2.2 SO Windows

Windows 10 IoT Core [24] es una versión del núcleo de Windows 10 adaptada para el Internet de las Cosas,

pudiendo funcionar tanto en dispositivos con pantalla o sin ella, cargando tan solo el núcleo del sistema y

funcionando con pocos recursos. Este SO está claramente enfocado al mundo de IoT, y ni siquiera cuenta con

soporte para Java, lo que lo hace inviable para nuestro Proyecto.

4.2.2.3 Otros SO

En esta categoría clasificamos a RISC OS [25], un sistema operativo con núcleo o kernel propio, distinto a los

kernels habituales como Linux y Windows. Fue desarrollado por Acorn Computers, una compañía británica que

dejó de existir en noviembre del año 2000, y cuyo código fuente es mantenido por RISC OS Ltd. con una licencia

Open Source.1 Se diseñó pensando en ordenadores basados en chips ARM.2. Ofrece un rendimiento menor al

de los SO Linux, además de contar con un soporte mucho más limitado, motivos por los que se ha descartado

su uso.

Clúster de servidores de mensajes

4.3.1 Descripción

Uno de los aspectos centrales del proyecto es la creación de un clúster que nos permita un intercambio adecuado

de la información biomédica de los pacientes entre todos los componentes del proyecto: almacenador de

constantes vitales en base de datos, visualización y otros posibles módulos a construir sobre las bases existentes,

así como aplicaciones de terceros. Para satisfacer esta necesidad, el proyecto abarca la configuración de un

conjunto de nodos y servidores diseñados que conformarán un clúster empleado como un bus de información,

así como la implementación y parametrización de consumidores y productores para dicha estructura de red. Las

características que debe soportar el clúster del proyecto no escapan de las requeridas habitualmente en esta

tecnología: alta disponibilidad, redundancia, seguridad, escalabilidad y facilidad para la integración con el

software diseñado.

Page 27: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

27

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

27

4.3.2 Análisis de alternativas

4.3.2.1 Apache Kafka

Figura 4-2. Logo de Apache Kafka

Apache Kafka [26] es un sistema de procesado de mensajes. Los mensajes se publican por los productores

(producers) en colas denominadas topics y se consumen de la cola por los consumidores (consumers) suscritos

a dicha cola. Es una solución al problema de los productores-consumidores concurrentes. En este problema

existen uno o más actores (productores) que generan los mensajes que son procesados por uno o más actores

(consumidores) de manera concurrente.

El sistema de encolado y procesado de mensajes es distribuido y particionado en diferentes instancias

denominadas brokers que conforman el clúster de Kafka. Dentro del clúster, en cada broker, cada topic o cola

está dividida en particiones en las que los mensajes se almacenan de manera secuencial. Las particiones de un

topic permiten:

- Distribuir la carga de trabajo entre diferentes brokers y consumidores

- Tener tolerancia a errores de los brokers, al poder tener replicadas la misma partición en brokers

distintos (aunque solo una es la activa, pueden tomar el sitio de la activa si ésta cae)

Figura 4-3. Arquitectura básica Java

El productor es quien encola los mensajes en cada partición, que mantiene estos mensajes de manera secuencial

y ordenada. Es el propio productor quien decide en qué partición específica del topic se almacena el mensaje.

Page 28: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

28

28

De esta manera el balanceado de los mensajes en las diferentes particiones queda en manos del productor, no

del clúster, que puede basarse en criterios de balanceado de carga o de lógica de negocio.

El modo en que se distribuyen los mensajes a los consumidores es también bastante flexible. Los consumidores

se agrupan en grupos de consumidores. El clúster distribuye los mensajes de cada partición a un único

consumidor del grupo, pero si hubiese más de un grupo de consumidores lo haría para cada grupo. De esta

manera nos encontramos en una cola clásica con la carga balanceada entre varios consumidores si solo hay un

grupo, y en un modelo de suscripción si tuviésemos más de un grupo.

Figura 4-4. Consumición de mensajes del clúster

El único modo de garantizar que los mensajes se consumen en el orden en que se crean es teniendo una única

partición por topic y un solo consumidor por grupo. El único modo de garantizar que los mensajes se consumen

una sola vez es teniendo un único grupo de consumidores.

El consumidor de cada partición es el que decide el orden en que se procesan los mensajes y los mensajes que

se procesan. El consumidor tiene libertad para moverse en la partición accediendo a los mensajes de manera

indexada (offset desde comienzo) y en sentido y con el criterio que quiera, y es quién lleva constancia de si han

sido consumidos o no. Esto permite que la política o lógica de procesado de mensajes sea mucho más flexible

que la cola tradicional, permitiendo el reprocesado de mensajes, el procesado en cualquier orden o el consumo

de mensajes en la misma partición por diferentes consumidores (si están en distintos grupos).

Los mensajes se mantienen en la partición, con independencia de si han sido consumidos o no, durante el tiempo

indicado por la política de retención de mensajes. No hay borrado de los mensajes. Esto se debe a una decisión

de diseño muy eficiente, puesto que el acceso al disco secundario es siempre secuencial y no aleatorio, con las

ventajas de rendimiento que supone.

Figura 4-5. Topics y particiones en Kafka

Page 29: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

29

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

29

En Kafka podemos combinar el modo de almacenaje clásico de los mensajes en las particiones con un modo

mapa, en el que los mensajes cuentan con clave y valor. Como todos los mensajes con la misma clave se

almacenarán siempre en la misma partición de un topic podemos activar la opción log.cleaner.enable para

mantener en la partición solo el último valor de una clave. A esta operación se le denomina “log compaction”

[27] y permite gestionar los topics como si fuesen mapas.

Solo queda comentar un punto de Kafka: pueden existir uno o varios nodos Zookeeper en un clúster de Kafka.

Apache ZooKeeper es un servicio de datos en estructura de árbol. El servicio es centralizado, replicado, de alta

disponibilidad y escalable; y garantiza la integridad en accesos concurrentes y el orden de modificación de los

datos de manera secuencial. El sistema está formado por un conjunto distribuido de instancias denominado

quorum que sirven la misma información, en el caso de Kafka, los brokers.

El servicio es centralizado porque solo una de las instancias en ejecución hace las veces de instancia maestra, es

la única que puede modificar los datos y que los replica al resto de las instancias. Esto garantiza el orden de los

cambios, la atomicidad transaccional y la integridad concurrente de la información. Cuando la instancia maestra

cae, el algoritmo de elección de líder, decide qué instancia es la nueva instancia maestra. El acceso de lectura,

sin embargo, puede hacerse a cualquiera de las instancias levantadas del sistema. Esto por un lado garantiza la

disponibilidad, al poder cualquier nodo convertirse en líder, y el rendimiento y la escalabilidad, al permitir poder

añadir todas las instancias que queramos al quorum para repartir la carga. Este diseño lo hace más adecuado para

situaciones en que la lectura de datos es mucho más habitual que la escritura (al menos 1:10 según la

documentación).

En resumen, Kafka es un solución tremendamente sólida, muy versátil y sencilla para consumir o transformar

información, ofreciendo una fiabilidad, escalabilidad y velocidad sin competencia en el mercado, motivos por

los que se ha elegido como sistema de intercambio de mensajes del proyecto.

4.3.2.2 RabbitMQ

Figura 4-6. Logo RabbitMQ

RabbitMQ [28] es un software de negociación de mensajes de código abierto, y entra dentro de la categoría de

middleware de mensajería. Implementa el estándar Advanced Message Queuing Protocol (AMQP). El servidor

RabbitMQ está escrito en Erlang, un lenguaje enfocado a programación concurrente y distribuida, y utiliza el

framework Open Telecom Platform (OTP) para construir sus capacidades de ejecución distribuida y

conmutación ante errores. Este MOM (Message oriented middleware), implementa un tipo de componentes

denominados exchanges, los cuales permiten enlazar colas, topics y otros exchanges entre sí. Esta opción facilita

mucho la labor de diseñar una jerarquía de colas más compleja y dinámica. El proyecto RabbitMQ consta de

diferentes partes:

- El servidor de intercambio RabbitMQ en sí mismo

- Pasarelas para los protocolos HTTP, XMPP y STOMP.

- Bibliotecas de clientes para Java y el framework .NET. (Bibliotecas similares para otros lenguajes se

encuentran disponibles por parte de otros proveedores).

- El plugin Shovel que se encarga de replicar mensajes desde un corredor de mensajes a otros

Se trata de un producto sin duda más maduro que Kafka, pero también menos optimizado, contando con

rendimiento notablemente inferior. Además, Kafka es una tecnología que se encuentra actualmente en plena

fase final de desarrollo por Apache, lo que nos garantiza una empresa fuerte detrás preparada para dar soporte y

mejorar el producto, además de poner en valor el gran número de usuarios que ya ha conseguido antes de lanzar

su primera versión estable.

Page 30: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

30

30

Base de datos

4.4.1 Descripción

Un elemento clásico en las aplicaciones informáticas es la base de datos, lugar donde se persiste la información

manejada. El presente proyecto define una suite de aplicaciones, desarrollando para tal efecto una arquitectura

sólida que permita la adición de nuevos módulos y funcionalidades. Por tanto, el diseño de una base de datos

era inherente al proyecto desde el principio, incluso si no se hubiera detectado su necesidad durante el análisis

de las aplicaciones que abarca esta memoria.

4.4.2 Análisis de alternativas

Para el proyecto se requerirá una base de datos relacional, por lo que en este capítulo nos centraremos en

comparar los diferentes motores de base de datos relacionales existentes, dividiéndolos en dos categorías:

- Libres: MySQL, PostgreSQL, Firebird, SQLite. las dos primeras son las más conocidas y, sin duda, son

válidas para un proyecto, por complicado que sea.

- Propietarias: Dejando de lado las menos “potentes”, dBASE (un clásico, pero muy superada),

FileMaker, Interbase, Access… tenemos las 2 más conocidas, Oracle y SQL Server de Microsoft,

además de IBM DB2, Informix, Progress…

Con lo anterior, y con el objetivo de ofrecer un análisis sólido que sirva para elegir la base de datos del proyecto

se va a partir de un estudio del mercado de motores de bases de datos. La investigación más completa es la

realizada por DB-Engine [29], quienes miden la popularidad de los distintos motores de base de datos a partir

de las consultas en buscadores de ámbito general (Google, Bing, etc.), menciones en webs especializados

(Stackoverflow. DBA Stack Exchange, etc), número de ofertas de trabajo en portales como Indeed y encuestas

de uso entre profesionales del sector. Según los datos de dicho estudio, existe un trio de soluciones que llevan

una amplia ventaja sobre el resto en número de usuarios y popularidad. Esta es una característica fundamental,

no solo índica la posible robustez de una base de datos, sino que implicará un mayor soporte e información

técnica sobre ellas por parte de la comunidad. Por tanto, en el presente análisis solo contemplaremos esas tres

bases de datos: Oracle, MySQL y SQL Server.

Figura 4-7. Ranking de bases de datos de DB-Engines.

Page 31: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

31

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

31

4.4.2.1 Oracle

Figura 4-8. Logo Oracle Database

La base de datos de Oracle, conocida como Oracle Database [30], es uno de los motores de bases de datos más

robustos del mercado, destacando por su baja tasa de errores y su alta fiabilidad. Su principal punto negativo

radica en su condición de código propietario, permitiendo solo su distribución bajo licencia comercial. Por el

contrario, cuenta con una amplia gama de puntos positivos. En primer lugar, cuenta con algunas características

no habituales en la competencia, como recuperación de transacciones erróneas, Grid Computing, Gateways,

FlashBack Table, etc. El otro gran punto a favor de Oracle es el lenguaje PL/SQL. PL/SQL es un lenguaje de

programación propio de Oracle que permite a los desarrolladores escribir procedimientos almacenados, triggers

e incluso funciones en Java. Gracias al compilador Java y la JVM incluida en las bases de datos, es posible

compilar programas Java directamente en la base de datos o leer una clase utilizando utilidades proporcionadas

por la base de datos. A pesar de tratarse de software propietario, la comunidad entorno a Oracle Database es

especialmente extensa, lo que nos permitirá encontrar ayuda de otros usuarios ante prácticamente cualquier

problema que nos pueda surgir. Todas estas características han hecho a Oracle Database dominar el mercado y

ser escogido como motor de base de datos de este proyecto.

Actualmente Oracle mantiene cinco ediciones de su base de datos, intentando presentar una gama de productos

que se adecue a las necesidades específicas de cada cliente.

- Oracle Database Standard Edition One: Ofrece facilidad de uso, potencia y rendimiento para grupos de

trabajo, a nivel de departamentos y aplicaciones Web. Desde los entornos de un solo servidor para

pequeñas empresas a los entornos de sucursales altamente distribuidos.

- Oracle Database Standard Edition: Oracle Database Standard Edition ofrece las funcionalidades de la

edición Standard Edition One, con el apoyo de máquinas más grandes y la agrupación de los servicios

con Oracle Real Application Clusters (Oracle RAC).

- Oracle Database Enterprise Edition: Ofrece el rendimiento, la disponibilidad, la escalabilidad y la

seguridad necesaria para las aplicaciones de misión crítica, tales como el procesamiento de grandes

volúmenes de transacciones en línea (OLTP), almacenes de datos en consultas intensivas y exigentes

aplicaciones de Internet.

- Oracle Database Express Edition: Es una edición básica de la base de datos de Oracle. Es rápida de

descargar, fácil de instalar y administrar, y es libre de desarrollar, implementar y distribuir. Es fácil de

actualizar a las otras ediciones de Oracle sin migraciones costosas y complejas. Oracle Database XE se

puede instalar en cualquier máquina tamaño con cualquier número de CPUs, almacena hasta 11 GB de

datos de usuario, con un máximo de 1 GB de memoria, y con una sola CPU en la máquina host. Existe

un foro en línea, para dar soporte. Como parece evidente, es la opción ideal para nuestro proyecto.

Actualmente la última versión estable de Oracle Database es la 12, pero no cuenta con una versión

exprés, por lo que emplearemos la última disponible: la 11g xe.

- Oracle Database Personal Edition: Soporta los entornos de desarrollo de un solo usuario y el despliegue

que requieren la plena compatibilidad con Oracle Database Standard Edition One, Oracle Database

Standard Edition y Oracle Database Enterprise Edition. Le diferencia la excepción de la no opción de

Oracle Real Application Clusters. Personal Edition sólo está disponible en los sistemas operativos

Windows y Linux. Tampoco incluye los módulos de administración.

Page 32: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

32

32

4.4.2.2 MySQL

Figura 4-9. Logo MySQL

MySQL [31] es la base de datos de código abierto más popular del mundo, tal y como anuncia orgullosamente

Oracle en su web. MySQL fue inicialmente desarrollado por MySQL AB, que fue adquirida por Sun

Microsystems en 2008, y ésta a su vez fue comprada por Oracle Corporation en 2010, la cual ya era dueña desde

2005 de Innobase Oy, empresa finlandesa desarrolladora del motor InnoDB para MySQL. MySQL es popular

por su velocidad de procesamiento y por emplear una licencia GLP (General Public Licence). Gracias a su

extensión, tiene conectores para la práctica totalidad de lenguajes importantes (algunos como Ruby o C++ no

cuentan con conector para Oracle Database). En cuento funcionalidad, destaca sobre la mayoría de rivales,

aunque quede un poco por debajo en una comparación con Oracle Database.

4.4.2.3 SQL Server

Figura 4-10. Logo SQL Server

SQL Server [32] es el sistema de gestión de bases de datos relacionales Microsoft que está diseñado para el

entorno empresarial. SQL Server se ejecuta en T-SQL (Transact-SQL), un conjunto de extensiones de

programación de Sybase y Microsoft que añaden varias características a SQL estándar, incluyendo control de

transacciones, excepción y manejo de errores, procesamiento fila, así como variables declaradas. SQL Server

fue lanzado en noviembre de 2005 y Microsoft presume de que su entrada en el mercado proporcionó una mayor

flexibilidad, escalabilidad, confiabilidad y seguridad a las aplicaciones de base de datos, y permitió que fueran

más fáciles de crear y desplegar, lo que reduce la complejidad en la gestión de bases de datos. Para este proyecto

SQL Server es una solución demasiado cerrada y engorrosa, frente a la facilidad de instalación y manejo que

ofrece la Express Edition de Oracle. Además, se encuentra en clara inferioridad frente a las otras bases de datos

analizadas en este apartado.

Entorno de desarrollo para BBDD

4.5.1 Descripción

Siempre que se trabaje con una base de datos es necesario un entorno de desarrollo para la misma, una aplicación

que nos permita ejecutar instrucciones en lenguaje SQL y administrar las funcionalidades de la base de datos.

La elección del IDE para base de datos dependerá enormemente del motor de base de datos escogido en el punto

anterior, pues existen muchas soluciones que solo soportan determinadas bases de datos, aunque exista una

tendencia cada vez mayor a que esto cambie. Para las bases de datos Oracle existen dos entornos de desarrollo

que destacan sobre los demás, por presencia en el mercado y funcionalidad: Oracle SQL Developer y TOAD.

Page 33: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

33

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

33

4.5.2 Análisis de alternativas

4.5.2.1 Oracle SQL Developer

Figura 4-11. Logo SQL Developer

SQL Developer [33] es el entorno de desarrollo para bases de datos de Oracle. Desarrollado en Java, actualmente

ofrece soporte para otras bases de datos distintas a la proa del Oracle, como MySQL o SQL Server. Al ejecutarse

sobre la Java Virtual Machine el programa se encuentra disponible para todos los sistemas operativos soportados

por Java, lo que en la práctica abarca cualquier opción que pueda hacer el usuario. Es una aplicación gratuita de

código propietario. Cuenta con una amplia gama de funcionalidades, cubriendo todas las elementales y contando

con alguna función avanzada. Se construye en torno a un interfaz principal que permite navegar por un árbol

jerárquico de objetos contenidos en bases de datos y realizar operaciones sencillas sobre ellos. Junto al

explorador se encuentra un área para ejecutar sentencias SQL y PL/SQL. A través de esta interfaz gráfica no

solo es posible ejecutar sentencias, sino también modificar gráficamente distintos objetos de la base de datos

(tablas, campos, índices, etc.) facilitando la tarea a los desarrolladores inexpertos. Otras funciones interesantes

son el modelado E/R (que genera un diagrama de relación entre clases) y la importación / exportación de datos

en múltiples formatos. Además, cuenta con un Sistema de plugins de forma que los usuarios puedan desarrollar

sus propias funcionalidades.

Figura 4-12. Interfaz gráfica SQL Developer

En resumen, SQL Developer es un entorno de desarrollo para base de datos tremendamente intuitivo y fácil de

usar, que no requiere de grandes conocimientos para su utilización. Además, cubre de sobra las funcionalidades

básicas, proveyendo a los usuarios expertos de otras capacidades más avanzadas. En nuestro caso, su condición

de gratuito y su facilidad de uso han sido los puntos clave que han provocado su elección en el presente proyecto.

Page 34: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

34

34

4.5.2.2 TOAD

Figura 4-13. Logo de TOAD

TOAD [34] es una herramienta gráfica para desarrollo de base de datos creada por Quest Software, actualmente

dentro de la corporación Dell, Inc. Originalmente se trataba de una aplicación diseñada exclusivamente para

bases de datos de Oracle (de hecho, TOAD son las siglas de Tool for Oracle Application Developers) aunque

actualmente soporta la práctica totalidad de bases de datos incluyendo las dominadoras del mercado (Oracle,

MySQL, PostgreSQL, Microsoft SQL Server, etc.). Se trata de una aplicación propietaria que se distribuye bajo

dos versiones: una Freeware limitada y una versión de pago completa. Cuenta con una enorme cantidad de

funcionalidades, centradas especialmente en los DBA (Data Base Administrator). Por ejemplo, realizar copias

de una base de datos (exports e import) es tremendamente sencillo desde la interfaz gráfica de TOAD, contando

con un simple asistente que te ayuda a través de todo el proceso. Es, sin duda, la opción más completa del

mercado para los desarrolladores de una base de datos de Oracle. Sin embargo, la versión gratuita se queda un

poco corta, ofreciendo prácticamente las mismas funciones que el SQL Developer, lo que no compensa una

interfaz menos intuitiva.

Lenguaje de programación

4.6.1 Descripción

Llega el momento de comentar el lenguaje de programación empleado para todo el proyecto, comparándolo con

otras opciones posibles. En este caso la elección está fundamentada en los conocimientos del desarrollador, pues

no es tan fácil cambiar de lenguaje de programación como optar entre dos entornos de desarrollo. Aun así, se

comentarán las ventajas e inconvenientes de la opción elegida frente a otros posibles lenguajes que presentan

características interesantes para el proyecto realizado.

4.6.2 Análisis de alternativas

4.6.2.1 Java

Figura 4-14. Logo de Java

Java [35] es un lenguaje de programación de propósito general, concurrente, orientado a objetos que fue

diseñado específicamente para tener tan pocas dependencias de implementación como fuera posible. Su

intención es permitir que los desarrolladores de aplicaciones escriban el programa una vez y lo ejecuten en

cualquier dispositivo, por lo que las aplicaciones de Java son generalmente compiladas a bytecode (clase Java)

que puede ejecutarse en cualquier máquina virtual Java (JVM) sin importar la arquitectura de la computadora

subyacente. Fue originalmente desarrollado por James Gosling de Sun Microsystems (la cual fue adquirida por

la compañía Oracle) y publicado en 1995 como un componente fundamental de la plataforma Java de Sun

Microsystems.

Page 35: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

35

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

35

Se definen tres plataformas Java, en un intento por cubrir distintos entornos de aplicación. Así, las APIs

pertenecen a una plataforma u otra en función de su funcionalidad.

- Java ME (Java Platform, Micro Edition): orientada a entornos de recursos limitados, como teléfonos

móviles.

- Java SE (Java Platform, Standard Edition): para entornos de gama media y estaciones de trabajo. Aquí

se sitúa al usuario medio en un PC de escritorio.

- Java EE (Java Platform, Enterprise Edition): orientada a entornos distribuidos empresariales o de

Internet.

Figura 4-15. Plataformas Java

La plataforma Java EE define un estándar para el desarrollo de aplicaciones empresariales multicapa basadas en

componentes. La lógica de la aplicación se divide en componentes de acuerdo a su función, y cada componente

puede ser instalado en una máquina diferente dependiendo de la capa a la que pertenezca. Cada uno de los

componentes de Java EE se ejecuta en un contenedor apropiado. Un contenedor es el entorno de ejecución para

un componente, que le proporciona acceso a una serie de servicios. Además de los componentes ya comentados

destaca el Enterprise Bean, encargado de la lógica de negocio. Sirven para automatizar la persistencia, dar

soporte a la implementación de fachadas del modelo (objetos de sesión, aplicación, etc.), declarar operaciones

transaccionales y aspectos de seguridad, etc.

La tendencia actual del mercado es relegar a Java al desarrollo back-end (capa de negocio y tratamiento de datos,

empleando otras opciones más potentes para la capa de presentación (como las diferentes implementaciones de

Javascript). En el caso que nos ocupa, realizaremos fundamentalmente desarrollo back-end, por lo que Java

parece una opción tremendamente sólida, teniendo en cuenta la robustez del lenguaje y su amplísimo uso.

Cualquier funcionalidad requerida externa requerida durante el desarrollo estará ya implementada por un tercero,

siendo tremendamente sencillo anexarla a nuestro proyecto. Además, es, sin duda, el lenguaje de programación

que mejor abarca múltiples escenarios, lo cual no es una característica baladí para una suite de productos que

pretende abarcar muchas aplicaciones diferentes.

4.6.2.2 Python

Figura 4-16. Logo de Python

Python [36] es un lenguaje de script desarrollado por Guido van Rossum en el que es posible codificar

empleando programación lineal, estructurada y orientada a objetos (siendo esta última la que ámbito de la

programación en la actualidad). Existen intérpretes de Python en múltiples plataformas: Windows, Linux, Mac

etc. Empresas como Google, Yahoo, Nasa etc. utilizan este lenguaje para sus desarrollos (actualmente el creador

Page 36: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

36

36

de Python Guido Van Rossum trabaja para Google.)

Se puede ejecutar instrucciones de Python desde la línea de comando o creando archivos con extensión *.py. Al

ser un lenguaje interpretado, la línea de comandos nos permite conocer el resultado de las líneas codificadas

inmediatamente, favoreciendo mucho la programación. Python se emplea en múltiples ámbitos: aplicaciones

que se ejecutan en un servidor web (equivalentes a lo que se puede hacer con PHP, ASP.Net, JSP, Ruby),

aplicaciones de escritorio con interfaces visuales accediendo a componentes escritos en .Net (Microsoft), Qt,

GTK, MFC, Swing (Java) etc., programas no visuales para cubrir funcionalidades back-end…

Es, por tanto, un lenguaje interesante que está creciendo considerablemente en la actualidad. Ya existen soportes

para la práctica totalidad de bases de datos (como por ejemplo Oracle Database) y domina el segmento de

programación enfocado a domótica, sobretodo sobre SBCs como Raspberry o placas Arduino. Para la

comunicación con los biodispositivos, núcleo del presente proyecto, Python sería una elección más que

adecuada, pero nos obligaría a limitar las funcionalidades en otras aplicaciones posibles o incluso en el diseño

de la suite. Python es una opción de futuro, que poco a poco comienza a consolidarse y a abordar múltiples

escenarios, pero se considera más adecuado diseñar una suite que se espera sirva de base para múltiples

desarrollos en un lenguaje con el mayor número de librerías y utilidades externas posibles.

Capa de persistencia

4.7.1 Descripción

El acceso desde las aplicaciones Java a la base de datos se va a estudiar en dos niveles. En el primero se

comentará la filosofía de trabajo con la base de datos, la API escogida, mientras que en el segundo se abarcará

que implementación concreta de esa filosofía se ha utilizado en el proyecto.

4.7.2 Análisis de alternativas

4.7.2.1 Bajo nivel de abstracción

Figura 4-17. Logo de JDBC

Java provee una API básica para establecer las comunicaciones con la base de datos denominada Java Database

Connectivity (JDBC). A través de algunas sus clases, organizadas en el paquete java.sql, podemos establecer la

comunicación con la base de datos y ejecutar sentencias SQL, almacenando los resultados de una consulta. Por

tanto, directamente sobre el JDBC podemos realizar las comunicaciones que queramos con la base de datos, sin

necesidad de establecer mayores niveles de abstracción. Esta política tiene claras ventajas: es muy sencilla, solo

requiere conocimiento SQL para trabajar con la base de datos y es la menos pesada y, generalmente, la que

ofrece mayor rendimiento. Por otra parte, implica tener que definir manualmente la consulta / sentencia SQL

que se quiera realizar cada vez, de forma que un desarrollador debe conocer SQL, no independizando los

lenguajes. Además, un cambio en base de datos implica buscar manualmente las posibles sentencias afectadas.

Está claro que estamos ante una política muy simple, lo cual implica algunas ventajas, pero se puede volver

demasiado engorrosa (poco escalable, actualizable, propensa a errores) en un Proyecto como este, en el que

varias aplicaciones diferentes van a querer trabajar con la base de datos. Parece interesante analizar otras

opciones que busquen un mayor nivel de abstracción, independizándonos definitivamente del lenguaje de base

de datos.

4.7.2.2 ORM: Object-Relational mapping

El mapeo objeto-relacional (Object-Relational mapping, O/RM, ORM, o O/R mapping) es una técnica de

programación para mapear datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a

Page 37: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

37

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

37

objetos y el utilizado en una base de datos relacional, utilizando un motor de persistencia. En la práctica, esto

implica crear una base de datos orientada a objetos “virtual”, que el motor ORM es capaz de transformar en la

base de datos relacional. Esto no solo posibilita el uso de las características propias de la orientación a objetos

(fundamentalmente herencia y polimorfismo), sino que abstrae al desarrollador del conocimiento de SQL al ser

el motor ORM el encargado de transformar las acciones realizadas sobre los objetos o clases de mapeo en

sentencias sobre las tablas / campos reales en la base de datos. El desarrollador solo tiene que crear el mapeo

entre el objeto Java y el elemento de la base de datos, pudiendo operar con los objetos en su desarrollo y

olvidándose prácticamente del resto del trabajo. Este sistema es, evidentemente, más complejo que el anterior

pero también mucho más robusto. Por ejemplo, si tenemos una clase Java que mapea los campos de una tabla

modificar el nombre de un campo solo implica modificar el nombre de una variable, pudiéndonos servir del

compilador para detectar los errores que esto pueda derivar. Además, ORM abre la puerta a funcionalidades más

avanzadas, como ya se ha comentado anteriormente.

El uso de ORM se ha vuelto cada vez más popular en los últimos años, sobre todo para proyectos de tamaño

medio-grande, facilitando el tratamiento con la base de datos. Todos estos son motivos más que suficientes para

optar por JPA (Java Persistence API), el estándar ORM de Java.

JPA es la API diseñada por Java para cubrir la metodología ORM. Es, no obstante, una mera interfaz que define

un flujo de trabajo y una metodología determinada, sirviendo de estándar para los diferentes motores ORM del

mercado. Es decir, JPA nos permite una capa más de abstracción: un mapeo objeto-relacional realizado en JPA

podrá valer para varios motores ORM diferentes, pudiendo cambiarlos si el desarrollador así lo desea.

4.7.2.2.1 Motor ORM

Figura 4-18. Logos de las principales implementaciones JPA: Hibernate, EclipseLink y OpenJPA

Hibernate [37] es, con mucha distancia, el principal motor ORM empleado en desarrollo Java. De hecho, aunque

Hibernate pueda entenderse como una implementación de JPA (cosa afirmativa) se trata de un framework

mucho más amplio y antiguo. JPA está basado en Hibernate, y es un intento de estandarizar la capa de

persistencia frente al boom de los frameworks ORM que provocó la entrada de Hibernate en el mercado. Por

tanto, Hibernate puede usarse tanto bajo JPA como capa de persistencia propia. En esta modalidad Hibernate

soporta la capacidad para trabajar con bases de datos NoSQL, algo que JPA no cubre, cachés multinivel, etc.

Más allá de Hibernate existen otras múltiples implementaciones de JPA, como EclipseLink [38]

(implementación seleccionada por Oracle como referencia desde JPA 2.0) y OpenJPA [39], de Apache. Aunque

son motores ORM sólidos se encuentran a demasiada distancia de Hibernate en cuanto a rendimiento,

funcionalidad y posición en el mercado.

En nuestro proyecto se ha intentado optar por la estandarización, ya que JPA cubre de sobra nuestras

necesidades, colocando a Hibernate como motor JPA dada su robustez y solvencia.

4.7.2.2.2 Lenguaje de consultas

Figura 4-19. Logo de QueryDSL

Parece fácil comprender que JPA nos proveerá de un conjunto de utilidades para realizar inserciones,

actualizaciones y eliminaciones de objetos (correspondientes a un registro en una tabla de base de datos), pero

no es tan sencillo imaginar cómo se ejecutan consultas SQL complejas a través de JPA. Para ello, se ha definido

Page 38: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

38

38

el Java Persistence Query Language (JPQL), un lenguaje de consulta orientado a objetos independiente de la

plataforma, usado para hacer consultas contra las entidades JPA. Es decir, JPQL está inspirado en gran medida

por SQL, y sus consultas se asemejan a las consultas SQL en la sintaxis, pero opera con objetos entidad de JPA

en lugar de hacerlo directamente con las tablas de la base de datos. JPQL define un conjunto de métodos para

facilitar la construcción de consultas, pero necesita recibir el grueso de la lógica en una cadena de texto, en vez

de utilizar los atributos del objeto empleado, algo muy poco mantenible. Es por esto que han surgido utilidades

para desarrollar consultas empleando directamente atributos Java, facilitando la programación y la gestión del

código, entre otras funcionalidades. JPA 2.0 introduzco Criteria, una API para consultas type-safe, es decir, a

prueba de errores de tipos gracias a trabajar completamente con instancias y métodos Java, evitando las cadenas

de texto de JPQL. A Criteria le han surgido algunas alternativas, entre las que destaca especialmente QueryDSL

[40], un framework de código libre que cuenta con soporte para una inmensa cantidad de frameworks de

persistencia, desde JPA hasta bases de datos no relacionales como MongoDB. QueryDSL es mucho más

intuitivo y fácil de manejar que Criteria y es tan potente que puede emplearse hasta para realizar consultas sobre

colecciones Java, algo que Oracle se ha trasladado al propio lenguaje en Java 8. Para poder ofrecer esta

funcionalidad necesita generar unas clases denominadas QClass, quienes contarán con los métodos y atributos

necesarios para facilitar la construcción de consultas. Estas clases se autogeneran a partir de las entidades JPA

definidas, gracias a un plugin integrable con Maven y otros gestores de dependencias y construcción del

proyecto.

4.7.2.3 Soluciones mixtas

Figura 4-20. Logo de iBatis

Existen algunos frameworks de persistencia que ofrecen soluciones a medio camino entre la ejecución directa

de sentencias SQL y los ORM. El caso más conocido es sin duda iBatis, frecuentemente categorizado dentro de

los ORM. iBatis [41] es una opción intermedia entre las dos políticas definidas previamente. Esta tecnología se

sustenta en definir no solo el mapeo entre los elementos de base de datos y las clases Java, sino también las

sentencias SQL que se utilizarán. Desde el desarrollo Java se indicará que operación (consulta, actualización,

inserción, etc.) se desea realizar. El hecho de que las operaciones se definan en SQL prácticamente puro y que

haya que describir todas y cada una de ellas ofrece una solución menos automática a los desarrolladores, aunque

abre la puerta a optimizar las sentencias SQL, un aspecto siempre criticado de los motores ORM.

Gestor de dependencias y construcción del proyecto

4.8.1 Descripción

En proyectos Java complejos la gestión de dependencias es una labor fundamental. Al igual que en la mayoría

de lenguajes, una correcta gestión de nuestro proyecto implicará conocer qué librerías necesitamos y con qué

versión exacta. Además, estas librerías contarán a su vez con otras dependencias, pudiendo darse el caso de

acabar incorporando a nuestro proyecto librerías duplicadas que reducen el rendimiento y favorecen la aparición

de errores. Para optimizar esta labor surgieron los gestores de dependencias, que nos permiten definir en un

fichero de configuración determinado las dependencias de nuestra aplicación, bastando incluso con indicar una

referencia completa a la librería para que el gestor se encargue de buscarla, descargarla e importarla a nuestro

proyecto automáticamente. Pronto esta funcionalidad se fusionó con la evolución de los programas encargados

de gestionar la vida del proyecto (siendo el más conocido make de C), quienes iban abarcando cada vez más

capacidades. De esta manera, es posible parametrizar la compilación, el empaquetamiento, el tratamiento de

ficheros externos, la ejecución de pruebas, etc. Toda esta amplia gama de funcionalidades provocó que los

gestores de dependencias y construcción crecieran en popularidad, hasta el punto de que hoy en día sea extraño

encontrar un proyecto de medio tamaño que no cuente con los servicios de ninguna de las distintas soluciones

existentes en el mercado.

Page 39: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

39

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

39

4.8.2 Análisis de alternativas

4.8.2.1 Ant

Figura 4-21. Logo de Ant

Ant [42] fue la primera herramienta moderna para la construcción de proyectos Java. Lanzado en el año 2000,

pretendía ser el equivalente Java de Make, convirtiéndose en una de las utilidades más populares del lenguaje

en un corto periodo de tiempo. Su facilidad de uso, y la capacidad de extender sus funcionalidades mediante

plugins, fueron sus principales puntos fuertes. Por otra parte, la configuración realizada sobre XML se volvía

demasiado engorrosa, dificultando en algunas ocasiones la legibilidad del código. Aunque sigue bajo desarrollo

en la actualidad, ha sido suplantado en la mayoría de los proyectos por Maven, otra solución de Apache que

apareció pocos años después, partiendo de los conocimientos y las experiencias adquiridas durante el desarrollo

de Ant.

4.8.2.2 Maven

Figura 4-22. Logo de Maven

Maven [43] apareció en 2004, como herramienta sucesora de Ant (ambas desarrolladas por Apache). Continuaba

utilizando XML como formato de configuración, pero replanteando completamente su estructura y lógica

interna. Mientras que Ant exigía a los desarrolladores codificar todos los pasos que quisieran ejecutar durante la

construcción de su proyecto, Maven definió un ciclo de vida (validate, compile, test, package, verify, install y

deploy). Cada fase se compone a su vez de goals u objetivos, de forma que el ciclo de vida siempre se ejecuta,

siendo tarea del programador vincular acciones con determinados goals. Quizás la principal característica de

Maven, aquella que ha convertido a esta utilidad de Apache en un must have de todo proyecto Java, es su gestión

de dependencias. Basta con identificar adecuadamente una librería en el fichero de configuración para que

Maven la descargue y la importe al proyecto. Además, cuenta con una amplia gama de plugins que permiten

abarcar prácticamente cualquier acción imaginable durante la construcción del proyecto. Maven permite filtrado

de ficheros, gestión de ficheros externos (resources), estructuración de proyectos en varios niveles, ejecución de

tests, etc. Sin embargo, no todo son ventajas: el enfoque centrado en el ciclo de vida reduce la flexibilidad en el

desarrollo. Además, usar XML como formato de codificación de Maven es poco versátil frente a otras opciones

que han ido surgiendo en el mercado.

Maven es, hoy en día, el gestor de construcción de Java más potente y útil. Cuenta con una enorme solvencia

fruto de su amplio uso por los desarrolladores. Poco a poco, otras opciones como Gradle han reducido su

hegemonía, pero sigue siendo la opción más adecuada para este proyecto al combinar una pequeña curva de

aprendizaje, una potente integración con el IDE escogido y una gran documentación disponible.

4.8.2.3 Gradle

Figura 4-23. Logo de Gradle

Page 40: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

40

40

Gradle [44] pretende combinar lo mejor de las dos herramientas vistas hasta ahora. Ofrece mayor flexibilidad al

programador, aunque mantiene la estructura de ciclo de vida introducida por Maven. Desde su lanzamiento en

2012 ha sufrido un crecimiento espectacular, llegando a ser escogida por Google como la build tool por defecto

en Android. Inicialmente, Gradle empleaba el sistema de dependencias Ivy, de Apache, aunque hace poco ha

migrado hacia su propio gestor de dependencias. La principal novedad de Gradle es el empleo de un lenguaje

específico del dominio (DSL) propio, diseñado específicamente para la construcción de software. Como

consecuencia de esto, los scripts de configuración de proyecto de Gradle son generalmente más cortos y claros

que los de sus competidores, facilitando no solo la programación sino también el mantenimiento del proyecto.

Entorno de desarrollo software

4.9.1 Descripción

Para el desarrollo de la aplicación será imprescindible contar con un entorno de desarrollo integrado (IDE). Se

trata de una herramienta software diseñada para facilitar la programación de aplicaciones, permitiendo la edición,

ejecución y depuración del código fuente (Java en este caso). Típicamente, un entorno de desarrollo contiene un

editor de código fuente, un compilador/intérprete/montador y un depurador complementados por una serie de

funciones adicionales. Es decir, además de dar soporte a la fase programación también lo hace a la fase de

pruebas. Por ejemplo, el editor no es un simple editor de texto, sino que reconoce y maneja elementos sintácticos

del lenguaje usado, avisa de errores en la programación, provee de funciones de autocompletado inteligente de

código, etc. El depurador, por su parte, suele permitir al desarrollador comprobar el efecto de cada línea de

código en la ejecución del programa, en vez de presentar la información en términos de lenguaje máquina. En

resumen, la principal utilidad de un entorno de desarrollo es la integración de todas las herramientas útiles

durante el desarrollo de software en una única interfaz, promoviendo un marco de trabajo amigable al

programador.

Podemos encontrarnos con entornos de desarrollo integrados con distintas filosofías: existen IDEs específicos

para un lenguaje determinado, frente a los entornos multilenguaje. A pesar de lo que pueda parecer, la diferencia

va más allá de la cantidad de lenguajes soportados. Los entornos de desarrollo integrados centrados en un único

lenguaje están fuertemente integrados, de forma que se presentan como una única herramienta compacta al

programador. Esto puede provocar una falta de flexibilidad, pero les dota de mayor accesibilidad. Por su parte,

los entornos de desarrollo multilenguaje están construidos como un conjunto de módulos que interoperan entre

sí. Se les conoce como toolkit, pues se presentan como un conjunto de herramientas para la programación. Como

es evidente, este enfoque provoca una integración más débil, mayor complejidad para el usuario, pero también

mayor versatilidad. La principal utilidad de estos IDEs es la capacidad de ver extendida su funcionalidad a través

de módulos o plugins. Gracias a ella, los programadores pueden llegar combinar las más variadas tecnologías

para el desarrollo de su proyecto a través de un mismo programa, añadiendo los plugins necesarios al IDE por

defecto e incurriendo en una alta personalización del entorno de trabajo.

Además de todo lo anterior, es interesante comentar que los entornos de desarrollo suelen contar con una serie

de funcionalidades habituales como son herramientas de programación visual, gestión de repositorios para el

trabajo en equipo o editores de estructura.

4.9.2 Análisis de alternativas

En los próximos subapartados se analizarán las opciones más empleadas entre los programadores del ámbito

correspondiente al de este proyecto: aplicaciones web en Java. La fuente más fiable para obtener un estudio

acerca de los IDEs más usados en el sector. Como nota curiosa, dicha empresa es la responsable de JRebel, un

plugin para IDEs que elimina las fases de build y redespliegue en proyectos Java.

Page 41: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

41

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

41

Figura 4-24. Comparativa entre los IDEs Java más usados

Como se puede comprobar en el estudio [45], el mercado se encuentra dominado por tres principales alternativas

estudiadas en el presente capítulo: Eclipse, Intellij IDEA y NetBeans. Además de ellas se echará un vistazo al

JDeveloper de Oracle, por los motivos que se argumentarán más adelante.

4.9.2.1 Eclipse

Eclipse [46] es un IDE multiplataforma de código abierto, iniciado originalmente por IBM y desarrollado por la

Fundación Eclipse desde 2001. Puede clasificarse entre los entornos de desarrollo de tipo toolkit, ya que está

compuesto por una estructura base sobre la que pueden instalarse distintos plugins que permiten agregar soporte

para múltiples lenguajes de programación (java, c, php, etc.), tecnologías (maven, gradle, spring, etc.) o

personalización del entorno.

Figura 4-25. Arquitectura de eclipse.

Su arquitectura se compone de los siguientes elementos:

Page 42: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

42

42

Plataforma

Es el núcleo del Eclipse IDE. Se encarga de descubrir al inicio qué complementos están instalados, creando un

registro de información sobre ellos. Para reducir el tiempo de inicio y el uso de los recursos, no carga ningún

complemento hasta que realmente se lo necesita. Se trata del único componente que no se implementa como un

complemento.

Espacio de trabajo

El espacio de trabajo es el complemento responsable de la administración de los recursos del usuario. Incluye

todos los proyectos que crea el usuario, los archivos de esos proyectos y los cambios en los archivos y otros

recursos. También es responsable de notificar a otros complementos interesados sobre los cambios en los

recursos, como archivos creados, eliminados o modificados.

Entorno de trabajo o workbench

El entorno de trabajo proporciona a Eclipse una interfaz de usuario. Se crea con la utilización de un Kit de

Herramientas Estándar (SWT) [47] — una alternativa al Swing/AWT GUI API de Java — y la API JFace [48],

quien se emplea sobre el citado SWT para proporcionar componentes de la interfaz gráfica.

Equipo

El componente de equipo es responsable de proporcionar soporte para el control de versiones y la gestión de los

repositorios

Ayuda

Componente de ayuda.

Plugins

Como se ha comentado anteriormente, todo en Eclipse son componentes o plugins. Además de los componentes

básicos comentados en los apartados anteriores, existen otros plugins imprescindibles para conformar un entorno

de desarrollo adecuado para el programador. Probablemente el plugin más importante de Eclipse sea JDT [49],

encargado de dar soporte a la programación en Java. Es responsable de gestionar las vistas de esquemas de

clases, además de varias funciones de soporte a la programación como el coloreado de código (realizando para

ello el reconocimiento sintáctico de todas aquellas palabras que son reservadas en el lenguaje) o el

autocompletado de código (con sugerencias dependientes del contexto, lo cual permite escribir código más

rápidamente). A todo esto, hay que sumar que permite configurar el formateo de código, la forma de escribir los

comentarios, generación de esqueletos de clase automáticamente, generación de métodos getters y setters de

manera automática, y un largo etcétera de funcionalidades útiles para el desarrollo. Este componente también

controla la depuración de todo código Java a través del JDT Debug.

Por último, existen una inmensa variedad de plugins que no son imprescindibles para todos los desarrollados,

pero que el programador podrá incluir para soportar las tecnologías que necesite para su proyecto concreto,

extendiendo así la funcionalidad del IDE.

Para terminar, conviene hacer un breve repaso de la interfaz gráfica del IDE, comentando los elementos más

básicos que se han usado durante el desarrollo de la aplicación.

Page 43: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

43

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

43

Figura 4-26. Interfaz de Eclipse IDE.

En Eclipse el concepto de trabajo está basado en las perspectivas, que no es otra cosa que una preconfiguración

de ventanas y editores, relacionadas entre sí, y que nos permiten trabajar en un determinado entorno de trabajo

de forma óptima. Por ejemplo, en la imagen superior podemos contemplar la perspectiva Java EE (desarrollo de

aplicaciones web Java) vacía. Abajo, con más detalle, las perspectivas abiertas

Figura 4-27. Perspectivas.

Por otra parte, el desarrollo sobre Eclipse se basa en los proyectos, que son el conjunto de recursos relacionados

entre sí, como puede ser el código fuente, documentación, ficheros configuración, árbol de directorios…

Figura 4-28. Vista de gestión de proyectos.

El IDE proporcionará asistentes y ayudas para la creación de proyectos. Por ejemplo, cuando creamos uno, se

abre la perspectiva adecuada al tipo de proyecto que estemos creando, con la colección de vistas, editores y

ventanas preconfigurada por defecto.

En el anexo de este documento se detalla la configuración y pasos básicos para llevar a cabo el desarrollo de la

aplicación.

Page 44: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

44

44

En resumen, Eclipse es un entorno de desarrollo integrado altamente versátil, capaz de dar soporte a

prácticamente cualquier tecnología o lenguaje gracias a su amplia moduralización. Irónicamente, su mayor

ventaja también es un principal inconveniente: la extensión a través de plugins permite que un mismo

programador que vaya a realizar varios proyectos convierta a Eclipse en su único entorno de desarrollo,

simplemente añadiendo o quitando los componentes necesarios para su siguiente desarrollo. Además, Eclipse

cuenta con la comunidad de usuarios más extensa, por lo que existen miles de plugins realizados por terceros

que llegan allí donde el Proyecto Eclipse no alcance. Sin embargo, su filosofía tan descentralizada convierte a

Eclipse en un IDE más propenso a bugs, fallos, cuelgues, etc. de lo que debería. Aun así, su comportamiento

sigue siendo, en condiciones normales y con los componentes habituales, lo suficientemente robusto como para

no eclipsar la enorme ventaja existente en su alta capacidad de ampliar funcionalidades. Todo esto lo ha llevado

a ser, claramente, la opción principal del mercado (sobre todo en Java) y la escogida para el desarrollo de la

aplicación expuesta en este documento.

4.9.2.2 IntelliJ IDEA

IntelliJ IDEA [50] es un entorno de desarrollo para programación sobre lenguaje Java creado por la compañía

JetBrains (inicialmente denominada IntelliJ). Se trata de un producto multiplataforma, disponible en Windows,

Mac, Linux y otras plataformas como Solarios, OpenBSD o FreeBSD. Están disponible dos versiones del

mismo:

- Community Edition: es la versión software libre, licenciada bajo licencia Apache.

- Ultimate Edition: versión propietaria y de pago.

Al igual que el resto de IDEs comentados en el presente apartado, está desarrollado en Java, aunque presenta

ciertas características que lo convierten en un producto diferenciado del resto. Se trata de un IDE diseñado para

soportar solamente lenguaje Java o relacionados (JavaScript, Groovy, etc.), por lo que puede clasificarse como

un entorno de desarrollo centrado en un lenguaje. A pesar de esto, IntelliJ IDEA también puede extender sus

capacidades mediante algunos plugins. En ambas versiones está habilitada esta funcionalidad, aunque solo la

versión de pago contiene alguno de los plugins oficiales más interesantes como Php o node.js. Es importante

destacar que, a pesar de contar con la posibilidad de añadir extensiones, la filosofía de este IDE es

diametralmente distinta a la de Eclipse o NetBeans. Aquí no existe una estructura modular donde la práctica

totalidad de las funciones la ejecutan componentes separables del núcleo, sino que se cuenta con una base sólida,

la cual implementa las funciones básicas para la programación, ejecución, depuración, etc., de tal forma que los

plugins solo dan soporte a ciertas tecnologías asociadas a Java o JavaScript. Existe la posibilidad de que las

nuevas versiones del producto incluyan nuevas funciones o características en el núcleo, como ocurrió con la

implementación de soporte para Python o Ruby en la edición Ultimate, los cuales no fueron extendidos como

un plugin independiente. Sin embargo, IntelliJ IDEA permite instalar módulos de terceros, permitiendo a la

comunidad suplir algunas carencias.

IntelliJ IDEA es un entorno de desarrollo muy interesante, tal y como han acreditado varios estudios [51], donde

suele destacar en el soporte a la programación Java, ofreciendo mejoras en funciones como el autocompletado

o la refactorización de código sobre sus competidores. Además, es el IDE más cohesionado de los estudiados,

pero carece del ecosistema de extensiones que tienen NetBeans y, fundamentalmente, Eclipse. Sin duda es un

serio candidato para todo desarrollo con Java, lo que le ha permitido alcanzar mayores cuotas de mercado con

el paso del tiempo hasta el punto de ser escogido por Google como base para el IDE oficial de Android, Android

Studio. Además, es una opción ganadora para comenzar a desarrollador, ya que es más accesible que sus

competidores. A la hora de escoger entre este IDE y Eclipse conviene tener en cuenta que se trata de dos

aplicaciones con filosofías diferentes, por lo que no hay una opción mejor que la otra. En esta ocasión ha pesado

más la posibilidad de conocer una plataforma tan versátil como Eclipse, altamente implantada en el mercado

laboral y en la comunidad, que optar por un entorno de desarrollo más sólido. Probablemente, de trabajar en un

proyecto más complejo hubiera sido más interesante contar con la solidez de IntelliJ IDEA.

Page 45: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

45

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

45

4.9.2.3 NetBeans

NetBeans IDE [52] es un IDE multiplataforma de código libre fundado por Sun Microsystems a finales del año

2000. Actualmente Oracle Corporation (comprador de Sun) sigue siendo la principal impulsora del proyecto.

Al igual que Eclipse puede catalogarse como un entorno de desarrollo de tipo toolkit, ya que está diseñado para

dotar a la comunidad de libertad para extender su capacidad gracias a los Módulos o Add-ons Packs. Como

puede suponerse, ya que comparten filosofías, su arquitectura recuerda a la de Eclipse: la práctica totalidad de

las funcionalidades la realizan módulos, de tal forma que el usuario podría quitar y añadir estos plugins a su

antojo para personalizar su herramienta de trabajo. Esto se lleva hasta el extremo, por lo que hasta la

funcionalidad Java es realizada por un módulo. Soporta otros lenguajes tan dispares como C/C++ o PHP, aunque

se utiliza principalmente para Java.

Es interesante destacar que está desarrollado sobre la plataforma NetBeans, un framework diseñado para facilitar

la creación de aplicaciones de escritorio para la API Swing (Java) de Oracle. No es extraño encontrar confusiones

entre la plataforma y el IDE.

Tiene una interesante presencia en el sector empresarial, además de contar con una potente comunidad de

usuarios. Cuenta con el inconveniente de que su ecosistema de extensiones no es comparable al de Eclipse, lo

que le deja por detrás de dicha alternativa en una categoría demasiado similar. Sin embargo, no son pocos los

usuarios que señalan a NetBeans como su IDE favorito, destacando que es más sólido que su competidor. Al

igual que ocurría con IntelliJ IDEA, al no estar desarrollando un proyecto de demasiada envergadura no es

necesario sacrificar las ventajas de Eclipse.

4.9.2.4 JDeveloper

JDeveloper [53] es otro IDE multiplataforma desarrollado por Oracle Corporation desde 1998. Es el único de

los analizados que no dispone de ninguna versión bajo licenciada de código libre, aunque sí es gratuito.

Es un entorno de desarrollo centrado en Java y lenguajes adyacentes (JavaScript, PHP, etc.), por lo que puede

clasificarse entre los entornos centrados en un lenguaje, como era el caso de IntelliJ IDEA. Eso no le impide, al

igual que al programa de JetBrains, contar con la posibilidad de extender sus funciones con plugins o módulos.

En este caso nos encontramos con la menor gama de extensiones de todos los IDEs reseñados. Se debe a que

Oracle JDeveloper está diseñado para optimizar su interconexión con otras aplicaciones, frameworks o librerías

de Oracle, lo cual le dota de tremenda utilidad para determinados desarrollos, pero provoca que la comunidad

no busque extender sus características más allá de las imprescindibles. En el caso concreto del proyecto

presentado en el presente documento, el uso de una base de datos Oracle no es condición suficiente para justificar

la elección de este IDE, pues no aporta ninguna ventaja sobre sus competidores. A pesar de eso se ha considerado

necesario tener una breve introducción a este producto, más aún si se tiene en cuenta que es el entorno en el que

está programado el SQL Developer de Oracle, el IDE de Base de Datos empleado en la aplicación.

Page 46: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Análisis de tecnologías

46

46

Resumen del análisis de tecnologías empleadas en el proyecto

En las líneas superiores se ha dedicado el espacio suficiente para analizar todas y cada una de las tecnologías

empleadas en el proyecto, realizando una adecuada comparativa con el resto de opciones existentes en el

mercado y justificando las elecciones realizadas. En general, se han empleado una serie de elementos recurrentes

en las argumentaciones: se ha intentado apostar, en la medida de lo posible, por tecnologías de código abierto,

con una amplia comunidad detrás y con las mayores garantías posibles en fidelidad. Junto a estos puntos se ha

valorado el futuro de todos los elementos implicados, pues se está diseñando un proyecto en un ámbito

claramente innovador, en el que emplear una tecnología con pronta fecha de caducidad reduciría el impacto que

nuestro trabajo pudiera tener en el mercado o en la comunidad.

La extensión de este capítulo y la enorme cantidad de tecnologías comparadas dan cuenta de la complejidad del

proyecto diseñado, en el que se han abordado numerosos frentes: desde la creación de varios módulos o

componentes software independientes hasta el diseño de una base de datos, desde la parametrización de un

clúster de servidores de colas de mensajes distribuidas hasta la elección de componentes hardware para la

integración física con biodispositivos.

Además, tal y como se comentaba al inicio, la labor realizada a lo largo de este capítulo se considera

imprescindible, pues constituye un elemento básico sobre el que construir la descripción detallada del proyecto.

O, en otras palabras, comentar y justificar las tecnologías empleadas en el desarrollo de la aplicación IoMT es

un requisito irrenunciable que se debe satisfacer antes de abordar los pormenores de la solución realizada.

Page 47: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

47

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

47

5 DESCRIPCIÓN DE LA PROPUESTA

n este apartado se va a entrar en detalle de la solución adoptada, explicando paso a paso las decisiones

tomadas en función de las tecnologías escogidas y para cada uno de los tres sectores en los que podemos

dividir el conjunto de aplicaciones y herramientas que componen este proyecto: integración con

biodispositivos para recuperar la información biomédica de los pacientes, almacenamiento e intercambio de

dichos datos y visualización de los mismos.

A lo largo del capítulo se deberá abordar con profundidad la arquitectura diseñada para dar cabida a todos los

componentes del proyecto. Una vez comentada la arquitectura, que establece las relaciones entre todos los

elementos, se entrará en detalle de cada uno de estos componentes, empleando la siguiente lógica:

- Primero se abordarán los aspectos exclusivos de la integración con los biodispositivos.

- En segundo lugar, se tratará la parte de la solución dedicada al almacenamiento e intercambio de la

información.

- Por último, se abordará el software específico creado para el proyecto. Aunque se ha diseñado un

módulo para cubrir cada una de las funcionalidades, todos cuentan con una serie de elementos comunes

agrupados en pequeños proyectos reutilizables. Dentro de este apartado se ha optado por encarar

primero los módulos comunes antes de analizar los módulos principales de integración,

almacenamiento y visualización, por este orden.

Arquitectura

5.1.1 Diseño funcional

Para comprender las decisiones tomadas en el diseño del presente proyecto conviene comenzar citando los

requisitos de partida que se han creído imprescindibles:

- Se realizará un software de recolección de datos para recuperar la información procedente de los

biodispositivos gracias al hardware de integración. Dicho software contará con un diseño versátil, que

permita la elección de los diferentes protocolos que, en cada caso, se emplearan en la comunicación con

los biodispositivos.

- Formará parte del presente proyecto una herramienta básica de visualización de la información extraída

a través del software de recuperación de datos.

- Será imprescindible almacenar la información recuperada en una base de datos.

- El diseño debe ser lo suficientemente robusto como para permitir la ampliación de funcionalidades en

el futuro. Por ejemplo, parece interesante diseñar el sistema de forma que se facilite la creación de un

módulo de explotación avanzado de la información, que saque estadísticas o genere informes; en la

línea de lo expuesto en la presentación del proyecto.

- Se va a trabajar con una información de especial importancia, para la que habrá que contar con un

sistema que garantice que no se pierda ni se corrompan los datos.

A todo lo anterior hay que sumar un nuevo requisito: el caudal de información a tratar es considerable, aunque

no pueda parecerlo a simple vista. Para ello, debemos distinguir entre dos tipos de constantes médicas con las

que trataremos en el proyecto:

- Datos discretos: medidas concretas realizadas cada cierto tiempo, a baja frecuencia. Por ejemplo, es

habitual expresar la frecuencia cardíaca en pulsaciones por minuto, de forma que, por definición, no

tiene sentido que recibamos esta constante con otra frecuencia. En definitiva, este tipo de datos suelen

E

Page 48: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

48

48

representar datos medios o estadísticos. Para hacer una explicación gráfica accesible, este tipo de

mediciones se corresponden con los valores numéricos de los monitores de pacientes que estamos

acostumbrados a ver tanto en los centros de atención sanitaria como en la ficción.

- Datos continuos: aquí hablamos de información médica que se mide constantemente, a alta frecuencia.

Se diferencian de las anteriores en que no representan valores medios ni agrupaciones, sino la evolución

temporal de una determinada característica del paciente. Por ejemplo, un caso conocido es el

electrocardiograma (ECG), que registra la actividad eléctrica del corazón. Se trata de una gráfica con

una característica forma periódica, con picos de actividad durante los latidos del paciente. Sin embargo,

en ese caso no interesa solo la medición del número de latidos sino observar continuamente la actividad

del corazón para poder analizar si existe alguna anomalía en su funcionamiento. Por tanto, aquí nos

encontramos con una señal analógica que debe pasar por un sistema de muestre para ser convertida en

una señal digital explotable.

Esta información genera un gran caudal de datos, pues dependiendo de la precisión podemos

encontrarnos con ondas con una frecuencia de muestreo de hasta 500 valores por segundo. Por tanto,

no solo el hardware elegido deberá tener capacidad suficiente para procesar varias variables biomédicas

a tiempo real, sino que toda esta información también debe ser tratada por varias aplicaciones, lo que

condicionará el diseño técnico del software.

Figura 5-1. Tipos de constantes médicas, continuas y discretas.

5.1.2 Prototipo inicial de la arquitectura del proyecto

Con todo lo anterior podemos montar un prototipo del proyecto que exprese las relaciones entre todas las partes

y ayude a comprender lo comentado hasta el momento:

Figura 5-2. Primer prototipo de MEDIPi

Page 49: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

49

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

49

Aplicación Software Icono Descripción

Device Data Acquisition

DDA

Componente software encargado

de establecer la comunicación con

los biodispositivos y recuperar la

información biomédica.

CHART

Aplicación de visualización de las

constantes biomédicas de los

pacientes en tiempo real.

Figura 5-3. Leyenda primer prototipo de MEDIPi

En la figura superior tenemos una versión del primer esquema del proyecto. De un vistazo observamos no solo

las relaciones entre los diferentes componentes del software, sino también podemos contemplar qué módulo del

software correrá sobre qué componente hardware.

Con todos estos componentes interrelacionados cubriríamos los requisitos funcionales que hemos tomado como

base de la construcción de la solución MEDIPi: el recolector de información, corriendo sobre un determinado

hardware de integración que elegiremos más adelante y a través de los puertos, físicos o no, necesarios según

cado protocolo, almacenará las constantes biomédicas proporcionadas por los biodispositivos en la base de datos.

Por último, el visor de datos leerá de base de datos para representar adecuadamente las gráficas de las constantes

recopiladas.

Sin embargo, este prototipo cuenta con varias limitaciones importantes en dos de los puntos marcados en el

análisis funcional. En primer lugar, hemos considerado fundamental la creación de una estructura lo

suficientemente sólida como para permitir fácilmente la expansión de las funcionalidades existentes y/o la

adición de nuevos módulos como podrían ser el tratamiento masivo de datos, aplicaciones de gestión de historia

clínica, etc. No en vano estamos hablando de la suite MEDIPi, enfocando desde el inicio el proyecto como un

conjunto de soluciones dedicadas a los diferentes aspectos relacionados con la información biomédica de los

usuarios de un sistema sanitario. Este prototipo propone solucionar este problema simplemente construyendo un

sistema de almacenamiento de datos lo suficientemente modularizado como para que los nuevos módulos

software se cimienten en él, leyendo la información allí almacenada y realizando con ellas sus labores

específicas. No es una solución incorrecta, pero sí demasiado básica dadas las características del contexto en el

que nos ubicamos. Hemos hablado antes de múltiples constantes recuperadas para cada usuario, algunas con

cientos de muestras por segundo. El software y el hardware de integración tiene capacidad suficiente para tratar

con ellas, pero para que puedan ser explotadas por terceros deberían almacenarse en base de datos en su totalidad,

no solo las de un paciente, si no las de todos. He aquí la principal diferencia: mientras que el hardware y el

software de recolección de datos solo tratan información recuperada para cada paciente, la base de datos

almacena la de todos. Por tanto, este modelo exige una base de datos inmensa. De partida esto provoca la

necesidad de invertir en un servidor potente, con enorme capacidad de almacenamiento, no solo para la base de

datos, sino para cada lugar en el que se vaya a ejecutar alguno de los módulos que necesiten acceder a la

información biomédica del paciente. Es decir, si uno de los posibles añadidos a los elementos existentes

actualmente a la suite es una aplicación web esta debería ejecutarse sobre un servidor con capacidad de

procesamiento potente. Pero el problema no es solamente ese: supongamos que queremos abordar un módulo

de explotación de datos (big data). Las soluciones existentes, como Hadoop [54], son conscientes de las

limitaciones de procesamiento derivadas de emplear como sistema de entrada una base de datos relacional

clásica. De hecho, en los últimos tiempos estamos observando el ascenso de las bases de datos NoSQL en este

tipo de trabajos. Aun así, incluso utilizando bases de datos relacionales deben realizarse modificaciones sobre la

estructura clásica: es inabordable emplear un servidor centralizado donde se ubiquen todos los datos, optando

siempre por sistemas de ficheros distribuidos como soporte a esas bases de datos.

Page 50: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

50

50

Figura 5-4. Esquema del sistema de ficheros distribuidos HDFS empleado por Hadoop.

Por tanto, con este prototipo inicial estamos construyendo una arquitectura que, efectivamente, va a permitir la

adición de módulos con nuevas funcionalidades, pero conocemos que estamos generando limitaciones de partida

para una de las funcionalidades que, a primera vista, parecen más interesantes de añadir a la suite.

La primera alternativa a este prototipo es evidente: si el problema radica en la base de datos podemos optar por

cambiarla y emplear un sistema de ficheros distribuidos sobre el que ubicar nuestra base de datos relacional o

NoSQL. Sin embargo, esto implica dificultar enormemente la creación de la misma, el modelado de datos y su

manteamiento, solamente para evitar limitaciones en una característica que ni siquiera se plantea abordar de

momento.

5.1.3 Modelo definitivo

Hasta ahora hemos llegado a una conclusión: el alto volumen de datos que se deberán manejar nos obligan a

replantear la arquitectura del primer prototipo, consiguiendo armonizar la existencia de una base de datos SQL

estándar que no sea excesivamente difícil de manejar por los módulos básicos de la suite con una herramienta

que permita a la vez abordar de forma escalable y sólida la explotación de la información recolectada. Para

abordar este conflicto debemos replantear la arquitectura, quitando el foco en el punto débil de la misma: la base

de datos.

En el modelo definitivo, a diferencia del prototipo comentado en el apartado previo, el dispositivo encargado de

realizar el intercambio de información entre las distintas aplicaciones se desplaza de la base de datos a una

herramienta que permita la comunicación de grandes cantidades de datos de forma escalable y asegurando la

integridad de la información. Por tanto, en vez de que la aplicación de recolección de datos envíe la información

a la base de datos y el resto de módulos lean de ella se empleará un sistema de intercambio alternativo de

información en el que “escribirá” el módulo de recuperación de información y del que “leerán” los módulos que

así lo deseen. En resumen, gracias a este cambio, la base de datos es solo uno de los componentes que “leen” de

este sistema de intercambio de información, permitiendo que muchos otros también lo hagan. Hemos construido

una arquitectura que cumple con la condición de escalabilidad y evita limitaciones en la explotación de la

información que puedan realizar otros módulos. Como toda decisión, esta también tiene sus puntos débiles, sus

inconvenientes: hemos añadido más complejidad a la estructura. Será tarea fundamental del diseño de dicho

sistema intermedio escoger una herramienta y una configuración de la misma que reduzcan este problema.

Page 51: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

51

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

51

Surgen varios aspectos a tratar tras este cambio de arquitectura, que implicarán replantear y remodelar algunas

de las deducciones que se planteaban en el primer prototipo.

Lo primero es partir de que, si ahora vamos a tener un “nodo” de intercambio, una herramienta para la

comunicación de la información, deberá existir por fuerza un programa, un módulo de la suite MEDIPi que se

encarga de leer de dicha herramienta y de persistir la información en base de datos. Aplicando estos cambios

obtenemos un esquema general de la arquitectura definitiva planteada.

Figura 5-5. Esquema general de la arquitectura

Aplicación Software Icono Descripción

Device Data Acquisition

DDA

Componente software encargado

de establecer la comunicación con

los biodispositivos y recuperar la

información biomédica.

SAVER

Módulo que persistirá la

información recopilada por DDA

en base de datos

CHART

Aplicación de visualización de las

constantes biomédicas de los

pacientes en tiempo real.

Figura 5-6. Leyenda esquema general de la arquitectura

A simple vista ya se pueden sacar algunas conclusiones: existe un destacable aumento de complejidad con

respecto al primer prototipo y se ha redefinido el papel de la base de datos en la suite. Más adelante

comentaremos el primer punto, pero de momento centrémonos en cómo queda finalmente la arquitectura del

proyecto:

Page 52: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

52

52

Componentes de MEDIPi: Modelo definitivo

Sector Hardware Software

Integración con biodispositivos Raspberry Pi 2 DDA

Almacenamiento y transmisión Base de datos Clúster SAVER

Visualización PC Cliente CHART

En el prototipo DDA lee y escribe en la base de datos: lee la información de configuración del programa

(incluyendo los datos de los biodispositivos con los que debe integrarse), así como otros parámetros; y escribe

las constantes biomédicas directamente. Ahora el software de recolección lee de base de datos igual que antes,

pero escribe toda la información recuperada en el sistema de intercambio de datos, representado por la nube en

el esquema general.

Como consecuencia de lo comentado anteriormente, necesitamos un nuevo módulo software que ejecute la tarea

de recuperar datos de dicho sistema y escribirlos en base de datos. Esa es la labor de MEDIPi Saver,

representado en el esquema en la esquina inferior derecha. Ahora podemos considerar la base de datos como

“una copia de seguridad” de la información intercambiada por el sistema, un lugar en el que almacenamos la

información antigua. Esto nos permite realizar algunos cambios en el planteamiento: muchas aplicaciones de la

suite usarán la base de datos, pero esta ya no es el punto central del intercambio de los datos biomédicos. En el

apartado correspondiente al hardware de integración se realizó un análisis acerca de dichos datos, estableciendo

una clasificación básica entre datos continuos y discretos. Junto a lo anterior, en párrafos previos hemos hecho

hincapié en los problemas que nos producen las señales continuas, de gran peso, comentando la necesidad que

existe en sistema de tratamiento masivo de datos de emplear bases de datos no relacionales (por definición más

escalables) e incluso fragmentar el sistema de ficheros sobre el que corre la base de datos. Esta nueva arquitectura

nos permite solucionar todo esto: ahora la base de datos es, desde el punto de las constantes biomédicas, un

elemento de almacenamiento de la información antigua, por lo que puede llevarse a cabo un filtrado de dichos

datos. Al fin y al cabo, ahora existe otra manera de acceder a toda la información. Saver será el encargado de

aplicar ese filtrado, que partirá de no almacenar las constantes continuas, reduciendo considerablemente el

tamaño de la base de datos. Además, podrán diseñarse otros filtros que complementen al anterior, dando

empaque a este módulo del software. Al igual que DDA, Saver necesitará acceder a ciertos parámetros de

configuración ubicados en la base de datos.

Al igual que el resto de módulos software de la suite MEDIPi, Chart también sufre algunos cambios como

consecuencia de la nueva arquitectura. Ahora no necesita leer de base de datos la información biomédica, que

llegará a través del sistema de intercambio, reduciendo el acceso a la base de datos a la información general:

configuración, datos del paciente, etc.

En general encontramos “dos puntos de acceso” para los módulos software presentes o futuros: el sistema de

intercambio (clúster Kafka de colas de mensajes) y la base de datos, pudiendo escoger uno u otros según necesite.

Por ejemplo, una aplicación de gestión de historia clínica es probable que no necesite los datos a tiempo real de

los pacientes y le baste con lo existente en base de datos, mientras que un sistema de big data probablemente

recupere los datos mediante el sistema de intercambio, siendo probable incluso que emplee una base de datos

propia más adecuada para sus labores que se pueble a partir de dichos datos. Finalmente hemos concluido una

arquitectura sólida y escalable, en la que conviven la base de datos y un sistema de intercambio de datos masivo,

siendo ambos imprescindibles: mientras que el sistema de intercambio de datos masivo permite cumplir

adecuadamente los requisitos funcionales y la existencia de la base de datos es insustituible, pues en algún lugar

debe estar persistida la configuración de las aplicaciones y la información básica de los usuarios del sistema:

datos del paciente, fechas, constantes, etc.

Page 53: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

53

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

53

Hardware de integración con biodispositivos

El primer paso en el planteamiento del proyecto es sin duda realizar el análisis de cómo debe ser la integración

física con los biodispositivos médicos. Empezaremos con una clasificación básica de los elementos con los que

deberá integrarse la solución desarrollada: podremos diferenciar entre mecanismos de soporte médico existentes

en el mercado (como monitores cardíacos, de presión, ventiladores automáticos, bombas de infusión de

medicamentos, etc.) y dispositivos no comerciales, como sensores o soluciones libres empleados en ámbitos

académicos o divulgativos. El presente proyecto pretende caminar en ambos frentes, ofreciendo una herramienta

lo suficientemente sólida como para dar soporte a biodispositivos empresariales usados en las unidades de

atención médica de hospitales y a dispositivos más básicos y accesibles.

Figura 5-7. A la izquierda, un sensor de pulso cardíaco. A la derecha, un ventilador de General Electrics

5.2.1 El estándar HL7

El protocolo HL7, (Health Level Seven) de capa de aplicación en el modelo OSI, está diseñado para intercambiar

todo tipo de información médica como admisiones, traslados, informes, constantes del paciente, etc. Se ubicará

normalmente sobre un protocolo propio de sesión MLLP (Minimum Lower Layer Protocol) [55], aunque es

posible encontrarlo sobre una gran variedad e capas de sesión como ebXML (Electronic Business using

eXtensible Markup Language), SOAP (Simple Object Access Protocol), etc. Sea cual sea el protocolo de sesión,

es poco habitual que no esté construido sobre TCP/IP, de forma que los productos que usan HL7 transmiten la

información finalmente a través de un puerto Ethernet o incluso a través una interfaz WiFi.

Tras este protocolo se encuentra la organización HL7 International que, desde 1987, apuesta por dotar a la

comunidad médica de estándares que permitan la interoperabilidad de datos mundial. Para ello lleva a cabo una

estrategia en múltiples frentes:

- Desarrollar el estándar HL7 buscando una sintaxis coherente y extensible que estructurar información

en salud y apoyar los procesos de atención al paciente, para ser intercambiada entre aplicaciones de

software, conservando al mismo tiempo la semántica de la información.

- Colaborar con otras organizaciones desarrolladoras de estándares y organismos nacionales e

internacionales de estandarización (por ejemplo, ANSI e ISO), para desarrollar infraestructuras de

dominios de información en salud para promover el uso de estándares compatibles.

HL7 define simplemente una estructura, un conjunto de segmentos y de campos que se deben cumplimentar, así

como el contenido de cada uno. Sin embargo, no se indica qué formato exacto debe tener cada campo, por lo

que dos dispositivos que utilicen HL7 tendrán una estructura similar, pero la información no será totalmente

intercambiable. Por ejemplo, un dispositivo puede informar de una constante vital indicando el nombre de la

variable biomédica, mientras que otro puede emplear un código de identificación; uno puede indicar las unidades

en el sistema internacional, mientras otro use el estándar ISO/IEEE 11073. Incluso es posible encontrar el mismo

dato en diferentes campos según se haya interpretado la especificación. Por tanto, HL7 nos ofrece una gran base

para la estandarización de la exportación de datos, pero aun así será necesario conocer los detalles concretos de

la implementación que ha hecho cada proveedor.

Para terminar este breve análisis del protocolo HL7, se va a detallar algunas características básicas de su

Page 54: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

54

54

representación. Los mensajes HL7 se suelen informar de dos maneras totalmente diferentes: XML o ER7. Este

último no es más que una representación del valor de cada campo separado por el carácter |, tal y como se puede

ver en el siguiente ejemplo.

MSH|^~\&|CERNER||PriorityHealth||||ORU^R01|Q479004375T431430612|P|2.3|

PID|||001677980||SMITH^CURTIS||19680219|M||||||||||929645156318|123456789|

PD1||||1234567890^LAST^FIRST^M^^^^^NPI|

OBR|1|341856649^HNAM_ORDERID|000002006326002362|648088^Basic Metabolic

Panel|||20061122151600|||||||||1620^Hooker^Robert^L||||||20061122154733|||F|||||

||||||20061122140000|

OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20061122154733|

HL7 tiene evidentes aspectos positivos: toda apuesta por estandarizar la exportación de biodatos actualmente

pasa sí o sí por este estándar, no existiendo competidores reales en el mercado. Además, como se ha comentado

hace unas líneas, HL7 apuesta por abordar la práctica totalidad de información clínica de los pacientes, no

quedando reducido al campo de la integración con biodispositivos. Esto es realmente interesante, aunque pocos

centros sanitarios lo emplean para las constantes médicas de los enfermos sí es mucho más habitual que sirva

como base en el intercambio de información administrativa (altas, traslados, informes, etc.) Sin embargo, los

aspectos negativos que rodean al protocolo no son menores: solo los biodispositivos de los últimos años están

apostando decididamente por implementarlo como mecanismo de exportación de datos, lo que, unido a la

elevada vida media de dicha maquinaria, provoca que sea realmente difícil encontrar un centro sanitario en el

que una cantidad representativa de sus biodispositivos soporte HL7. Un rápido vistazo al mercado actual

corrobora la afirmación anterior: los productos alternativos a este proyecto no se centran en implementar un

servidor de HL7, sino que siempre trabajan con protocolos propietarios específicos, pues es el único modo de

dar soporte a un número razonable de dispositivos. A lo anterior hay que sumar dos cuestiones menores: se

pretende que el actual proyecto sea extensible a sensores no comerciales (que no suelen trabajar con HL7) e

incluso que se estudie la posibilidad de influir en el comportamiento del dispositivo, algo que queda totalmente

fuera del planteamiento del estándar.

En un futuro, sería interesante abordar una herramienta que permita recibir y procesar información HL7. Como

ya se ha comentado, HL7 no es solamente un estándar para la exportación de datos biomédicos de los pacientes,

sino que también permite el intercambio de otros mensajes administrativos y clínicos. Por tanto, abordar este

modo de integración con biodispositivos implica diseñar una arquitectura compatible con los otros usos del

estándar, algo totalmente fuera del alcance de este proyecto. Eso sí, parece evidente que estamos ante un gran

cambio de enfoque: basta con un servidor HL7 colocado en la red para recibir los mensajes y procesarlos, sin

necesidad de recurrir a componentes hardware específicos como en el enfoque anterior.

5.2.2 Protocolos propietarios

Una vez comentado por qué se ha descartado una integración con biodispositivos basada en HL7, se pasa a

analizar el enfoque multiprotocolo. Este enfoque consiste en diseñar una aplicación capaz de alternar entre un

conjunto variado de protocolos, generalmente propietarios, cada uno de los cuales se comunicará mediante un

puerto diferente (puertos paralelos, RS232, USB, etc.). Para abordar adecuadamente el diseño de una tarea tan

ambiciosa debemos contar con un hardware de integración para conectar uno o varios dispositivos, de forma

que el software que corra sobre él traslade la información recibida a un formato interno estándar y la envíe al

sistema de almacenamiento / intercambio de información adecuado. Bajo este prisma es inmediato obtener la

primera característica sobre la que se cimentará el hardware de integración del proyecto: la versatilidad. Por

tanto, se descarta diseñar un componente electrónico propio. Un desarrollo específico obligaría a cambiar el

enfoque del proyecto, que no es otro que la integración del mayor número de soluciones tecnológicas posibles

de forma que los usuarios del mismo, profesionales sanitarios u otros, puedan explotar la información biomédica

procesada por los mismos. Dicho enfoque es irrenunciable, ningún cliente optará por implementar una solución

para centralizar información si los elementos soportados son demasiado limitados.

Otra posibilidad sería desarrollar un dispositivo electrónico que disponga de los conectores básicos del mercado,

por ejemplo, una placa con varios USB, un puerto Ethernet y pines para sensores, pero, evidentemente, ya

Page 55: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

55

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

55

encontramos placas que realizan perfectamente esta función a precios populares.

Junto a la necesidad de un componente hardware lo suficientemente versátil como para cubrir la comunicación

con diversos productos va unida la escalabilidad del mismo; es decir, la cantidad de dispositivos / protocolos

soportados y su facilidad para que esto aumente en el futuro. Con el enfoque elegido, nos encontraremos en un

escenario en el que nuestro hardware de integración raramente abandonará la dinámica 1 puerto – 1 dispositivo.

Es aquí donde se plantea el asunto de la escalabilidad, intrínsecamente relacionada al punto anterior. Previamente

se ha justificado la preferencia por un dispositivo hardware ya existente en el mercado, dado la poca

especificidad de las conexiones (casi siempre estándares) y la amplia versatilidad necesaria. Ahora a esto

debemos sumarle el mayor número posible de conexiones, teniendo en cuenta que cada conexión podría ser

totalmente diferente (puerto serie, paralelo, USB, etc.). Bajo esta concepción parece convincente plantearse la

necesidad de dotar a nuestro hardware de la mayor cantidad de puertos, del tipo más “estándar” posible. Dicho

puerto debería completarse con un adaptador a otro tipo de conexión cuando sea necesario. Esto facilita aumenta

exponencialmente la versatilidad y escalabilidad del software, aunque no cierra totalmente el coste de

implantación: si en el futuro se pretende dar soporte a un nuevo dispositivo será necesario incorporar al hardware

el adaptador adecuado, con el consiguiente desembolso. Dado el pequeño precio de los adaptadores existentes

en el mercado entre puertos estándares, se entiende que nos encontramos ante la solución óptima, encontrando

un punto intermedio adecuado entre los factores que estamos considerando.

Figura 5-8. La Raspberry Pi 2 B ofrece 4 puertos USB a bajo coste

Quedan por cerrar un par de asuntos importantes, generalmente relacionados entre sí: coste y rendimiento.

Conviene recordar que pretendemos correr sobre el hardware un programa encargado de comunicarse con varios

dispositivos a la vez, recuperando las constantes biomédicas del paciente, procesándolas y enviándolas a una

base de datos para su almacenamiento. En principio, no parece una tarea excesivamente exigente, que requiera

de una velocidad de procesamiento de datos elevada, aunque para analizar adecuadamente este punto debemos

observar con qué velocidad envía información los dispositivos médicos. Dado que planteamos una integración

versátil que permite la adaptación del mayor número posible de dispositivos, la pregunta debe ser reformulada

para pasar de ¿con qué velocidad recibiremos datos? a ¿cuál es la tasa máxima de datos que deberemos soportar?

Antes de acercarnos a las conclusiones de este apartado del análisis, conviene tener claro la función del proyecto:

la idea es recopilar toda la información posible del paciente para almacenarla y ser explotada posteriormente. Es

decir, deberemos estar preparados para recuperar toda la información disponible, de tal forma que corresponde

a otra solución, fuera del alcance de este proyecto, decidir cuánta cantidad de información es realmente necesaria.

Aclaremos a qué nos referimos con la frase anterior: es habitual que en los centros sanitarios los profesionales

de enfermería comprueben las constantes de los pacientes con una periodicidad elevada, cercana a la hora,

excepto en situaciones de crisis. La presente solución no debe entrar en estas cuestiones, solo procesando datos

de acuerdo a determinados patrones médicos, sino que debe almacenar toda información recibida, siendo tarea

posterior filtrar o explotar como se desee los datos recolectados.

Llegado a este punto es fácil comprender que la capacidad de procesamiento dependerá de dos variables:

cantidad de constantes y frecuencia con la que se esperan recibir datos de cada una. Evidentemente, la capacidad

de procesamiento de la información está íntimamente relacionada con la cantidad de constantes a recibir. Incluso

si contemplamos solo de las denominadas variables discretas, no es lo mismo procesar cinco variables por

minuto que cien por segundo. Por su parte, la frecuencia con la que recibiremos los datos no es problemática si

hablamos de constantes discretas, pues es raro trabajar con resoluciones inferiores al segundo, mientras que en

Page 56: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

56

56

el caso de las señales continuas la tasa de muestreo suele situarse en las 500-1000 muestras por segundo.

Partiendo de lo anterior, parece adecuado concluir que el principal dato para realizar la correcta caracterización

de nuestro sistema es la tasa de muestreo de las señales continuas que debemos procesar a tiempo real. No se

trata de una frecuencia especialmente elevada, por lo que muchas de las placas de bajo coste existentes en el

mercado (Arduino, Raspberry, etc.) deben tener capacidad suficiente para trabajar con ellas siempre que no

hablemos de una cantidad desmesurada de variables continuas. Hasta ahora, esas variables eran solamente las

mostradas en las pantallas de los dispositivos médicos (fundamentalmente monitores, aunque también otros

elementos auxiliares como ventiladores); por lo que nos moveremos sobre la docena de variables en el más

exigente de los casos.

Con cuatro puertos USB, la Raspberry Pi 2 debe ser capaz de soportar las bioseñales de cuatro dispositivos a la

vez. Esta placa hardware cuenta con un procesador cuatro núcleos de 900 MHz, lo que la capacitar de sobre para

actuar como hardware de integración en nuestro proyecto.

Antes de terminar este punto es necesario abordar el único objetivo del proyecto relacionado con la integración

que no se ha comentado hasta el momento: la posibilidad de dotar a las aplicaciones propias, o a programas de

terceros a través de internet, de la capacidad de influir en el comportamiento de los biodispositivos soportados.

La idea inicial pretendía conocer las posibilidades de interacción bidireccional con estos dispositivos,

permitiendo a las aplicaciones setear parámetros o cambiar su configuración, con el objetivo de abrir la puerta a

desarrollar productos más inteligentes. Si todo lo anterior es realizable, es posible imaginar un escenario en el

que determinada información biomédica del paciente pueda provocar un cambio automático en el

comportamiento de los dispositivos, o incluso permitir a los facultativos un control remoto de los mismos.

Durante el apartado anterior se ha comentado que esta funcionalidad escapa totalmente del ámbito del estándar

HL7, siendo solamente posible bajo un enfoque de comunicación basado en protocolos propietarios, Esto es

cierto, existen protocolos propietarios de comunicación con biodispositivos que permiten a los ordenadores

modificar su comportamiento, en la línea de lo comentado en este párrafo. Sin embargo, no existe un patrón

común, un conjunto de funcionalidades habituales soportadas por los protocolos; es más, el número de

protocolos que ofrecen algo más que la mera exportación de datos es insignificante. Por tanto, se concluye que

los dispositivos actuales del mercado no están enfocados a esta tarea, por lo que no se puede abordar en el

presente proyecto.

5.2.3 Adaptación entre puertos estándares

Tal y como se ha comentado en el punto anterior, será necesario complementar nuestro hardware de integración

con los adaptadores necesarios para otros puertos de entrada estándares. Como el caso más habitual será la

utilización de un adaptador USB – RS232 se ha considerado adecuado realizar un breve comentario sobre esta

parte del proyecto.

Page 57: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

57

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

57

Figura 5-9. Esquema de una adaptación RS232 (DB9) a USB

RS232 es una interfaz que designa una norma para el intercambio de una serie de datos binarios entre dos

extremos (1 a 1), mientras que USB es un bus, de tal forma que permite a más de un dispositivo conectarse a un

puerto USB, provocando que el estándar no solo describa las propiedades físicas de la interfaz (capa física) sino

también los protocolos necesarios para transmitir adecuadamente la información. Esto no se da en la

comunicación RS232, donde existe una gran libertad para configurar muchos parámetros de la comunicación.

Con frecuencia es habitual que las aplicaciones controlen la tasa de bits, número de bits de parada, número de

bits de datos y otros parámetros, algo impensable en el estándar USB. Por todo esto, la adaptación entre ambos

puertos no es inmediata, como se puede comprobar en la imagen ubicada encima del presente párrafo.

En lo referente al coste, es habitual encontrar adaptadores DB9 a USB por un precio ubicado entre los 5 y 10

euros.

Figura 5-10. Adaptador empleado en el proyecto

Page 58: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

58

58

Base de datos

Antes de abordar el software de recuperación de datos es conveniente analizar el modelo de datos empleado,

pues este condiciona numerosos aspectos del programa.

En los capítulos anteriores se ha comentado las distintas tecnologías que se pueden usar para implementar una

base de datos, realizando una comparativa entre las mismas y justificando la elección de una base de datos Oracle

11g. En dicho punto se realiza una adecuada explicación de los conceptos más básicos necesarios para operar

con una base de datos como la seleccionada. A continuación, se procederá a comentar la solución escogida,

detallando el modelo de datos de acuerdo a las características previamente documentadas.

5.3.1 Tablespace

Como comentamos anteriormente, las bases de datos Oracle tienen una estructura lógica que comienza con el

Tablespace. Se define un Tablespace para controlar la localización de los ficheros de datos, especificación de

máximas cuotas de consumo de disco, disponibilidad de los datos (en línea o fuera de línea), backup de datos,

etc. Como se está montando una base de datos pequeña y destinada, de momento, solamente a nuestro proyecto,

no tiene sentido establecer una configuración no única para estos parámetros. En general, es poco habitual la

existencia de varios Tablespace en bases de datos de tamaño medio, pues los gestores de la base de datos suelen

renegar de combinar políticas diferentes siempre que no sea estrictamente necesario. En nuestro caso,

planteamos un modelo de datos de una decena de tablas, por lo que se turna absurdo llegar a tal nivel de

complejidad como para combinar varios Tablespace.

Conviene tener en cuenta que las bases de datos Oracle ya cuentan con varios Tablespace de fábrica, necesarios

para su correcto funcionamiento. En la imagen siguiente, obtenida a través de la aplicación web que ofrece

nuestra base de datos Oracle (http://127.0.0.1:8080/apex/), podemos conocerlos y comprobar sus datos básicos.

Figura 5-11. Tablespace iniciales de una base de datos Oracle XE 11g R2

Se procede a comentar de manera muy genérica la utilidad de cada uno de estos tablespace [56, 57]

- SYSTEM: todas las bases de datos Oracle contienen un tablespace SYSTEM, creado automáticamente

con la base de datos. Este tablespace está siempre online cuando la base de datos está abierta. Se trata

de un diccionario de datos, es decir, un repositorio de metadatos que permite almacenar formatos,

significados, relaciones, uso, etc. de cada elemento de la base de datos.

- SYSAUX: es un tablespace auxiliar del tablespace SYSTEM. Algunos componentes de las bases de

datos usan este tablespace como su ubicación por defecto para almacenar información.

- UNDO: al igual que los anteriores, toda instalación de una base de datos Oracle cuenta con un

tablespace UNDO. Como su propio nombre indica se emplean para almacenar información necesaria

para realizar acciones de deshacer. En este tablespace no se pueden crear tablas.

- TEMP: tablespace para el almacenamiento de información temporal.

- USERS: tablespace empleado para almacenar información básica de usuarios.

Page 59: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

59

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

59

Comenzaremos a parametrizar la base de datos del proyecto conectándonos con los parámetros establecidos por

defecto para la base de datos seleccionada.

Figura 5-12. Parámetros de conexión por defecto de la base de datos

En este apartado solo tendremos que crear el tablespace, para lo cual ejecutaremos desde alguno de los entornos

de desarrollo de base de datos del proyecto (SQL Plus o SQL Developer) la instrucción:

CREATE TABLESPACE TS_MEDIPI DATAFILE

'C:/oraclexe/app/oracle/oradata/XE/MEDIPI.dbf' SIZE 500M AUTOEXTEND OFF

LOGGING

ONLINE;

En la que se indican los siguientes parámetros:

- Datafile: se comentó en el capítulo de tecnologías empleadas la estructura física de una base de datos

Oracle XE 11g R2. En resumen, un datafile es el fichero (o ficheros) físicos en los que se encontrará la

información del tablespace. En este caso se emplea una base de datos sobre una máquina con Windows,

por lo que se crea el fichero bajo la estructura generada en la instalación de la base de datos.

- Tamaño: en este caso se ha optado por un tamaño base de 500MB. Por motivos de seguridad, se

deshabilita la capacidad de aumento dinámico del tamaño del tablespace. Si nos quedamos sin espacio

deberemos redimensionar el tablespace manualmente.

- Logging: con esta opción quedan registradas las operaciones de DDL e inserciones de datos en tablas

en el sistema de log predeterminado de Oracle.

- Online: es la opción predeterminada, pues un tablespace debe estar online para poder trabajar

normalmente con él. Se opta por poner offline un tablespace cuando se requieren hacer algunas

operaciones especiales como copias de seguridad más rápidas, labores de restauración de datos, mover

un datafile sin cerrar la base de datos, etc.

5.3.2 Usuarios / Esquemas

Conviene recordar algunos aspectos de la relación entre usuarios y esquemas en el modelo de información que

manejan las bases de datos Oracle. Resumiendo, un esquema es una colección de objetos de base de datos,

Page 60: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

60

60

incluyendo estructuras lógicas, tales como tablas, vistas, secuencias, procedimientos almacenados, sinónimos,

índices, clústeres, y la base de datos de enlaces. Un usuario posee un esquema, que se crea automáticamente al

crear el usuario. En Oracle, un usuario solo puede tener un esquema, a diferencia de lo que ocurre en otras bases

de datos. De esta forma, la relación entre usuario y esquema puede simplificarse hasta indicar que son sinónimos.

Realmente esto no es así, un usuario es el propietario de los objetos y el esquema la agrupación lógica de los

mismos, pero puede considerarse aceptable la simplificación al haber una relación 1 a 1. Además, un usuario

puede acceder a los objetos de esquemas diferentes del propio, si tienen permiso para hacerlo.

En el presente proyecto se ha optado por establecer dos esquemas diferentes para escenificar las dos grandes

categorías que componen el modelo de datos. Funcionalmente, podemos dividir el modelo de datos en dos partes

claramente diferenciadas:

- Información general médica: entran en esta categoría todo objeto relacionado exclusivamente con

información médica. Por ejemplo, parece evidente que necesitaremos almacenar información del

paciente como nombre, apellidos, DNI, etc.

- Información de la integración: en una categoría totalmente distinta podemos encontrar la información

puramente enfocada a la integración. Por ejemplo, habrá que crear una tabla con los dispositivos

conocidos, sus parámetros, su asignación a cada raspberry en caso de que tengamos más de una

funcionando a la vez, etc.

Como se observa, estamos hablando de una clasificación meramente funcional, no técnica. Sin embargo,

recordemos que en las bases de datos Oracle los usuarios tienen asociado un esquema. Si creamos dos esquemas

diferentes, podemos tener dos usuarios distintos para manejar información funcionalmente diferente. Por

ejemplo, podríamos darle a un profesional sanitario acceso a la base de datos con el usuario del esquema de

información médica, de forma que, ya sea directamente o a través de una aplicación concreta, pueda modificar

la información allí almacenada para añadir pacientes, modificar sus datos, etc. Sin embargo, no podría acceder

a la información de la integración con los dispositivos si configuramos adecuadamente la base de datos. Además,

un correcto modelado de la base de datos debe tener en cuenta la posible expansión del proyecto. Con esta

clasificación permitimos que se pueda extender el esquema de información médica para, por ejemplo,

compartirlo con una aplicación encargada de gestionar la historia clínica de un paciente.

Por tanto, vamos a crear dos usuarios: HEALTH y DATA_ACQ.

CREATE USER HEALTH

IDENTIFIED BY "HEALTH"

DEFAULT TABLESPACE TS_MEDIPI

TEMPORARY TABLESPACE TEMP

PROFILE DEFAULT

ACCOUNT UNLOCK;

GRANT CONNECT TO HEALTH;

GRANT RESOURCE TO HEALTH;

GRANT CREATE DATABASE LINK TO HEALTH;

ALTER USER HEALTH DEFAULT ROLE ALL;

CREATE USER DATA_ACQ

IDENTIFIED BY "DATA_ACQ"

DEFAULT TABLESPACE TS_MEDIPI

TEMPORARY TABLESPACE TEMP

PROFILE DEFAULT

ACCOUNT UNLOCK;

GRANT CONNECT TO DATA_ACQ;

GRANT RESOURCE TO DATA_ACQ;

GRANT CREATE DATABASE LINK TO DATA_ACQ;

ALTER USER DATA_ACQ DEFAULT ROLE ALL;

Page 61: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

61

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

61

En la creación de los usuarios le asignamos el tablespace creado anteriormente y le damos los permisos y

características necesarias para acceder a la base de datos independientemente. La propiedad del usuario

“ACCOUNT UNLOCK” indica que se permite el login del usuario en la base de datos mediante la contraseña

indicada en la instrucción “IDENTIFIED BY”. A continuación, le indicamos que emplee el perfil por defecto.

Los perfiles [57] se emplean para restringir el uso que un usuario puede hacer de la base de datos, en términos

de cantidad de espacio disponible, tiempo de conexión, etc. En este caso, al tratarse de un modelo de datos

pequeño, no hay necesidad de definir una política de perfiles demasiado compleja, con lo que se opta por emplear

el perfil por defecto, que no limita las características del usuario. Para terminar, es necesario configurar los roles

del usuario: Todos los usuarios que quieran acceder a la BD deben tener el rol CONNECT; aquellos que necesiten

crear segmentos (procedures, triggers, Jobs, etc.) necesitaran el rol RESOURCE. Por último, el permiso “CREATE

DATABASE LINK” [58] añade la posibilidad de crear un enlace privado a la actual base de datos desde una

segunda base de datos de Oracle, lo que permitiría lanzar consultas o realizar modificaciones desde la segunda

base de datos. La última sentencia indica los roles por defecto, es decir, los que tendrá el usuario

automáticamente al logarse en la base de datos.

5.3.3 Tablas

Es el turno de comentar la parte central del modelo de datos: las tablas y los campos que las componen. Hemos

visto anteriormente que nuestra solución va a contar con dos esquemas: HEALTH y DATA_ACQ, los cuales

se detallan a continuación.

Figura 5-13. Modelo de datos

En el gráfico anterior se ha empleado la siguiente notación:

- Las elipses representan las tablas del modelo de datos

- Las flechas representan las relaciones entre tablas. Cuando una tabla apunta a otra se está

representando que en la tabla origen existe una referencia a la tabla apuntada mediante una clave externa

Como se observa, las tablas se reparten entre los dos esquemas creados. Dentro de HEALTH ubicamos las

entidades que recopilan información general, como por ejemplo información del paciente; mientras que en

DATA_ACQ se encuentra todo el modelo de datos de la recolección de información.

Se puede observar que el número de relaciones entre tablas de distintos esquemas es lo más reducido posible y

Page 62: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

62

62

siempre van de tablas de DATA_ACQ a entidades del esquema HEALTH. Esto no es casualidad, si se desea

implementar otro sistema sobre esta base de datos, como por ejemplo una aplicación que represente la

información del paciente, el esquema HEALTH debería ser completamente independiente, de forma que no sea

necesaria realizar ninguna acción sobre el esquema DATA_ACQ, hasta el punto de poder borrar este esquema.

Emplear esta política de separación de entidades permite una gran modularidad, de forma que nuevas

aplicaciones puedan crear esquemas propios sobre el núcleo HEALTH, ignorando el resto de esquemas.

Además de lo anterior, se observa que el modelo de base de datos construido cumple con el estándar de

normalización 3FN.

5.3.3.1 Información común a todas las tablas

Antes de comenzar, conviene comentar los tipos básicos de datos de Oracle, para comprender la terminología

usada posteriormente en la definición de las tablas:

- NUMBER(X, Y): Tipo numérico. El primer valor representa la precisión (número total de dígitos) y el

segundo la escala (número de dígitos decimales, es decir, a la derecha del punto decimal). El valor por

defecto es (38,0)

- DATE / TIMESTAMP(X): Tipo fecha. El tipo TIMESTAMP es similar a DATE (el tipo fecha más

habitual) pero permite introducir fracciones de segundos, indicando entre paréntesis el número de

dígitos de precisión en las fracciones de segundo. El valor por defecto es 6.

- VARCHAR2(X BYTE): Tipo texto, indicando el tamaño máximo en bytes (50 por defecto).

A lo largo del apartado se empleará la clasificación estándar de tablas en función de la información almacenada:

- Maestras: Información prácticamente fija, que cambia raramente, y generalmente relacionada con un

conjunto de datos maestros del mundo real. Por ejemplo, un catálogo de países del mundo se almacenará

en una tabla maestra, pues esta información no debe cambiar prácticamente nunca. En nuestro caso, la

tabla CONSTANT será maestra, pues es poco habitual añadir o eliminar variables clínicas como la

frecuencia cardiaca, presión arterial, etc. Si se pretende optimizar el uso de una tabla maestra se

centrarán los esfuerzos en agilizar las consultas, penalizando la inserción de nuevos registros. Las tablas

maestras no deben hacer referencia (mediante una clave externa) a ninguna otra tabla que no sea también

maestra.

- Paramétricas: Contienen información variable que no suelen cambiar habitualmente. Este tipo de tablas

se suelen emplear para datos del sistema, aunque puede emplearse para información del mundo real de

variación mayor a las maestras. Como se puede deducir, la tabla PARAMETER de nuestro modelo de

datos se emplea para almacenar determinados parámetros del sistema, como podría ser una constante

que indique el número de intentos de reconexión que deben realizarse tras una pérdida de conexión con

la red.

- Datos: Las tablas de tipo Datos contienen información no fija, que varía constantemente, como las

constantes de un paciente. En este tipo de tablas prima la velocidad de inserción / modificación de

registros. Será muy habitual que las tablas de datos hagan referencia a las tablas maestras, pero nunca

al revés.

Para homogenizar el modelo de datos y facilitar su uso, se seguirán un conjunto de reglas comunes:

- Clave primaria: La clave primaria de toda tabla se denominará TABLA_ID. Cuando un campo haga

referencia a la clave primaria de otra tabla mantendrá el nombre original.

- Fechas: los campos que almacenen una fecha serán de tipo TIMESTAMP.

Además de todo lo anterior, las tablas creadas para el modelo de datos de MEDIPi comparten un núcleo, un

conjunto de columnas comunes que representan información básica. Estas son:

Page 63: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

63

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

63

CAMPO TIPO DEFAULT COMENTARIO

DELETED NUMBER(1,0) 0 Indicador de borrado lógico. 1 borrado / 0 no borrado

INSERT_DATE TIMESTAMP(6) SYSDATE Fecha de creación del registro

UPDATE_DATE TIMESTAMP(6) Fecha de última modificación del registro

VERSION NUMBER(38,0) 0 Versión del registro

5.3.3.2 Esquema HEALTH

5.3.3.2.1 PATIENT

Es la entidad base de todo modelo de base de datos para el ámbito sanitario. Esta tabla de datos debe incluir la

información básica del paciente, como el nombre, DNI, etc.

CAMPO TIPO DEFAULT COMENTARIO

PATIENT_ID NUMBER(38,0) Clave primaria de la tabla

PID VARCHAR2(32 BYTE) Identificador del paciente en el servicio sanitario. Debe

estar siempre informado.

DNI VARCHAR2(32 BYTE) DNI

NAME VARCHAR2(32 BYTE) Nombre

SURNAME1 VARCHAR2(32 BYTE) Primer apellido

SURNAME2 VARCHAR2(32 BYTE) Segundo apellido

SEX NUMBER(1,0) 0 0: Desconocido / 1: Hombre / 2: Mujer / 3: Indeterminado

5.3.3.2.2 EPISODE

Cada vez que un paciente visite un centro sanitario se crea un nuevo episodio, con fecha de ingreso y de fin. En

esta tabla debe haber una clave externa a la tabla PATIENT, para poder relacionar la información del episodio

con el paciente al que pertenece. Al igual que PATIENT, se trata de una tabla de datos, que contendrá una gran

cantidad de información que irá aumentando constantemente.

CAMPO TIPO DEFAULT COMENTARIO

EPISODE_ID NUMBER(38,0) Clave primaria de la tabla

PATIENT_ID NUMBER(38,0) Referencia al paciente. Este campo no puede ser nulo.

EID VARCHAR2(32 BYTE) Identificador del episodio en el servicio sanitario. Debe

estar siempre informado.

START_DATE TIMESTAMP(6) Fecha de ingreso

Page 64: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

64

64

END_DATE TIMESTAMP(6) Fecha de alta

5.3.3.2.3 CONSTANT

Si se pretende recopilar constantes clínicas del paciente es evidente que necesitamos una tabla maestra de

variables biomédicas, un catálogo de variables que podremos obtener automáticamente de la integración con los

dispositivos.

CAMPO TIPO DEFAULT COMENTARIO

CONSTANT_ID NUMBER(38,0) Clave primaria de la tabla

TYPE NUMBER(1,0) 0 0: Numérica / 1: Texto

DESCRIPTION VARCHAR2(128 BYTE) Descripción de la variable clínica

MAX_VALUE NUMBER(38,0) En caso de tratarse de una variable de tipo numérico (las

más habituales) se indica aquí el valor máximo posible de

la misma.

MIN_VALUE NUMBER(38,0) Valor mínimo posible de una constante numérica

Hemos optado por establecer una clasificación de variables en función de si esperamos recuperar valores

numéricos o alfanuméricos, ya que el tratamiento de la información variará en función de esto.

Otra información importante que puede pasar desapercibida a primera vista es la almacenada en las columnas

MAX_VALUE y MIN_VALUE. La idea es emplear estos campos para conocer el umbral de valores posibles

de una variable clínica. En numerosas ocasiones será habitual recibir información incorrecta desde los

dispositivos médicos, no solo datos imprecisos, si no directamente valores fuera de rango. Estos datos, que en el

ámbito de la instrumentación biomédica se conocen como “artefactos”, no suelen ser filtrados por los propios

dispositivos pues la política habitual es mostrar toda la información posible dejando su interpretación a cargo de

los profesionales médicos. En nuestro caso, una de las funcionalidades que MEDIPi aportará a los usuarios es

un tratamiento básico de limpieza de datos, rechazando datos claramente erróneos, que se salgan del umbral de

valores compatibles con la vida. Como es razonable, solo podremos realizar este tratamiento para aquellas

variables clínicas de tipo numérico.

5.3.3.2.4 CONSTANT_INFO

En los puntos anteriores se ha definido el conjunto de tablas básicas del modelo de datos general: pacientes,

episodios y variables biomédicas, con lo que ya se tiene información suficiente para definir la entidad más

importante de MEDIPi: la tabla de valores de constantes clínicas, donde se volcará toda la información

recuperada desde los dispositivos.

Como es fácil deducir, necesitaremos al menos una referencia al paciente y otra a la maestra de variables. Lo

primero lo haremos con una clave externa a la tabla EPISODE, quedando así asociada la constante a una estancia

concreta del paciente. En general, se debe tender a establecer relaciones lo más específicas posibles. Por ejemplo,

si se hubiera asociado el resultado de una medición (p.e. Temperatura) a un paciente en vez de a un episodio

sería más difícil en un futuro sacar estadísticas o patrones de la información recuperada. Siguiendo con el

ejemplo, si un paciente ingresa dos veces, la segunda de ellas con fiebre, es evidente que mantener claramente

los resultados asociados a dos episodios diferentes facilita la explotación de la información. En caso contrario,

al observar que los valores pasan de normales a altos habría que revisar las fechas, pudiendo dar lugar a alguna

confusión.

En la definición de la tabla CONSTANT se definió una categorización muy básica de constantes, una

Page 65: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

65

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

65

clasificación entre variables numéricas (la gran mayoría) y de tipo texto. Por tanto, debemos preparar nuestro

modelo de datos para almacenar variables cuyo valor sea un texto. Un caso fácil de comprender puede ser el

modo de funcionamiento del biodispositivo, que se suele tratar como un texto. Por tanto, a pesar de guardar

fundamentalmente valores numéricos, es necesario definir el campo valor como alfanumérico. Existen otras

alternativas a esta metodología: podría haberse optado por crear una tabla de valores posibles identificados por

una clave numérica. De esta forma, bastaría con informar en el campo valor la clave de esta tabla, pudiendo

mantener la columna VALUE como numérica. Sin embargo, este modelo presenta otras deficiencias: no es

posible introducir cualquier valor, solo los presentes en esta tabla. A no ser que se opte por ir introduciendo todos

los valores nuevos en esa tabla, perdiéndose las ventajas sobre el texto libre. Por todo esto, y esperando diseñar

un modelo de datos lo menos restrictivo posible para evitar futuras modificaciones, se ha optado por un campo

VALUE de tipo texto.

CAMPO TIPO DEFAULT COMENTARIO

CONSTANT_INFO_ID NUMBER(38,0) Clave primaria de la tabla

CONSTANT_ID NUMBER(38,0) Clave externa que hace referencia a la constante informada

EPISODE_ID NUMBER(38,0) Clave externa que hace referencia al episodio

correspondiente del paciente para el que se recopila la

variable.

CONSTANT_DATE TIMESTAMP(6) SYSDATE Fecha de recuperación de la variable

VALUE VARCHAR2(32 BYTE) Valor de la variable

MANUAL NUMBER(1,0) 0 0: Valor recuperado automáticamente / 1: Datos

introducido manualmente.

Es interesante realizar una observación acerca de la tabla que nos ocupa: a pesar de tratarse de la entidad diseñada

para almacenar información no solo no pertenece al esquema de adquisición de datos (DATA_ACQ), sino que

ni siquiera tiene relación con alguna tabla de dicho esquema. A primera vista resulta chocante, pero es fácilmente

comprensible desde la política escogida para el diseño del modelo de datos: cada esquema corresponde a una

funcionalidad concreta y diferenciada, de tal forma que las tablas que componen el esquema DATA_ACQ son

aquellas necesarias en la creación de una aplicación para la adquisición de datos, mientras que bajo HEALTH

agrupamos las tablas que mapean información médica de carácter general. El conjunto de constantes de un

paciente es una información médica que no debe ser exclusiva del software de adquisición automática de datos,

hasta el punto de que se podría diseñar una solución que permitiera a los profesionales médicos introducir “a

mano” valores para la temperatura del paciente, la frecuencia cardiaca, etc. La solución imaginada en la frase

anterior debería conocer las tablas en las que se recopile la información del paciente, su estancia actual, la

maestra de variables clínicas, etc., pero nunca debería ser imprescindible tener en cuenta el conjunto de

protocolos soportados por la recolección automática de información, por ejemplo. Por tanto, parece lógico

diseñar nuestro modelo de datos “sacando” la entidad de constantes médicas CONSTANT_INFO al esquema

general. Como toda decisión, este diseño nos genera también inconvenientes: si mantuviéramos

CONSTANT_INFO dentro del esquema DATA_ACQ probablemente se hubiera optado por añadir una

referencia al menos al dispositivo del que proviene la información, permitiendo una gran explotación de la

información a futuro. Bajo nuestra implementación, necesitaríamos combinar información de varias tablas para

poder mostrar esa información (necesitamos saber, a través del episodio, la asignación de dispositivos que tenía

el paciente en aquella fecha; pudiendo incluso no obtener un resultado concluyente si había más de un dispositivo

asignado en ese instante con capacidad de recuperar esa variable clínica). En resumen, hemos ganado en

modularización, pero hemos dificultado la explotación posterior de la información.

Page 66: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

66

66

5.3.3.3 Esquema DATA_ACQ

5.3.3.3.1 MEDIPI_INSTANCE

Nos encontramos ante la tabla central del esquema DATA_ACQ, sobre la que se construye el modelo de datos

de nuestra solución.

En ella, cada ejecución del software MEDIPi (por ejemplo, cada Raspberry que corra el software del presente

proyecto) estará representada por un registro, en el que será informados algunos de los parámetros necesarios

para especificar el funcionamiento de dicha ejecución. Es fácil imaginar un escenario como el siguiente: un

centro sanitario en el que se desea implantar MEDIPi en una sala con cuatro camas. Para dar cobertura a todos

los pacientes que vayan ocupando las camas, será necesario imaginar el escenario más desfavorable: que las

cuatro localizaciones estén ocupadas a la vez. Parece evidente que son necesarias cuatro Raspberrys, cada una

de ellas ejecutando MEDIPi, lo que se corresponde con cuatro registros en la tabla MEDIPI_INSTANCE en

base de datos. En resumen, con esta tabla podremos representar la parametrización básica de cada instancia.

CAMPO TIPO DEFAULT COMENTARIO

MEDIPI_INSTANCE_ID NUMBER(38,0) Clave primaria de la tabla

INSTANCE_NAME VARCHAR2(64 BYTE) Identificador único de la instancia de MEDIPi. Será único

y no nullable.

IP VARCHAR2(32 BYTE) Dirección IP de la máquina que está ejecutando el software

Se podría haber empleado el campo INSTANCE_NAME como clave primaria, ya que cumple con las dos

condiciones básicas de toda clave primaria: valores únicos y no nullables. Como se comentará en el apartado

correspondiente a la descripción del software de MEDIPi, al arrancar la aplicación se encargará de obtener su

INSTANCE_NAME, con el que se puede identificar el registro correspondiente de la tabla

MEDIPI_INSTANCE. Veremos más adelante que se ha optado por emplear el nombre del host sobre el que

corre la aplicación como INSTANCE_NAME. Conocido lo anterior, no hay motivos inmediatos para descartar

la utilización de este campo como clave primaria de la tabla. Sin embargo, la utilización de una clave numérica

nos proporciona más ventajas, como veremos en el punto siguiente (Secuencias). Además, al independizar la

clave de la instancia disponemos de mayor versatilidad a futuro. Si surge la necesidad de ejecutar dos instancias

en la misma máquina solo habrá que hacer una pequeña revisión en el código no siendo necesario modificar la

estructura de la base de datos. Esto último es fundamental, siempre debe diseñarse el modelo de una base de

datos de forma lo suficientemente robusta como para evitar sufrir modificaciones por pequeños cambios en el

alcance.

5.3.3.3.2 PROTOCOL

Con la descripción de la tabla PROTOCOL comenzamos a desgranar el conjunto de tablas que componen el

modelo de datos destinado a caracterizar los distintos dispositivos de los que el software se integrará para

recuperar información clínica de un paciente. Antes de continuar, recordemos el modelo diseñado:

Figura 5-14. Modelo de datos sobre biodispositivos

Page 67: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

67

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

67

Se observa que manejamos una estructura relativamente compleja, formada nada menos que por cuatro tablas

destinadas solamente a informar y categorizar los distintos dispositivos. Esta estructura ha sido necesaria para

agrupar adecuadamente los dispositivos desde 2 puntos de vista:

- Protocolos: es imprescindible realizar una asociación entre el dispositivo con el que nos integraremos y

el protocolo que este implementa, pues es perfectamente posible que dos dispositivos diferentes, de

modelos y fabricantes diferentes, empleen el mismo protocolo.

- Tipos: Para una correcta explotación posterior de los datos es necesario conocer de qué tipo es cada

dispositivo (Monitor, ventilador, etc.). Esto puede ser fundamental, ya que es habitual que varios

dispositivos puedan recuperar la misma constante, siendo necesario priorizar los valores de aquel tipo

de dispositivo que sea más preciso en la medición de dicha variable clínica, ignorando los del otro.

Conociendo ya las condiciones iniciales, que serán fundamentales en la estructura de esta sección de la base de

datos, abordamos la definición de la tabla que nos ocupa.

CAMPO TIPO DEFAULT COMENTARIO

PROTOCOL_ID NUMBER(38,0) Clave primaria de la tabla

CODE VARCHAR2(8 BYTE) Código alfanumérico para identificar unívocamente un

protocolo. No puede ser nulo.

DESCRIPTION VARCHAR2(256 BYTE) Descripción del protocolo.

INFO

VARCHAR2(256 BYTE) Información extra, como podría ser datos de

parametrización.

Nos encontramos ante una tabla muy sencilla, una simple maestra donde listaremos todos los protocolos

conocidos por MEDIPi. Cuando informemos al software acerca del dispositivo asociado, la aplicación deberá

acceder hasta esta tabla, para poder identificar el protocolo empleado y operar en consecuencia. En esta ocasión

solo se evita emplear CODE como clave primaria por homogeneidad con el resto del modelo de datos y para

disfrutar de las ventajas que se comentarán en el próximo apartado.

5.3.3.3.3 DEVICE_TYPE

Esta tabla lista los distintos tipos de dispositivos disponibles para poder realizar acciones posteriores relacionadas

con la explotación de la información.

CAMPO TIPO DEFAULT COMENTARIO

DEVICE_TYPE_ID NUMBER(38,0) Clave primaria de la tabla

CODE VARCHAR2(8 BYTE) Código alfanumérico para identificar unívocamente un tipo

de dispositivo. No puede ser nulo.

DESCRIPTION VARCHAR2(128 BYTE) Descripción del tipo de dispositivo

Como se observa, nos basta con una clave primaria y un campo de descripción.

Page 68: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

68

68

5.3.3.3.4 DEVICE_MODEL

Esta es, seguramente, la tabla central del conjunto que componen el modelo de datos de dispositivos, con una

importancia superior a la de la tabla DEVICE, pues será el modelo del dispositivo quien nos permitirá reconocer

tanto el tipo del mismo como, sobre todo, el protocolo implementado.

CAMPO TIPO DEFAULT COMENTARIO

DEVICE_MODEL_ID NUMBER(38,0) Clave primaria de la tabla

DESCRIPTION VARCHAR2(256 BYTE) Descripción del modelo de dispositivo. No puede ser nulo.

INFO

VARCHAR2(256 BYTE) Información extra, como podría ser datos de

parametrización.

DEVICE_TYPE_ID NUMBER(38,0) Tipo de los dispositivos del presente modelo. Debe estar

siempre informado.

PROTOCOL_ID NUMBER(38,0) Protocolo de comunicación empleado por los dispositivos

de este modelo. Debe estar siempre informado.

5.3.3.3.5 DEVICE

En la tabla dispositivos incluiremos todos los diferentes dispositivos de los que dispongamos, indicando a qué

modelo pertenecen. Es perfectamente posible disponer de una amplia cantidad de dispositivos del mismo

modelo, teniendo todos ellos características iguales, por lo que se ha optado por crear la ya comentada tabla

DEVICE_MODEL donde centralizar toda esta información. Por tanto, dejamos DEVICE como un mero

catálogo de dispositivos empleados ahora o en el pasado.

CAMPO TIPO DEFAULT COMENTARIO

DEVICE_ID NUMBER(38,0) Clave primaria de la tabla

SERIAL_NUMBER VARCHAR2(256 BYTE) Número de serie del dispositivo. Puede estar nulo, pues en

algunos casos no será fácil obtenerlo.

DESCRIPTION VARCHAR2(256 BYTE) Descripción del dispositivo. No nullable

DEVICE_MODEL_ID NUMBER(38,0) Modelo del dispositivo. Debe estar siempre informado.

5.3.3.3.6 ALLOCATION

Ya se han definido las tablas encargadas de modelar los dispositivos y las diferentes Raspberrys que ejecutan el

software, pero no se ha comentado todavía como se establece la relación entre las mismas. Alejándonos

momentáneamente del modelado de base de datos, es evidente que será necesario informar de alguna manera al

software de, al menos, qué protocolos deberá implementar para establecer la comunicación con el dispositivo

de cara a recuperar la información de constantes clínicas del paciente. En la mayoría de los casos, bastará con

indicar el protocolo, actuando el software en consecuencia. Sin embargo, el estudio de los distintos protocolos

y soluciones de recuperación automática de datos nos ha permitido observar que existen casos en los que varios

modelos de un mismo fabricante pueden emplear el mismo protocolo, pero bajo alguna especificación que el

software debe tener en cuenta de cara a poder realizar una comunicación adecuada. El caso más habitual será el

de los biodispositivos conectados mediante una interfaz serie, donde algunos parámetros físicos de la

comunicación como la existencia de bit de paridad, los baudios, etc. pueden variar dependiendo del modelo de

dispositivo. MEDIPi usará una lógica común, pues el protocolo es el mismo, pero deberá conocer de alguna

Page 69: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

69

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

69

manera estas especificidades. Este es el motivo por el que se añadió una columna INFO a la tabla

DEVICE_MODEL y también la razón por la cual se considera imprescindible que la asignación entre

dispositivos y Raspberrys se realice al menos a nivel de modelo de dispositivo y no de protocolo.

Partiendo de lo anterior, se ha optado por realizar una asociación a nivel de dispositivo, lo que genera ventajas e

inconvenientes. La principal ventaja es que permite una gran explotación posterior de la información: a partir

del modelo de datos construido se puede recuperar qué dispositivo fue el responsable de cada constante

almacenada. No es una posibilidad despreciable, si descubrimos que un dispositivo ha estado funcionando

incorrectamente podríamos eliminar la información recuperada por él, o al menos identificarla para ponerla en

cuarentena. Por otra parte, es necesario indicar qué dispositivo concreto es el que está conectado a la raspberry,

lo que requiere identificar de forma unívoca cada dispositivo y mantener correctamente actualizado el catálogo.

Además de todo lo anterior, falta una asociación que realizar. Con el modelo de datos diseñado hasta el momento

el software no es capaz de llevar a cabo un mapeo entre el dispositivo asignado a una instancia concreta y el

episodio del paciente para el que se están recuperando las constantes biomédicas vía integración con dispositivos.

Para cumplir este requisito se introduce una clave externa a la tabla episodio desde ALLOCATION, lo que

implica una asociación a nivel paciente – dispositivo – instancia, aportando una mayor granularidad que si se

optara por una relación paciente – instancia. En otras palabras, una misma instancia podrá tener asignados varios

dispositivos (evidentemente, de modelos, tipo y protocolos diferentes) y cada uno de ellos recuperando

información de un paciente distinto.

CAMPO TIPO DEFAULT COMENTARIO

ALLOCATION_ID NUMBER(38,0) Clave primaria de la tabla

MEDIPI_INSTANCE_ID NUMBER(38,0) Referencia a la instancia del software con la que asociamos

el dispositivo. Debe estar informado

DEVICE_ID NUMBER(38,0) Referencia al dispositivo. Debe estar informado

EPISODE_ID NUMBER(38,0) Referencia al episodio. Debe estar informado.

PORT VARCHAR2(32 BYTE) Puerto de la máquina (Raspberry) a la que se conecta el

dispositivo. Puede ser nulo.

START_DATE TIMESTAMP(6) SYSDATE Fecha de inicio de la asignación

END_DATE TIMESTAMP(6) Fecha de fin de la asignación. Valdrá nulo cuando todavía

esté asignado

Junto a los campos mínimos necesarios para realizar la asignación encontramos tres campos no tan inmediatos.

El primero el puerto a través del cual se realiza la conexión, pues MEDIPi necesitará conocer a qué puerto estará

conectado el dispositivo para poder comunicarse con él. Con este campo cubrimos varias posibilidades:

podemos escribir en él el puerto físico (USB, Serie, etc.) si se trata de una comunicación serie o paralelo, o el

puerto que deberá escuchar el software pare recibir información a través de una red IP. Es bastante habitual que

dispositivos del mismo protocolo o modelo tiendan a emplear el mismo puerto para la comunicación, pudiendo

informarse de ello en el campo de parametrización extra que tienen las tablas correspondientes. Se ha indicado

arriba, en la descripción de los campos de la tabla, que el campo puerto puede no estar informado. En ese caso

se entiende que el puerto está informado en alguno de los campos de información comentados. Si no se diera el

caso el software no tendría la configuración mínima para iniciar la comunicación.

Además de todo lo comentado anteriormente se observa que existen dos campos extra: fecha de inicio de la

asignación y fecha de fin. Con ellos es posible mantener un histórico de asignaciones, indicando para cada

registro cuando comenzó y cuando terminó la asignación. Esto último es fundamental para poder recuperar a

posteriori qué dispositivo estaba asignado a qué Raspberry en todo momento.

Antes de pasar a la definición de la siguiente tabla se realizará un comentario sobre las decisiones meramente

Page 70: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

70

70

técnicas que se han tomado durante el análisis y realización del modelado de datos. Se ha considerado lo más

correcto emplear una clave primaria propia para la tabla, en vez de definir una clave compuesta. Dicha clave

compuesta debería estar formada por MEDIPI_INSTANCE_ID, DEVICE_ID y START_DATE. Incluso sería

necesario incluir el campo común DELETED, pues hablamos de una tabla de asignaciones, que es previsible se

rellene desde una aplicación, pudiéndose producir errores que justifiquen la utilización del borrado lógica. Nos

encontraríamos con una clave tan compleja que prácticamente abarcaría la tabla en su totalidad, dificultando las

consultas que se lancen sobre la tabla. Es por este motivo por el que se ha considerado más adecuado crear una

clave primaria simple.

5.3.3.3.7 PROTOCOL_CONSTANT_MAP

Los distintos protocolos emplean valores propios para identificar a las distintas constantes que manejan, desde

cadenas de texto hasta números identificativos. El software de MEDIPi necesitará conocer en todo momento

qué significa cada uno de ellos de cara a poder realizar el mapeo entre este identificador interno del protocolo y

uno común a todos y conocido por la aplicación. Es evidente por tanto que PROTOCOL_CONSTANT_MAP

será una tabla encargada de establecer las relaciones entre estos valores y la maestra de variables clínicas

conocidas por el sistema CONSTANT. Parece lógico supone que se tratará de una tabla maestra, que se rellenará

durante el desarrollo de la implementación del protocolo, y que no volverá a tocarse salvo para revisiones

puntales.

CAMPO TIPO DEFAULT COMENTARIO

PROTOCOL_ID NUMBER(38,0) Referencia al protocolo del que pertenece la variable.

Siempre debe estar informado.

CONSTANT_NAME VARCHAR2(128 BYTE) Identificador de la constante biomédica interno empleado

por el protocolo. Debe estar siempre informado y será

único dentro de un protocolo.

CONSTANT_ID NUMBER(38,0) Referencia al registro de la maestra de constantes para la

que se está realizando el mapeo. Debe estar informado

Estamos ante la única tabla del modelo de datos que no cuenta con una clave primaria simple, es decir, no

dispone de su PROTOCOL_CONSTANT_MAP_ID. El motivo es sencillo, estamos ante una tabla de mapeo

para la que, por cada protocolo nos bastará el identificador interno (CONSTANT_NAME) para conocer la

asignación. Por tanto, se empleará una clave primaria compuesta por PROTOCOL_ID y CONSTANT_NAME.

5.3.3.3.8 PARAMETER

La última de las tablas del modelo de datos es la más sencilla: se trata de una mera tabla paramétrica destinada

a almacenar información de configuración común a todas las ejecuciones del software MEDIPi. El software

consultará la base de datos para conocer el valor de estos parámetros y actuar según su valor. La parametrización

del software mediante una tabla de base de datos nos permite actualizar dinámicamente sus valores, sin

necesidad de andar parando y arrancando la solución, como veremos más adelante.

CAMPO TIPO DEFAULT COMENTARIO

PARAMETER_ID NUMBER(38,0) Clave primaria de la tabla.

PARAMETER VARCHAR2(64 BYTE) Identificador del parámetro. Debe ser único y estar siempre

informado.

Page 71: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

71

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

71

VALUE VARCHAR2(128 BYTE) Valor del parámetro.

DESCRIPTION VARCHAR2(256 BYTE) Descripción o comentarios del parámetro.

Para terminar el apartado destinado al modelado de tablas se muestran un par de ejemplos de las sentencias SQL

necesarias para crear nuestras tablas en base de datos:

CREATE TABLE DATA_ACQ.ALLOCATION

(

ALLOCATION_ID NUMBER(38,0) PRIMARY KEY,

MEDIPI_INSTANCE_ID NUMBER(38,0) REFERENCES DATA_ACQ.MEDIPI_INSTANCE .

(MEDIPI_INSTANCE_ID) NOT NULL,

DEVICE_ID NUMBER(38,0) REFERENCES DATA_ACQ.DEVICE (DEVICE_ID) .

NOT NULL,

PORT VARCHAR2(32 BYTE),

START_DATE TIMESTAMP(6) DEFAULT SYSDATE NOT NULL,

END_DATE TIMESTAMP(6) ,

DELETED NUMBER(1,0) DEFAULT 0 NOT NULL,

INSERT_DATE TIMESTAMP(6) DEFAULT SYSDATE NOT NULL,

UPDATE_DATE TIMESTAMP(6),

VERSION NUMBER(38,0) DEFAULT 0 NOT NULL

);

CREATE TABLE DATA_ACQ.PROTOCOL_CONSTANT_MAP

(

PROTOCOL_ID NUMBER(38,0),

CONSTANT_NAME VARCHAR2(128 BYTE),

CONSTANT_ID NUMBER(38,0) REFERENCES HEALTH.CONSTANT (CONSTANT_ID) .

NOT NULL,

DELETED NUMBER(1,0) DEFAULT 0 NOT NULL,

INSERT_DATE TIMESTAMP(6) DEFAULT SYSDATE NOT NULL,

UPDATE_DATE TIMESTAMP(6),

VERSION NUMBER(38,0) DEFAULT 0 NOT NULL,

PRIMARY KEY(PROTOCOL_ID, CONSTANT_NAME)

);

A través de la sentencia CREATE TABLE se especifican las características de la tabla a crear:

- Se indica ESQUEMA.TABLA

- Cada definición de un campo sigue la estructura: NOMBRE TIPO OTRA_CONF

- Para indicar una clave primaria se puede optar por añadir la instrucción PRIMARY KEY al final del

campo o colocar una línea final PRIMARY KEY(campos).

- Se define una clave externa mediante la instrucción REFERENCES

ESQUEMA.TABLA_REFERENCIADA (CAMPO_REFERENCIADO).

5.3.4 Secuencias

Mediante las secuencias [59], Oracle puede proporcionar una lista consecutiva de números unívocos que sirve

para simplificar las tareas de programación. La primera vez que una consulta llama a una secuencia, se devuelve

un valor predeterminado. En las sucesivas consultas se obtendrá un valor incrementado según el tipo de

incremento especificado. Es decir, una secuencia (sequence) se emplea para generar valores enteros secuenciales

únicos y asignárselos a campos numéricos; siendo tremendamente útiles para las claves primarias de las tablas.

Mediante el empleo de secuencias garantizaremos que las claves primarías sean únicas y secuenciales, pudiendo

Page 72: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

72

72

identificar fácilmente el orden en el que se han introducido los registros además de asegurar la integridad de la

información.

Veamos más detalladamente como funciona una secuencia: Todos los parámetros fundamentales de una

secuencia se indican en su creación mediante la sentencia CREATE SEQUENCE.

CREATE SEQUENCE NOMBRESECUENCIA

START WITH VALORENTERO

INCREMENT BY VALORENTERO

MAXVALUE VALORENTERO

MINVALUE VALORENTERO

CYCLE | NOCYCLE

CACHE VALORCACHE;

Sobre la instrucción podemos comentar:

- La cláusula START WITH indica el valor desde el cual comenzará la generación de números

secuenciales. Si no se especifica, se inicia con el valor que indique MINVALUE.

- La cláusula INCREMENT BY especifica el incremento, es decir, la diferencia entre los números de la

secuencia; debe ser un valor numérico entero positivo o negativo diferente de 0. Si no se indica, por

defecto es 1.

- MAXVALUE define el valor máximo para la secuencia. Si se omite, por defecto es

99999999999999999999999999.

- MINVALUE establece el valor mínimo de la secuencia. Si se omite será 1.

- La cláusula CYCLE indica que, cuando la secuencia llegue a máximo valor (valor de MAXVALUE)

se reinicie, comenzando con el mínimo valor (MINVALUE) nuevamente, es decir, la secuencia vuelve

a utilizar los números. Si se omite, por defecto la secuencia se crea NOCYCLE.

- Con la condición CACHE se define el número de valores que se almacenarán en la caché de Oracle,

aumentando la velocidad en la consulta de la secuencia (reduciendo las lecturas y escrituras que realiza

Oracle en disco). Si se produce algún fallo que provoque el cierre o reinicio de la base de datos los

números cacheados se perderán, de tal forma que en el próximo arranque la secuencia comenzará en el

número siguiente al último cacheado.

Si no se especifica ninguna cláusula, excepto el nombre de la secuencia, por defecto, comenzará en 1, se

incrementará en 1, el mínimo valor será 1, el máximo será 999999999999999999999999999, NOCYCLE y no

estará cacheada.

Para emplear las secuencias se emplean dos instrucciones especiales:

NOMBRESECUENCIA.NEXTVAL;

NOMBRESECUENCIA.CURRVAL;

Con la primera instrucción obtenemos el próximo valor de la secuencia, mientras que la segunda se emplea para

recuperar el valor actual de la misma.

Por tanto, aunque las secuencias sean un objeto de base de datos totalmente independientes de las claves

primarias, en el presente proyecto se utilizarán solamente para facilitar el trabajo con las claves primarias simples

de las tablas.

Veamos un ejemplo de la definición habitual de una secuencia en nuestro modelo de datos:

CREATE SEQUENCE HEALTH.PATIENT_ID_SEQ

Page 73: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

73

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

73

START WITH 1

INCREMENT BY 1

MAXVALUE 999999999999999999999999999

MINVALUE 1

NOCYCLE

CACHE 20;

5.3.5 Índices

El índice [60] de una base de datos es una estructura de datos que mejora la velocidad de las operaciones,

permitiendo un rápido acceso a los registros de una tabla. Al aumentar drásticamente la velocidad de acceso, se

suelen usar sobre aquellos campos sobre los cuales se vayan a realizar búsquedas frecuentes.

El índice tiene un funcionamiento similar al índice de un libro, guardando parejas de elementos: el elemento que

se desea indexar y su posición en la base de datos. Para buscar un elemento que esté indexado, sólo hay que

buscar en el índice de dicho elemento para, una vez encontrado, devolver el registro que se encuentre en la

posición marcada por el índice. Los índices son construidos sobre árboles, funciones de cálculo u otros métodos.

Los índices pueden ser creados usando una o más columnas, preparando la base de datos tanto para búsquedas

rápidas al azar como para ordenaciones eficientes de los registros.

El espacio en disco requerido para almacenar el índice es típicamente menor que el espacio de almacenamiento

de la tabla (puesto que los índices generalmente contienen solamente los campos clave de acuerdo con los que

la tabla será ordenada, y excluyen el resto de los detalles de la tabla), lo que da la posibilidad de almacenar en

memoria los índices de tablas que no cabrían en ella. En una base de datos relacional un índice es una copia de

parte de una tabla

Automáticamente Oracle crea índices únicos tanto para las claves primarias de las tablas como para los campos

diseñados como únicos y no nulos, pero será necesario informar de otros índices extra que se consideren

necesarios para agilizar las consultas sobre la base de datos.

Eso sí, es importante tener en cuenta que los índices producen una leve ralentización en la inserción de registros,

pues es ahí donde se informa al índice de los nuevos registros. Esto nos lleva a una fácil deducción: las tablas

maestras o paramétricas deberán contener tantos índices como sea necesario, pues apenas se realizarán

inserciones y son tablas constantemente consultadas por los programas. Por otra parte, se debe ser más cauteloso

con los índices en las tablas de datos. En general, el empleo de índices es una política altamente beneficiosa para

el rendimiento de las aplicaciones que emplean bases de datos Oracle. Incluso en tablas de datos que reciben

nuevos registros constantemente es necesario contar con los índices adecuados para que realizar consultas sobre

la misma no lastre la velocidad del software. Por ejemplo, en un centro sanitario las tablas PATIENT o

EPISODE pueden contener decenas de miles de registros pasados unos meses, por lo que realizar una búsqueda

por DNI de un paciente puede tardar segundos si no existe un índice para ese campo. Aunque dicho índice

provoque un retraso prácticamente despreciable en la inserción.

De todo lo anterior sacamos que debemos crear índices para los campos o conjuntos de cambios más

frecuentemente consultados. En el modelo de base de datos de MEDIPI se han implementado los siguientes

índices “extra”, además de los que Oracle define por defecto:

- PATIENT: SEX. Si se pretende realizar una explotación posterior de los datos será habitual intentar

obtener patrones en las constantes biomédicas en función del sexo del paciente.

- EPISODE: PATIENT_ID. Es habitual que las claves externas tengan un índice que permita agilizar las

consultas cuando se crecen información de varias tablas. En general, Oracle recomienda seguir esta

regla [61].

- EPISODE: BED_ID.

- EPISODE: START_DATE y END_DATE. Un índice común para los dos campos, ya que lo habitual

será realizar consultas en las que se informen de las condiciones para ambas columnas. Por ejemplo, se

usará para cuando sea necesario consultar los episodios activos en un momento determinado.

Page 74: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

74

74

- ALLOCATION: MEDIPI_INSTANCE_ID. Para facilitar las consultas que cada instancia de software

realizará para conocer sus dispositivos asociados.

- ALLOCATION: DEVICE_ID

- ALLOCATION: START_DATE y END_DATE. Un índice común para los dos campos, de forma

similar a los índices de la tabla EPISODE. Se supone que será habitual realizar consultas para conocer

la asignación de dispositivos en un momento concreto.

- DEVICE: DEVICE_MODEL_ID

- DEVICE_MODEL: DEVICE_TYPE_ID.

- DEVICE_MODEL: PROTOCOL_ID

- MEDIPI_INSTANCE: BED_ID

- PROTOCOL_CONSTANT_MAP: CONSTANT_ID

La sentencia que se debe emplear para crear un índice tiene una estructura sencilla, similar a la explicada para

crear claves externas.

CREATE INDEX PAT_SEX_IX ON HEALTH.PATIENT (SEX);

5.3.6 Permisos

Cuando se crea un objeto (como por ejemplo una tabla o una secuencia) se indica el esquema al que pertenece,

como en el siguiente ejemplo:

CREATE TABLE HEALTH.PATIENT (…

El nombre del objeto debe venir precedido por el esquema y un punto. Si no se especifica el esquema se creará

el objeto en el esquema del usuario con el que se está ejecutando la sentencia.

Esta política de usuarios / esquemas tiene un inconveniente: por defecto un usuario tiene permisos para modificar

/ crear objetos en su esquema, pero no para alterar o crear objetos en esquemas ajenos. Cuando el software se

arranque debe iniciar su comunicación con la base de datos, autenticándose contra esta con un usuario. En

nuestro caso usaremos el usuario DATA_ACQ, el más indicado para el software de integración con

biodispositivos. Sin embargo, este usuario no va a tener acceso a los objetos del esquema HEALTH, en el que

crearemos algunas tablas básicas. Esto provocará que, al crear cada objeto, debamos dar permisos al resto de

usuarios si necesitamos que accedan o modifiquen esta información.

Para dar permisos a uno o varios usuarios se emplea la instrucción GRANT [62], que ya se empleó en el apartado

correspondiente a la definición de los usuarios / esquemas de la base de datos. Esto se debe a que la instrucción

GRANT se puede emplear para dos fines:

- Dar permisos del sistema: anteriormente vimos que la sentencia GRANT CONNECT TO DATA_ACQ

daba permiso al usuario DATA_ASQ para conectarse a la base de datos.

- Establecer permisos sobre objetos: de manera análoga a la instrucción del punto anterior, podemos

establecer una sentencia que de determinados privilegios a un usuario o un rol.

En la línea siguiente vemos las dos sentencias que se han empleado en la construcción de nuestra base de datos

para dar los permisos adecuados al usuario DATA_ASQ.

Page 75: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

75

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

75

GRANT SELECT ON HEALTH.PATIENT_ID_SEQ TO DATA_ACQ;

GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON HEALTH.PATIENT TO DATA_ACQ;

La primera es el GRANT típico de una secuencia, dando permisos de consulta, mientras que la segunda es el

GRANT que se debe ejecutar para permitir a un usuario realizar las acciones básicas sobre una tabla (consultar,

insertar, actualizar, borrar registros y crear una clave externa en un objeto que apunte a dicha tabla)

Es bastante habitual encontrarnos con una sentencia como mostradas arribas pero que den privilegios al rol

PUBLIC en vez de especificar un usuario concreto. PUBLIC es un rol especial que poseen todos los usuarios,

de tal forma que basta con darle permiso a ese rol para que todos los usuarios lo tengan. En nuestro caso se

podría haber optado por darle los permisos a este rol especial, pero se cree más correcto llevar a cabo una política

de permisos restrictiva, dando permisos cuando sea necesario y no a todos los usuarios por defecto.

Page 76: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

76

76

Sistema de intercambio de datos: Kafka

La arquitectura software de MEDIPi se sustenta en un sistema de intercambio masivo de información biomédica

entre los diferentes módulos que la componen. Para que cumpla adecuadamente su función, es necesario que el

diseño cumpla una serie de características fundamentales:

- Alta disponibilidad: debe estar siempre operativo. Una caída del mismo supone pérdida irrecuperable

de información.

- Integridad: el sistema debe ser suficientemente robusto como para evitar no solo pérdidas de

información, si no también que esta se corrompa.

- Velocidad: vamos a trabajar con grandes cantidades de información, por lo que el retraso con el que se

mueva la información puede ser un punto crítico.

- Escalabilidad: añadir más capacidad de procesamiento al sistema debe ser lo más sencillo posible,

permitiendo incluso una adaptación dinámica, quitando y poniendo elementos según sea necesario.

Basándonos en todo lo anterior se ha realizado un estudio acerca de las diferentes herramientas que cumplen con

los requisitos citados. En el citado estudio (ubicado en el capítulo dedico a las tecnologías empleadas) se ha

justificado la elección de Kafka, además de describir sus componentes y funcionamiento básico. Partiendo de

ese conocimiento, abordaremos aquí la parametrización y configuración de Kafka dentro del presente proyecto.

Figura 5-15. Arquitectura básica de Kafka

Resumiendo lo visto anteriormente en detalle, Apache Kafka es un sistema de almacenamiento

publicador/subscriptor distribuido, particionado y replicado. Estas características, añadidas a que es muy rápido

en lecturas y escrituras lo convierten en una herramienta excelente para comunicar streams de información que

se generan a gran velocidad y que deben ser gestionados por uno o varias aplicaciones. Con respecto a la

estructura, Kafka se basa en un conjunto de servidores o nodos fundamentales, denominados Broker que, junto

a un nodo especial que ejecuta el software Apache Zookeeper componen el clúster. Serán los brokers quienes

manejen los datos, manteniendo la integridad de los datos. La información se estructura en canales o Topics, por

lo que se intercambian mensajes. La arquitectura se completa con los Producers (mandan mensajes al clúster) y

los Consumer (leen mensajes del clúster).

Para parametrizar Kafka debemos crear por tanto nuestro propio clúster, debiendo diferenciar claramente entre

el componente hardware y el software. Es decir, por una parte estarán los servidores físicos y por otra los

componentes software de Kafka: por ejemplo, es posible que corran varios brokers sobre un mismo servidor.

Nosotros nos centraremos en el componente software, pues se considera que no entra dentro del alcance del

Page 77: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

77

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

77

presente proyecto elegir los servidores sobre los que deben correr el sistema de intercambio o las aplicaciones

de la suite. Aun así, conviene recalcar que Kafka es una herramienta muy optimizada que no exige un alto coste

de procesamiento, por lo que no será necesario ningún procesador de especial capacidad. Gracias a lo anterior

podemos seguir manteniendo la coherencia con el argumentario establecido en la elección del hardware de

integración, apostando siempre por reducir el coste de instalación de MEDIPi al máximo posible.

Para la configuración partiremos de los binarios de ejecución existentes en la propia página web de Kafka [63],

modificando los ficheros de configuración adecuadamente.

5.4.1 Nodos

El punto de partida es la creación de un clúster que maneje la información biomédica. Hemos comentado que

existen dos tipos de nodos: Zookeeper y Broker.

- Zookeeper: pueden existir uno o varios nodos Zookeeper en un clúster de Kafka. Realizan las tareas de

coordinador de los diferentes brokers que compondrán el clúster llevando a cabo labores de

sincronización, configuración, registro, agrupación de nodos, elección de nodo/s líder/es, etc. Sus

opciones parametrización se modifican en un fichero zookeeper.properties. Al igual que ocurre en el

resto de elementos a comentar del presente apartado, las opciones de configuración de Zookeeper son

numerosas, por lo que solo nos centraremos en las que se han considerado necesarias para parametrizar

el clúster de MEDIPi. En el caso actual, se ha seguido la configuración básica recomendada por Apache

[64]:

Parámetro Valor Descripción

clientPort 2181 (valor por defecto) Puerto para la comunicación con los brokers

u otras instancias de ZK

dataDir /tmp/Zookeeper Directorio en el que ZK almacenará la

información temporal, logs, etc.

tickTime 2000

Tiempo en milisegundos de un tick, unidad

mínima de comunicación empleada por ZK.

Empleada para regular timeouts, keep-

alives, etc.

maxClientCnxns 0 Límite de conexiones para una misma IP

Para terminar, solo queda arrancar el nodo e indicar la ubicación del fichero de parametrización:

../bin/zookeeper-server-start.sh ../config/zookeeper.properties

- Broker: serán los nodos fundamentales del clúster, encargados de almacenar adecuadamente la

información y responder a las peticiones de los consumers que le correspondan a cada uno. Como ya se

describió con detalle el funcionamiento de los brokers de Kafka en el apartado correspondiente a las

tecnologías empleadas abordaremos aquí solo la configuración de los nodos, partiendo de los mismos

criterios expuestos para el Zookeeper y basándonos en las posibilidades de parametrización de la

versión de Kafka empleada de acuerdo a la documentación existente [65]:

Page 78: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

78

78

Parámetro Valor Descripción

broker.id 1 Clave única para la identificación de un bróker en el

clúster

listeners PLAINTEXT://:9093

Se trata de una lista separada por comas en las que

se informa de los puertos y protocolos que los

brokers ponen a disposición de producers y

consumers para el envío de información.

num.partitions 2

Número de particiones por defecto para cada topic.

Este valor influye, como ya hemos visto en la teoría

de Kafka, en la capacidad del clúster para balancear

la carga entre nodos

log.retention.hours 8

Tiempo mínimo de vida de un fichero de log antes

de ser marcado como eliminable. Se opta por un

valor poco elevado, para evitar que la gran cantidad

de ocupación movida por las constantes del

paciente pueda provocar un elevado consumo de

espacio en las máquinas donde se ubiquen los

nodos del clúster de MEDIPi

zookeeper.connect localhost:2181 IP del nodo Zookeeper al que se conectará

Al igual que ocurre con los nodos Zookeeper, iniciamos un servidor con la siguiente instrucción

../bin/kafka-server-start.sh ../config/server_0.properties

5.4.2 Topics

En la tecnología Kafka denominamos Topic a una categoría, canal u agrupación de mensajes para los que se

emplea una parametrización común. Es decir, un topic no es más que una manera de etiquetar mensajes,

agrupándolos en un mismo “canal”. Gracias a esta estructuración, un consumidor puede suscribirse a un topic y

acceder solo a los mensajes o paquetes de información ubicados bajo una determinada etiqueta. Sin embargo,

esta separación no tiene efectos solamente en el ámbito lógico o funcional, sino también en el técnico, pues cada

topic puede parametrizarse de manera independiente.

Abordemos en primer lugar los distintos topics que manejaremos en el presente proyecto:

Topic Descripción

LFConstantInfoTopic Constantes discretas de los diferentes usuarios de cualquier instancia del

software DDA.

HFConstantInfoTopic Constantes continuas de los pacientes recuperadas por DDA.

Esta división es fundamental, pues separamos dos tipos de datos clínicos que tienen características diferentes.

El gran caudal de datos que generan las señales “continuas” puede provocar un tratamiento diferenciado de las

señales discretas, tal y como hemos comentado ya en varias ocasiones. En nuestro caso, por ejemplo, se ha

implementado un modelo de base de datos enfocado solo a las variables biomédicas del primer tipo, pues se ha

mostrado como escasamente relevante en un primer nivel clínico las formas de ondas pasadas de los pacientes.

Sin embargo, habrá muchos otros ámbitos, entre ellos el diagnóstico médico en situaciones específicas o posibles

Page 79: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

79

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

79

estudios y análisis complejos en los que serán de gran interés. Por tanto, al establecer esta separación permitimos

que las aplicaciones de MEDIPi se nutran de uno, otro o ambos según sea necesario para el desarrollo de su

labor concreta. A lo anterior debemos sumar las ventajas en el tratamiento de datos que esta separación conlleva:

la cantidad de información que se mueve en el topic dedicado a las “formas de onda”, “variables continuas” o a

“tiempo real” (términos poco precisos como mínimo) es muy superior a la de las constantes discretas, por lo que

si ambos tipos de información convivieran en un mismo canal la explotación de las constantes discretas debería

pasar siempre por un proceso de filtrado, ralentizando el proceso que se pretenda llevar a cabo.

Además de definir funcionalmente qué tipo de información viaja agrupada bajo cada Topic, se ha de detallar la

parametrización básica de cada uno. Se ha comentado al principio del presente apartado que cada topic permite

aplicar una configuración específica y en este caso la existencia de dos tipos de información con algunas

características importantes diferenciadoras nos obliga a establecer algunos matices entre sus parametrizaciones.

En este momento describiremos solamente los parámetros a abordar, dejando los valores concretos para

apartados ulteriores.

Parámetro Descripción

partitions

El número de particiones especifica en cuántas partes de dividirá un topic. Es

importante entender que cada partición se ubicará completamente en un solo servidor,

de forma que la cantidad de particiones impactará en la capacidad de paralelismo. Por

tanto, podemos dividir un topic en más particiones que nodos existentes, pero no podrá

repartirse la carga en más nodos que números de particiones.

replication-factor

Controla cuantos servidores (nodos brokers) replicarán cada mensaje escrito. Salvo

casos muy básicos es imprescindible que haya al menos 2 servidores, no solo para que

exista redundancia y tolerancia a fallos, si no para poder manejar transparentemente

los servidores implicados. Es decir, si solo tenemos un nodo cada vez que se necesite

realizar una labor de mantenimiento en este se deberá parar, aunque sea

momentáneamente todo flujo de datos, mientras que la existencia de varios nodos

permite ir moviendo uno a uno los servidores de un nodo a otro de forma totalmente

transparente y sin interrumpir la comunicación con consumers y producers.

La configuración puede volverse mucho más compleja, permitiendo modificar un amplio abanico de parámetros,

tal y como se especifican en la documentación oficial [66].

Antes de finalizar comentemos las instrucciones empleadas para el manejo de los topics:

../bin/kafka-topics.sh --create --Zookeeper 127.0.0.1:2181 --replication-

factor 2 --partitions 1 --topic LFConstantInfoTopic

../bin/kafka-topics.sh --alter --Zookeeper 127.0.0.1:2181 --partitions 2

--topic LFConstantInfoTopic

../bin/kafka-topics.sh --delete --Zookeeper 127.0.0.1:2181 --topic

LFConstantInfoTopic

Como observamos, aquí no existe ningún fichero de configuración como ocurría en los Zookeepers o en los

Brokers, si no que los distintos parámetros y sus valores se comunican en la creación / edición del topic

pasándose como argumentos de entrada al binario de Kafka encargado de tales labores. Se observa que la

fórmula empleada es la habitual en el trabajo con cualquier programa mediante línea de comandos: se especifica

el parámetro precedido por un doble guion y, a continuación, el valor que se quiere indicar.

Page 80: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

80

80

5.4.3 DTOs

Ya prácticamente tenemos definida la totalidad de elementos básicos que compondrán nuestro clúster, a la espera

de tratar un poco más adelante la configuración de producers y consumers. Solo nos queda comentar qué

información enviaremos y cuál será el método que emplearemos para codificarla.

Con respecto al primer punto, se han definido dos objetos de transferencia de datos (DTO), uno para cada topic,

ya que no se intercambia exactamente la misma información por ambos canales.

LFConstantInfo HFConstantInfo

Tipo Atributo Tipo Atributo

Long constantId Long constantId

Long episodeId Long episodeId

Date constantDate Date startDate

String value String[] value

Float period

Boolean manual Boolean manual

Como se observa, hay pocas diferencias entre ambos objetos, más allá del campo periodo para indicar el tiempo

en milisegundos que separan a cada muestra del array de valores. Se ha optado por emplear en el intercambio

de información un objeto específico, pudiendo haberse empleado una instancia de CONSTANT_INFO para el

topic de información a baja frecuencia y una versión adaptada del mismo para el HFConstantInfoTopic. La

opción tomada permite enviar solo la cantidad de información realmente necesaria, de forma que el resto de

datos que deben conocerse para poder formar un registro de ConstantInfo pueden deducirse u obtenerse

mediante una consulta a base de datos. Con esta medida se reduce la cantidad de información que se intercambia

por el clúster, permite a un nodo almacenar más mensajes con el mismo espacio y, sobretodo, permite a

cualquiera acceder a la información sin necesidad de conocer el modelo de datos de MEDIPi. Este último punto

es muy interesante en nuestra búsqueda de gran modularidad: un nuevo módulo podría, aunque sería poco

probable, no necesitar conectarse bajo ninguna circunstancia a la base de datos, por lo que le bastaría con la

información consumida de Kafka para trabajar. Por otro lado, si enviáramos un objeto correspondiente

totalmente a un registro de CONSTANT_INFO facilitaríamos la tarea del módulo Saver, que solo tendría que

realizar un insert o update. Tomándose en consideración ambos puntos de vista se ha optado por optimizar la

información transmitida, aunque eso implique que Saver deba realizar algunas acciones más antes de almacenar

una constante en base de datos. Es preferible apostar por un modelo flexible que tomar decisiones que solo

beneficien a una aplicación de la suite.

Una vez conocido el DTO es necesario analizar qué alternativas existen a la hora de transmitirlo o codificarlo

para su emisión por el clúster. Gran parte de esta labor se ha realizado cuando se ha comparado el formato de

texto JSON con otras posibilidades en el capítulo destinado a las tecnologías empleadas en el proyecto, pero aun

así conviene comentar aquí algunos datos importantes:

{"constantName":" Frecuencia cardiaca

","constantId":1,"episodeId":1,"constantDate":"May 26, 2016 1:27:24

PM","value":"90.89457584984491","manual":false}

El párrafo anterior supone una muestra concreta de un valor para la constante vital de un paciente de prueba. Si

Page 81: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

81

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

81

observamos con atención es fácil deducir que se trata de una representación determinada del DTO

LFConstantInfo definido unas líneas más arriba. El objeto Java definido con los atributos ya comentados se

transforma en un texto que sigue el esquema

“nombreAtributoUno”:”valorUno”,”nombreAtributoDos”:”ValorDos”, de acuerdo al formato JSON. Gracias a

él, o mejor dicho a una determinada librería que implementa ese formato en Java) podemos transmitir un texto

plano que apenas llegará a pesar 1KB, una cantidad irrisoria para lo que un clúster de nodos Kafka es capaz de

manejar.

5.4.4 Modelo

Una vez detallados los tipos de nodos, su funcionalidad y su parametrización básica ya podemos intuir algunas

características básicas del clúster de MEDIPi. A lo deducido anteriormente debemos añadir una reflexión

fundamental: la dimensión que deberá tener el clúster, algo que nos indicará el número de nodos y servidores de

un tipo u otro que deberemos manejar. Aquí nos encontramos ante un evidente dilema: no podemos seguir

realizando un estudio “general” como hasta ahora, en el que indicábamos las características de la solución

diseñada ignorando casi por completo el número de usuarios implicados, concurrencia, cantidad de datos a

manejar, etc. En resumen, por cada implantación posible de la solución habrá que realizar un pequeño estudio

acerca de la cantidad de información que se va a procesar, importancia de los datos, necesidad de redundancia

y control de errores, etc.; no pudiendo establecerse un modelo genérico para todos los casos. Aun así, con objeto

de clarificar cómo debe ser un clúster de MEDIPi se aborda un modelo “mínimo”, de acuerdo a unas nociones

concretas adquiridas tanto por la práctica como por el análisis inicial de los actores implicados.

Como se comentó adecuadamente en el apartado dedicado a la teoría de la tecnología empleada, un clúster Kafka

mantiene un log particionado por cada topic, de forma que estas1 particiones son distribuidas a través de los

diferentes brokers. Número de particiones y parametrización de los mimos están, como ya hemos visto en el

punto anterior, íntimamente relacionados con la capacidad de paralelismo del clúster.

Figura 5-16. Modelo del clúster

Page 82: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

82

82

Con la figura superior se pretende escenificar la arquitectura del modelo mínimo propuesto en el presente

proyecto:

- Servidores: 1 nodo Zookeeper y 2 nodos brokers, servidores para el balance de carga

- Topics: los dos topics indicados, ambos con factor de replicación 2 (existen 2 servidores). Para el topic

de las constantes discretas se ha optado por dos particiones, mientras que se amplía a una tercera en el

caso del topic para las constantes biomédicas “continuas” de los pacientes.

En el esquema se pretende escenificar el control que los brokers realizan de las particiones mediante un resaltado

en negrita. Este aspecto no pertenece al ámbito del usuario, si no que forma parte de las tareas de balanceo de la

tecnología Kafka elegir qué nodo maneja qué partición partiendo de la configuración proporcionada y el

algoritmo del protocolo. Para conocer cuál es el balanceo real de un topic podemos ejecutar la siguiente

instrucción de Kafka:

../bin/kafka-topics.sh --describe --Zookeeper localhost:2181 --topic

LFConstantInfoTopic

Topic:LFConstantInfoTopic PartitionCount: 2 ReplicationFactor:2 Configs:

Topic: LFConstantInfoTopic Partition: 0 Leader: 1 Replicas: 1,0 Isr:

1,0

Topic: LFConstantInfoTopic Partition: 1 Leader: 0 Replicas: 0,1 Isr:

0,1

Donde observamos, para cada partición del topic:

- Quién es el “líder” de cada partición, responsable de las lecturas / escrituras de dicha partición.

- Lista de nodos que replicarán la partición, independientemente de que sean el líder o no.

- Nodos actualmente disponibles de la lista de nodos replicas.

5.4.5 Producers

Sabemos que un Producer es cada uno de los “escritores” de un Topic, es decir, son los actores que representan

la entrada de información en un topic determinado. Si volvemos al esquema del modelo de arquitectura que se

ha definido para la suite software de MEDIPi observamos que solo se ha definido un elemento que realice este

rol: el módulo de adquisición de datos de biodispositivos DDA.

A partir de aquí vamos a comenzar una nueva parte del sistema de intercambio de información, saliéndonos del

clúster en sí mismo, por lo que dejamos de trabajar con la línea de comandos arrancando servidores, indicando

ficheros de configuración, pasando parámetros al ejecutable, etc. Como producers (y también consumers) se

manejarán desde el código de los módulos emplearemos la implementación Java de Kafka para tales labores.

En este apartado vamos a detallar el proceso que seguimos en el código para la correcta creación y configuración

de un producer, así como las instrucciones empleadas en el envío de constantes biomédicas al clúster. Más

adelante, cuando detallemos el software de los módulos implicados, veremos cómo determinados aspectos de

diseño y programación del código se relacionan con el producer (clase Java que lo llama, estructura dentro de la

aplicación, ubicación de los valores, etc.)

Siguiendo la misma estructura que en puntos anteriores, comenzamos abordando las distintas opciones de

parametrización posibles y justificando los valores empleados:

Page 83: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

83

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

83

Parámetro Valor Descripción

bootstrap.servers Server0Ip:port,

Server1Ip:port,…

Lista de ips:puertos empleada para la

comunicación inicial con el clúster Kafka.

Mediante estos datos se iniciará el primer

intercambio de información con algunos de

los brokers indicados. Una vez realizada la

comunicación inicial se accede a los nodos

reales del clúster (que pueden modificarse

dinámicamente) y esta información deja de

usarse.

key.serializer org.apache.kafka.common.

serialization.LongSerializer

Clase serializadora para la clave. En

nuestro caso la clave será un numérico de

tipo long.

value.serializer org.apache.kafka.common.

serialization.StringSerializer

Clase serializadora para el valor. En nuestro

caso intercambiamos texto plano.

acks 1

Número de acks que necesita recibir el

producer antes de enviar los datos al

clúster:

0: no se espera ningún ack, el mensaje se

envía inmediatamente por el socket y se

considera enviado

1: se espera a que al menos el nodo bróker

líder la partición implicada devuelva ack

All: se espera a que todos los nodos que

trabajen con la partición (líderes y

seguidores) envíen su consentimiento.

buffer.memory 33554432

Número de bytes que el producer

mantendrá en su buffer a la espera de ser

enviados al servidor.

retries 1 Número de reintentos

linger.ms 1000

El producer agrupará en un batch los

mensajes o records antes de enviarlos al

servidor. Este parámetro especifica el

tiempo a esperar entre cada envío,

agrupando durante ese periodo todos los

records recibidos.

batch.size 102400

Tamaño máximo del batch. Se producirá un

envío siempre que se alcance este valor

máximo para el batch, independientemente

del retraso indicado en el linger.ms. Se

combina con el parámetro anterior para

definir una política que oscile entre valores

que permitan una escritura/lectura casi a

tiempo real y la optimización del número

de peticiones/respuestas intercambiadas

con los servidores.

Page 84: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

84

84

metadata.fetch.timeout.ms 500 Timeout de la operación realizada en el

intercambio del primer mensaje al topic

timeout.ms 1000 Timeout del ack del servidor

El código que debe tratar el arranque de un Producer de la tecnología Kafka comenzará siempre por la gestión

de la parametrización; en nuestro caso, informando al producer de la configuración arriba detallada:

Properties props = new Properties();

props.put("bootstrap.servers", "localhost:9093, localhost:9094");

La fórmula diseñada por Kafka para dotar de la adecuada configuración a sus Producers Java consiste en la

instanciación de un objeto Properties (java.util) al que seteamos, como si de un simple mapa se tratase, una

pareja nombre -valor por cada parámetro que deseamos indicar. De esta manera podemos arrancar varios

Producers con igual configuración a partir del mismo objeto, tal y como observamos a continuación. Además

de informar a la nueva instancia de Producer creado de su parametrización indicamos los tipos de clave

(primer tipo) y valor (segundo tipo) que deberá manejar.

Producer<Long, String> producer = new KafkaProducer<Long, String>(props);

Gson gson = new Gson();

String msg = gson.toJson(constantInfo);

ProducerRecord<Long, String> producerRecord = new ProducerRecord<Long,

String>(AppConstants.KAFKA_TOPIC_CONSTANTINFO, msg);

producer.send(producerRecord);

En este segundo bloque se realiza la conversión al formato de intercambio. La librería Gson empleada nos

permite crear rápidamente un texto que represente, de acuerdo al estándar JSON, un objeto Java recibido. En

este caso le pasamos una instancia de tipo ConstantInfo (la cual no es más que el mapeo de la entidad

correspondiente de Base de Datos) y nos construye un String con los atributos del objeto y sus valores. Gson

también puede ser configurada, pues puede no existir una representación única de un valor baja determinadas

circunstancias. Por ejemplo, podemos tomar la decisión de representar los valores sin informar (null) como una

cadena de texto ‘null’, o una cadena vacía.

Una vez terminada la conversión, creamos un “mensaje”, lo que en Kafka se conoce como un Record o

ProducerRecord, indicando simplemente topic, clave y mensaje. Parémonos un momento a analizar las

posibilidades de instanciar una clase ProducerRecord. El constructor de la clase ProducerRecord puede recibir

los siguientes parámetros:

A) Topic - Value B) Topic – Partition_Id - Value

C) Topic – Key - Value D) Topic – Partition_Id – Key - Value

Topic y value (el mensaje a transmitir) son los únicos parámetros constantes. El resto de posibilidades no son

más que la combinación de la posibilidad de incluir la clave del mensaje y un identificador de la partición a la

que queremos enviar el mensaje. En el capítulo de teoría de Kafka del presente proyecto se ha documentado la

importancia de las claves y las particiones. Como bien se ha explicado, debatir la necesidad de informar de una

clave anexa al mensaje implica necesariamente debatir qué modo queremos emplear para el envío de

información. Para ello realizaremos una doble clasificación:

Page 85: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

85

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

85

Clasificación 1: Modos

- Modo clásico: los brokers manejarán particiones compuestas por los distintos records. Formarán una

cola de mensajes.

- Modo compacto: se emplea una determinada configuración de los brokers implicados que nos permite

almacenar solo el último valor asociado a una clave. Podría entenderse como un mapa clave-valor a

gran escala.

Clasificación 2: Orden

- Sin orden: Kafka no realizará acciones especiales para intentar mantener el orden correcto en los

mensajes de un topic. El almacenamiento en el log es FIFO, los datos más antiguos serán los primeros

en ser eliminados del log. Sin embargo, la distribución de records entre particiones, así como otros

factores menores pueden provocar un desordenamiento de la información. Solo la información

gestionada por una misma partición se mantiene ordenada.

- Con orden: todos los mensajes pertenecientes a un determinado grupo o categoría se manejarán en orden

de llegada. Es importante entender que no se puede hablar de un estricto orden temporal: somos

conscientes de la existencia de los ya comentados “batch” en los producers, que agrupan records antes

de ser enviados al bróker. Por tanto, pueden producirse alteraciones del orde1n en situaciones de

múltiples producers.

De lo anterior se deduce que enviar mensajes controlando la partición destino (opciones B y D) nos permite

garantizar en gran medida el ordenamiento temporal de los records en el log. De igual forma, los mensajes que

comparten clave son gestionados por la misma partición, ya sea mediante el modo clásico o eliminando las

duplicidades para crear un log compacto. Con todo esto sobre la mesa nos preguntamos qué categorías deben

aplicar en nuestra situación: está claro que no necesitamos emular ningún mapa, la información enviada por

alguno de los topics deberá ser leída en orden de entrada, sin ningún tratamiento específico. Además, nos interesa

mantener un orden temporal, pero no es necesario que este sea totalmente estricto, pues las aplicaciones que leen

del clúster directamente emplean la fecha (presente en el value) para realizar el tratamiento que deseen a los

datos recibidos. Este asunto puede provocar algún malentendido: Kafka es una aplicación diseñada para manejar

gran cantidad de datos a tiempo real, por lo que siempre pone el foco en mantener un correcto ordenamiento

temporal de los mensajes intercambiados. El uso de técnicas o parámetros que intentan reducir al mínimo la

posibilidad de desórdenes es interesante pero desproporcionada para el proyecto actual, en tanto que implican

limitar otras capacidades de la tecnología, como por ejemplo la disminución del balanceo entre brokers que se

produce al forzar manualmente una misma partición. Por tanto, lo más conveniente es optar por el constructor

A, que emparejamos con el modo clásico sin orden temporal estricto.

5.4.6 Consumers

Un consumer es un lector de la información “almacenada” en el clúster. En el caso de la suite software de

MEDIPi observamos que tenemos dos aplicaciones que deberán ser consumidoras del clúster: Saver y Chart.

Una vez más trabajaremos aquí con la implementación java de Kafka.

Al tratar con dos consumers claramente diferenciados vamos a abordar la parametrización para cada uno de

ellos, aunque la mayor parte de la configuración sea común.

Parámetro Saver Chart Descripción

group.id

saverGroup

(Se producirá

balanceo de

mensajes entre

[No informado]

(Cada ejecución

de Chart recibirá

los mismos datos)

Identificador del grupo de consumers. La

pertenencia a un grupo de consumers afecta

a la recepción de datos.

Un record solo se envía a un consumer de

Page 86: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

86

86

las instancias de

saver)

un grupo, permitiendo de esta manera

balancear la carga entre los consumers.

bootstrap.servers Server0Ip:port,Server1Ip:port,…

Lista de ips:puertos empleada para la

comunicación inicial con el clúster Kafka.

Mediante estos datos se iniciará el primer

intercambio de información con algunos de

los brokers indicados. Una vez realizada la

comunicación inicial se accede a los nodos

reales del clúster (que pueden modificarse

dinámicamente) y esta información deja de

usarse.

key.deserializer org.apache.kafka.common.

serialization.LongDeserializer

Clase deserializadora para la clave. En

nuestro caso la clave será un numérico de

tipo long.

value.deserializer org.apache.kafka.common.

serialization.StringDeserializer

Clase deserializadora para el valor. En

nuestro caso intercambiamos texto plano.

auto.offset.reset earliest latest

Política a emplear en la inicialización del

offset en la primera petición o cuando haga

referencia a un valor incorrecto:

- Earliest: primer mensaje del log

- Latest: último record en el log.

Módulo LFConstantInfoTopic RealTimeLFConstantInfoTopic

Saver SÍ NO

Chart SÍ SÍ

La configuración de los dos consumers de Chart (uno para cada topic) es similar.

La parametrización común no requiere más detalles de los ya comentados, pero si es conveniente analizar con

mayor finura las decisiones detrás de las diferencias de configuración entre nuestros dos módulos, pues radican

en las distintas funcionalidades de los módulos y nos permiten comprender algunos aspectos más de Kafka.

Como ya sabemos de sobra, Saver es el módulo encargado de consumir del clúster los datos biomédicos para,

tras un filtrado básico, almacenarnos en una base de datos. Por su parte, Chart recibe los valores actuales de

parámetros vitales de un paciente y nos muestra una gráfica a tiempo real de los mismos. Las características de

ambos sistemas son diferentes, pero podemos simplificar sus diferencias en una sola frase: Saver necesita todos

las constantes médicas, presentes y pasadas, para poder almacenarlas adecuadamente; mientras que Chart solo

empleará las últimas. Esta es la idea que está detrás de la heterogénea configuración.

Para Saver emplearemos el group.id, una técnica de Kafka que permite balancear los records que serán

procesados entre los distintos consumers de un grupo. De esta manera, podemos arrancar varias instancias de

Saver en distintas máquinas que se encarguen, en paralelo, del almacenaje en base de datos de la formación.

Además, no queremos dejar ningún dato sin procesar, por lo que cuando se arranque una instancia de Saver se

buscará el primer mensaje del log, procesando el resto a partir de él. Se debe tener cuidado con esta

configuración, si el log abarca mucha información se reprocesarán una gran cantidad de mensajes. En nuestro

caso hemos puesto un periodo de “backup” o de retención en los logs bastante corto y contamos con que

podemos arrancar varias instancias en paralelo que agilicen el procesado de todos los datos desde el primero.

Page 87: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

87

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

87

Además, estamos hablando del topic ConstantInfo, el que menos volumen de bytes mueve. Eso sí, si alguna de

las condiciones comentadas en este párrafo cambiara debería replantearse esta parametrización.

Properties props = new Properties();

props.put("bootstrap.servers", "localhost:9093, localhost:9094");

...

KafkaConsumer<Long, String> constantInfoConsumer = new

KafkaConsumer<>(props);

constantInfoConsumer.subscribe(Arrays.asList(AppConstants.KAFKA_TOPIC_CONSTAN

TINFO));

ConsumerRecords<Long, String> records =

constantInfoConsumer.poll(SaverConstants.KAFKA_POLL_TS);

for (ConsumerRecord<Long, String> record : records) {

Gson gson = new Gson();

DataWriterManager.writeConstantInfoToAll(gson.fromJson(record.value(),

ConstantInfo.class));

}

En las líneas superiores tenemos las instrucciones que se emplean, grosso modo, en ambos módulos para

instanciar un consumer a través de la API Java de Kafka. Al igual que ocurría con los producers, comenzamos

indicando los parámetros y sus valores, e instanciando un KafkaConsumer y pasándolo el objeto Properties que

contiene la configuración. Tras suscribirse al topic del que deseamos recibir mensajes se realiza un poll. Con un

poll estamos realizando una petición al clúster para recibir un array de records, indicando como parámetro de la

operación el tiempo que se debe esperar mientras no hay datos disponibles. Si el clúster dispone de un nuevo

record antes de que se cumpla ese plazo se termina la acción devolviéndoselo; mientras que si se cumple el

timeout sin tener ningún mensaje disponible se termine la espera devolviendo un array vacío de records. En

nuestro caso lo hemos establecido en 1000 milisegundos. Ya podemos recorrer el array de records recibidos

(ConsumerRecords) y traducir el mensaje enviado mediante JSON de cada ConsumerRecord a un objeto Java

del tipo que corresponda según el topic del que proviene.

Set<TopicPartition> topics = constantInfoConsumer.assignment();

topics.forEach(partition -> constantInfoConsumer. seekToBeginning (partition, record.offset()));

Las líneas de código superiores no se corresponden directamente con ninguna parte de los desarrollos, pero nos

ayudan a explicar algunos conceptos con los que hemos trabajado. Así vemos como podemos recuperar las

particiones de un topic mediante la primera instrucción y trabajar con ellas. Podemos indicar mediante el método

seek el offset a partir del cual queremos leer. En el parámetro auto.offset.reset indicamos por donde comenzar a

leer tras arrancar un consumer, mientras que estas instrucciones permiten muchas más opciones, pues podemos

invocar un seek a un punto determinado del log en varias partes del código. Por ejemplo, podríamos tener interés

en reprocesar determinados mensajes bajo algunas circunstancias de manera dinámica gracias a estas

instrucciones.

Con toda esta información ya conocemos qué sistema de intercambio de información vamos a implementar, su

modelo y arquitectura concreta, así como el conjunto de instrucciones que deberemos emplear para iniciar y

configurar de acuerdo a nuestras necesidades cada uno de los elementos que lo componen. Con esta información

es el momento de abordar el resto de elementos software del presente proyecto.

Page 88: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

88

88

Componentes software

Nos embarcamos ahora en la parte central del proyecto. A lo largo del actual capítulo ya hemos comentado que

la parte software del proyecto estará compuesta por tres aplicaciones independientes enfocadas a tareas distintas.

Nombre del módulo Icono Descripción

Device Data

Acquisition

DDA

Componente software encargado de establecer la

comunicación con los biodispositivos y recuperar la

información biomédica.

SAVER

Módulo que persistirá la información recopilada por

DDA en base de datos

CHART

Aplicación de visualización de las constantes

biomédicas de los pacientes en tiempo real.

5.5.1 Estructura del software del proyecto

Las tres aplicaciones se van a comportar como módulos independientes, de forma que cada uno puede ejecutarse

en una máquina completa, aunque habrá muchos elementos en común. Por tanto, es lógico pensar que tendremos

tres proyectos diferentes que se sustenten en un cuarto proyecto común que aglutine las utilidades o

dependencias empleadas por todos los módulos. Además, en el capítulo anterior hemos realizado una

comparativa entre las distintas opciones existentes para manejar las comunicaciones con la base de datos,

eligiendo finalmente emplear JPA (Java Persistence Api) con Hibernate como implementación. Ya que el

estándar JPA implica definir clases java que mapeen las tablas del modelo de base de datos parece evidente que

todas las clases formen parte de ese “proyecto” común que los tres módulos emplearán.

Durante el apartado dedicado a la base de datos se ha establecido un modelo de datos compuesto por dos

esquemas: uno específico de la adquisición de datos DATA_ACQ y otro genérico de cualquier software del

ámbito sanitario denominado HEALTH. Durante la explicación del diseño se ha hecho especial hincapié en que

el esquema HEALTH sea independientemente, de forma que si se construye un módulo que no trabaje con la

información almacenada en las tablas del esquema de adquisición de datos no sea necesario, en este caso,

importar las clases java que construyan su mapeo de datos. Por tanto, sería ahora incoherente no crear dos

librerías diferenciadas. En esta línea vamos a ir un paso más allá, llevando a una tercera librería toda la lógica

común de nuestro uso de JPA (clases abstractas, métodos útiles empleados por todas las aplicaciones que quieren

acceder a base de datos, patrones de acceso que deberán emplearse, etc.). Conforme avancemos y vayamos

tratando el contenido de cada una de estas librerías se irá comentando con mayor detalle porqué es más correcta,

funcional y técnicamente, la estructura escogida frente a otras.

Page 89: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

89

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

89

Figura 5-17. Estructura de Proyectos DOM (Document Object Model) (Base de datos)

En el párrafo anterior hemos tratado las librerías que van a proporcionar acceso a la base de datos a todos los

módulos o aplicaciones que así lo deseen. Parece lógico realizar una tarea similar con el acceso al sistema de

intercambio de información, al clúster Kafka. Por tanto, contaremos con otra librería que agrupe la lógica común

de acceso a los consumers y producers de Kafka empleados, el modelo de datos de los objetos empleados, las

librerías Java específicas para tales labores, etc. Las aplicaciones que deseen trabajar con Kafka (actualmente

las tres diseñadas) deberán importar esta librería. Gracias a esto se evita duplicar código: no es necesario que en

2 aplicaciones se haga la misma acción (instanciar un consumer de Kafka, subscribirse al topic, arrancar un hilo

para leer datos, etc.) si no que toda esta información está centralizada en una única librería evitando duplicidades.

Sin embargo, es fácil imaginar un módulo de MEDIPi que no necesite acceso al clúster. Por ejemplo, se puede

crear una aplicación de gestión de la historia clínica de un paciente que tenga más que suficiente con la

información biomédica almacenada en la base de datos. En ese caso no será necesario importar esta librería,

evitando cargar con clases inútiles.

Figura 5-18. Estructura de Proyectos Cluster (Kafka)

A pesar de todo lo descrito hasta el momento, todavía es posible encontrarnos con elementos duplicados y lógica

repetida entre las tres aplicaciones descritas (DDA, Saver y Chart). Se trata de la gestión de Logs, properties,

constantes comunes, métodos Java implementados que son útiles para el tratamiento de la información

biomédica en más de un ámbito, etc. Para evitar esto, concluimos la modularización de la suite definiendo una

nueva librería que agrupa lógica común para varias de las aplicaciones o módulos de MEDIPi.

Figura 5-19. Estructura de Proyectos App (Elementos comunes de aplicaciones MEDIPi)

Una vez conocidos los tres grupos funcionales en los que se han divido las librerías diseñadas para la suite

MEDIPi es el momento de plantear como será la relación entre los tres módulos (DDA, SAVER y CHART) y

cada una de ellas.

Page 90: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

90

90

Figura 5-20. Estructura de Proyectos MEDIPi. Representación gráfica.

Con el objetivo de clarificar la arquitectura software diseñada se han empleado un conjunto de normas y códigos

de colores que se procede a explicar a continuación:

- Los rectángulos con bordes discontínuos representan elementos que son exclusivamente proyectos

Maven; es decir, indican que un determinado proyecto actua sólamente como padre de un conjunto de

hijos, sin tener código Java asociado. Por tanto, las líneas que van de un proyecto de este tipo a un

componente buscan indicar una relación padre-hijo.

- Los rectángulos de línea contínua representan proyectos Maven y Java. Serán hijos de proyectos padres

exclusivamente Maven. Además, se representarán las depenencias con otros proyectos de la suite

mediante una línea contínua.

- Las librerías MEDIPi-DOM se representan en naranja. Serán todas aquellas que contengan clases,

métodos u objetos relacionados con el acceso a la base de datos.

- Las librerías MEDIPi-Cluster se representan en verde. Bajo esta categoría clasificamos toda librería que

agrupe funcionalidad relacionada con el acceso y gestión del Cluster Kafka.

Page 91: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

91

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

91

- Las librerías MEDIPi-App se representa en azul. Todo proyecto que contenga bien un módulo de

MEDIPi, bien una librería de utilidades para las aplicaciones se incluirá en este grupo.

- Toda aplicación o librería de la suite se sustenta en una serie de convenciones o elementos básicos. Para

el acceso a base de datos estos se encuentran en core_dom, mientras que para la comunicación con el

clúster se ubican en core_cluster. Por tanto, las librerías cuya denominación empieza por core- se

consideran fundamentales: todo proyecto o librería de una categoría se debe sustentar sobre la clase

core correspondiente de su sector.

No conviene olvidar la clasificación realizada, pues no solo se trata de una categorización funcional, sino que

también tiene implicaciones técnicas, tal y como veremos un poco más adelante.

Para poder trabajar con tantas librerías y proyectos relacionados entre sí se emplea la herramienta de Apache

conocida como Maven, adecuadamente documentada en secciones previas de esta memoria. La especialidad de

maven es la gestión de dependencias, un auténtico quebradero de cabeza en una suite de productos como la aquí

diseñada Es evidente que no solo debemos lidiar con que muchos proyectos compartan dependencias (sobre

todo los que pertenecen a una misma categoría) sino también con la existencia de dependencias internas dentro

de la suite. A todo lo anterior Apache suma varias utilidades ya comentadas: gestión de javadoc, compilación

del proyecto en el jar correspondiente, filtrado de recursos, etc. Por tanto, conforme se avance en la descripción

de los distintos proyectos, junto al detalle del código empleado se irá comentando la configuración de Maven

escogida.

Figura 5-21. Estructura de Proyectos MEDIPi. Representación en carpetas

Page 92: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

92

92

5.5.2 MEDIPI Suite

En la imagen con la que se cerraba el punto anterior se puede observar la estructura de carpetas del código actual

de la suite MEDIPi. Los diferentes proyectos se agrupan bajo un directorio con el nombre de la categoría

correspondiente, incluyendo un archivo de Maven pom.xml para gestionar la parametrización común. En el

primer nivel se observa que, además de los directorios de las distintas categorías, existe un fichero pom.xml. Su

contenido es el siguiente.

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>medipi</groupId>

<artifactId>medipi-suite</artifactId>

<version>1.0</version>

<packaging>pom</packaging>

<modules>

<module>medipi-dom</module>

<module>medipi-Cluster</module>

<module>medipi-app</module>

</modules>

<properties>

<JAVA_1_8_HOME>C:\Program Files\Java\jdk1.8.0_65</JAVA_1_8_HOME>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.3</version>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-resources-plugin</artifactId>

<version>2.7</version>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-source-plugin</artifactId>

<version>2.4</version>

</plugin>

</plugins>

</pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<source>1.8</source>

<target>1.8</target>

<encoding>UTF-8</encoding>

<executable>${JAVA_1_8_HOME}/bin/javac</executable>

<fork>true</fork>

</configuration>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-resources-plugin</artifactId>

<configuration>

Page 93: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

93

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

93

<encoding>UTF-8</encoding>

</configuration>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-source-plugin</artifactId>

<executions>

<execution>

<id>attach-sources</id>

<goals>

<goal>jar</goal>

</goals>

</execution>

</executions>

</plugin>

</plugins>

</build>

<dependencies>

<!-- LOG -->

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.7.21</version>

</dependency>

</dependencies>

</project>

Gracias a este pom se está definiendo un proyecto padre o proyecto general, del que colgarán todos y cada uno

de los proyectos de MEDIPi. Dicha definición se encuentra al principio del fichero: se trata de un proyecto de

nombre “medipi-suite”, de la organización o grupo “medipi”, con versión “1.0-RELEASE” y empaquetamiento

“pom”. Esto último indica que no se trata de un proyecto java, en cuyo caso se indicaría empaquetamiento jar,

war o el que correspondiera, sino de una agrupación de proyectos de maven. La utilidad de esto es que podemos

definir una serie de características comunes a todos los hijos de este proyecto sin tener que duplicar el código en

cada uno de ellos.

En la siguiente región se observan los módulos o hijos del proyecto: se tratan de las categorías comentadas, algo

que coincide perfectamente con el árbol de directorios mostrado más arriba. Parece lógico entender que se va a

realizar una acción similar con cada una de ellas: cada categoría tendrá otro pom padre, que gestionará los

recursos o parametrizaciones Maven comunes a todas las librerías que pertenezcan al grupo.

La sección properties indica una serie de propiedades que heredaran todos los hijos de este proyecto, tanto los

de primer nivel como los de niveles inferiores. En este caso, solo se especifica la ubicación del JDK empleado

en la compilación y la codificación a emplear en los ficheros. Por tanto, gracias a este pom padre los

desarrolladores se ahorran duplicar esta información en el pom de cada proyecto. Además, en ningún momento

se pierde independencia, pues cada proyecto puede compilarse independientemente siempre que se pueda

acceder a los pom superiores.

La etiqueta build agrupa un conjunto de acciones que se realizan durante la compilación del proyecto. En este

caso, se especifica que todo proyecto de medipi deberá compilarse con la versión 8 de java y los ficheros se

trataran con la codificación UTF-8. Con el primer plugin se indica la generación del jar clásico, mientras que

con el tercero se obliga a crear otro jar que incluya los ficheros fuente. En el capítulo dedicado a la tecnología

Maven se comentó con más detalle la utilidad de los plugins y el ciclo de trabajo de maven, pero conviene

Page 94: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

94

94

repasar un par de cuestiones básicas en este punto. Los plugin de Maven llevan a cabo una funcionalidad

específica. Para emplearlos se indica su versión, configuración y se asocian a una determinada meta. Maven

tiene un ciclo de funcionamiento organizado por fases (preparación, compilación, empaquetado, etc.), de forma

que se ejecutan de forma secuencial. Además, cada fase se subdivide en metas o goals. Todo plugin se asocia a

una fase concreta, algunos de forma explícita (cuando se indica mediante los atributos execution) y otros

implícita (se asignan a la fase y meta por defecto).

La última de las secciones es la más importante, aquella que supone el centro de Maven: la gestión de

dependencias del presente proyecto. En nuestro caso se está indicando una serie de librerías de logs que todo

proyecto de MEDIPi incorporará, debiendo usarla para informar de avances, problemas, errores, etc. Se ha

comentado anteriormente que la configuración aquí indicada se replica para todos y cada uno de los proyectos

hijos. Por tanto, health-dom incorpora a librería de log4j especificada, así como el proyecto core-dom, que a su

vez también usa la citada librería. Es decir, se está produciendo una duplicidad, de forma que bajo el ahondamos

en el jar de health-dom deberíamos ser capaces de encontrar dos log4j-1.2.17.jar. Sin embargo, esto no ocurre:

Maven conoce que ambos proyectos tienen un padre común, por lo que automáticamente importa solo una

librería log4j, ahorrando espacio y previniendo futuros errores. Además, cuando especificamos una librería

Maven en el pom es posible realizar exclusiones, filtrando aquellas de sus librerías hijas que no deseamos. Toda

esta funcionalidad es la que hace de Maven una herramienta tremendamente útil para proyectos tan

modularizados como el nuestro.

5.5.3 MEDIPi-DOM

Se trata de un proyecto maven que pretende agrupar los elementos comunes en la gestión y construcción de

todos los proyectos DOM de la suite MEDIPi, incluyendo dependencias compartidas y repositorios comunes.

Se observa que cada una de las tres categorías en las que se ha dividido funcionalmente los proyectos de MEDIPi

se corresponde con un proyecto maven que centraliza los parámetros de construcción compartidos por todos los

módulos de dicha categoría.

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-suite</artifactId>

<version>1.0</version>

</parent>

<artifactId>medipi-dom</artifactId>

<packaging>pom</packaging>

<modules>

<module>core-dom</module>

<module>health-dom</module>

<module>datacq-dom</module>

</modules>

<repositories>

<!-- OJDBC -->

<repository>

<id>novamens</id>

<url>http://maven.novamens.com</url>

</repository>

</repositories>

Page 95: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

95

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

95

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>com.mysema.maven</groupId>

<artifactId>apt-maven-plugin</artifactId>

<version>1.1.3</version>

</plugin>

</plugins>

</pluginManagement>

<plugins>

<plugin>

<groupId>com.mysema.maven</groupId>

<artifactId>apt-maven-plugin</artifactId>

<executions>

<execution>

<goals>

<goal>process</goal>

</goals>

<configuration>

<outputDirectory>target/generated-sources/java</outputDirectory>

<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>

</configuration>

</execution>

</executions>

</plugin>

</plugins>

</build>

<dependencies>

<!-- Base de datos -->

<dependency>

<groupId>com.oracle</groupId>

<artifactId>ojdbc6</artifactId>

<version>11.2.0.4.0</version>

</dependency>

<!-- Hibernate -->

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<version>5.1.0.Final</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-entitymanager</artifactId>

<version>5.1.0.Final</version>

</dependency>

<!-- EHCache -->

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-ehcache</artifactId>

<version>5.1.0.Final</version>

</dependency>

<!-- Query DSL -->

<dependency>

<groupId>com.querydsl</groupId>

<artifactId>querydsl-jpa</artifactId>

<version>4.1.0</version>

</dependency>

<dependency>

<groupId>com.querydsl</groupId>

<artifactId>querydsl-apt</artifactId>

<version>4.1.0</version>

<scope>provided</scope>

</dependency>

</dependencies>

</project>

Page 96: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

96

96

En las líneas superiores se encuentra el fichero pom.xml. Un primer vistazo nos indica que se trata de un proyecto

hijo de medipi-suite, pero a la vez padre de los proyectos dom (core-dom, health-dom y datacq-dom). Por tanto,

estos tres módulos heredarán tanto la configuración aquí indicada como la especificada en el pom superior.

Como hemos visto anteriormente, podemos indicar en un pom.xml las dependencias de nuestro proyecto

especificando grupo, id y versión. Con esta información Maven buscará primero en su repositorio local. Si no

encuentra el archivo buscado irá al repositorio central [67] para descargar el jar correspondiente al repositorio

local. Si, por cualquier razón, necesitamos utilizar librerías que no se encuentran en el repositorio central de

maven es posible especificar otros repositorios auxiliares, tal y como se ha hecho en el presente pom.

En el presente proyecto se trabaja con JPA, usando Hibernate como implementación de dicho estándar. Junto a

este se ha optado por EhCache como herramienta de gestión de una caché de consultas integrable con

JPA/Hibernate. Además, se empleará QueryDSL para la consulta a base de datos, dada su gran versatilidad.

Todo lo anterior será empleado por las aplicaciones Java correspondientes para acceder a la base de datos Oracle

empleada. Observamos que las herramientas comentadas coinciden con las dependencias de todos los proyectos

dom, quedando todavía solo un punto por explicar: la presencia del plugin apt-maven-plugin. Para entender su

utilidad conviene refrescar la memoria: en el capítulo dedicado a las tecnologías se comentó que QueryDSL se

sustenta en unos archivos denominados QClass. Una QClass (Query Class) es una clase Java que se sustenta

sobre una entidad de JPA, ofreciendo al framework QueryDSL una serie de funcionalidades para manejar las

consultas que se deseen realizan sobre dicha tabla / entidad. El plugin ANT de maven, configurado tal como se

indica arriba, permite generar automáticamente las QClass de todas las entidades de nuestro modelo de datos.

Durante el proceso de compilación / construcción, Maven buscará las clases del proyecto que contienen etiquetas

JPA y generará una QClass para cada una de ellas en el directorio destino correspondiente. Es importante

entender que todos los proyectos que contengan clases JPA deberán tener dicho plugin si queremos que se

generen automáticamente las QClass. Ubicar el plugin en este pom padre nos permite automatizar aún más esta

tarea, evitando tener que copiar y pegar esta configuración en todo proyecto dom de la suite.

5.5.3.1 CORE-DOM

5.5.3.1.1 Funcionalidad de la libreria

El proyecto core-dom presenta la arquitectura básica de comunicación con la base de datos común de la suite de

MEDIPi. Todo proyecto JPA requiere de la definición de las entidades (que, grosso modo, mapean las tablas de

la base de datos), la configuración/creación de la conexión a la base de datos y la gestión de las transacciones.

A todo esto, le sumaremos la gestión de las diferentes cachés y la utilización del framework QueryDSL. A la

hora de configurar todos estos parámetros, se han tomado una serie de decisiones de diseño que generan una

metodología de trabajo propia: todas las aplicaciones deberán emplearla, de forma que se unifiquen criterios y

no se produzcan diferencias en las capas básicas sobre las que se construyen los módulos. Para escenificar esto

se ha desarrollado la librería core-dom, donde se agrupa toda la funcionalidad comentada.

Figura 5-22. Proyecto core-dom

Page 97: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

97

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

97

5.5.3.1.2 Configuracio n de proyecto Maven

Como todo proyecto de MEDIPi, emplearemos Maven para la gestión de la compilación y construcción del

proyecto. En este caso se trata de uno de los proyectos más sencillos, pues no cuenta con ninguna especificidad

sobre el proyecto padre medipi-dom, por lo que nos bastará con especificar la dependencia con el pom padre e

indicar los parámetros básicos de definición del proyecto.

<?xml version="1.0"?>

<project

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd"

xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-dom</artifactId>

<version>1.0</version>

</parent>

<artifactId>core-dom</artifactId>

<packaging>jar</packaging>

<name>core-db</name>

</project>

5.5.3.1.3 Co digo Java

Vamos a estructurar el código desarrollado en core-dom en cuatro grandes bloques según su funcionalidad:

modelo de entidades JPA, gestión de la conexión con base de datos, comunicación con la misma y utilidades.

5.5.3.1.3.1 DOM Base

Ya se ha comentado en varias ocasiones que usar JPA (Java Persistence Api) implica un enfoque orientado a

objetos, de forma que las tablas de base de datos se mapean en objetos Java denominados entidades. Esto ofrece

una versatilidad mayor de la planteada en un primer punto: podemos utilizar muchos de los elementos de diseño

de la programación orientada a objetos en estas clases: abstracción, herencia, polimorfismo, etc. En nuestro caos

hemos definido un modelo de datos en el que todas las tablas tienen un conjunto de columnas o atributos

comunes.

CAMPO TIPO DEFAULT COMENTARIO

DELETED NUMBER(1,0) 0 Indicador de borrado lógico. 1 borrado / 0 no borrado

INSERT_DATE TIMESTAMP(6) SYSDATE Fecha de creación del registro

UPDATE_DATE TIMESTAMP(6) Fecha de última modificación del registro

VERSION NUMBER(38,0) 0 Versión del registro

Toda tabla de MEDIPi tiene los atributos arriba definidos. Si realizamos una traducción de lo anterior a

programación orientada a objetos, puede decirse que los atributos deleted, insert_date, update_date y version

son comunes a todo objeto que mapee una tabla de base de datos. Parecería lógica crear una clase abstracta que

definiera dichos atributos, de forma que los distintos objetos la extendieran, ahorrando al desarrollador repetirlos.

Esta es precisamente una muestra de la utilidad del enfoque ORM que se ha decidido emplear.

Page 98: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

98

98

@MappedSuperclass

public abstract class MedipiAbstractEntity {

@Column(name = "DELETED", nullable = false)

private boolean deleted = false;

@Column(name = "INSERT_DATE", nullable = false, length = 6)

private Date insertDate = new Date();

@Column(name = "UPDATE_DATE", length = 6)

private Date updateDate;

@Version

@Column(name = "VERSION", nullable = false, precision = 38, scale = 0)

private Long version;

// getters y setters de los atributos …

}

Mediante la etiqueta @MappedSuperclass indicamos a JPA que la clase solamente contiene un conjunto de

mapeos entre columnas de base de datos y atributos que se aplicarán a todas las clases que la hereden, sin

constituir una entidad en sí misma.

La etiqueta @Column permite indicar la correspondencia del atributo con una determinada columna de base de

datos, así como especificar otras opciones (nullable o no, precisión, escala, unicidad, etc.). Incluso se puede

realizar una definición de la columna mediante la opción ColumnDefinition empleando las instrucciones de

definición de columnas de SQL. Por su parte, la etiqueta @Version indica a JPA que ese campo se está utilizando

para indicar el número de versión del registro. El atributo asociado será manejado automáticamente por la

implementación de JPA, En nuestro caso, Hibernate lo inicializa en 0 y aumenta en uno su valor con cada

actualización sobre el registro.

Gracias al plugin de Maven configurado, siempre que se compile / construya el proyecto se genera la QClass

asociada a la entidad JPA MedipiAbstractEntity en el directorio target/generated-sources/java/paquete-de-la-

entidad. De esta parte solo nos interesa conocer qué son las QClass, como las generamos y cómo las utilizaremos

para realizar consultas. Por tanto, en este punto no hay necesidad de realizar un análisis detallado de las QClasses

generadas, más allá de observar que cada atributo de la entidad se transforma en otro atributo de un tipo análogo

en esta clase. Dichos tipos nos ofrecen, como se verá más adelante, un conjunto de métodos que nos ayudarán a

construir las consultas.

/**

* QMedipiAbstractEntity is a Querydsl query type for MedipiAbstractEntity

*/

@Generated("com.querydsl.codegen.SupertypeSerializer")

public class QMedipiAbstractEntity extends EntityPathBase<MedipiAbstractEntity> {

private static final long serialVersionUID = -925350210L;

public static final QMedipiAbstractEntity medipiAbstractEntity = new

QMedipiAbstractEntity("medipiAbstractEntity");

public final BooleanPath deleted = createBoolean("deleted");

public final DateTimePath<java.util.Date> insertDate =

createDateTime("insertDate", java.util.Date.class);

public final DateTimePath<java.util.Date> updateDate =

createDateTime("updateDate", java.util.Date.class);

public final NumberPath<Long> version = createNumber("version", Long.class);

public QMedipiAbstractEntity(String variable) {

Page 99: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

99

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

99

super(MedipiAbstractEntity.class, forVariable(variable));

}

public QMedipiAbstractEntity(Path<? extends MedipiAbstractEntity> path) {

super(path.getType(), path.getMetadata());

}

public QMedipiAbstractEntity(PathMetadata metadata) {

super(MedipiAbstractEntity.class, metadata);

}

}

5.5.3.1.3.2 DBManager

El trabajo con JPA se sustenta en el objeto EntityManager, que contiene toda la información para crear

conexiones, manejar transiciones y otras funcionalidades de gestión de la base de datos. La creación y

configuración de este objeto, así como de otros puntos secundarios como la parametrización de la caché, se

ocupa esta sección del código de core-dom.

Para ello definimos una interfaz DBManager, con cuatro métodos básicos.

public interface DBManager {

/**

* Recupera el objeto EntityManager de JPA

*

* @return EntityManager

*/

EntityManager getEntityManager();

/**

* Libera el espacio reservado por la caché especificada

*

* @param cacheName

* Identificador de la caché

*/

void cleanCache(String cacheName);

/**

* Libera la conexión con la base de datos

*/

void shutdown();

/**

* Devuelve el identificador de la región en la que se ubica la caché

* de queries

*

* @return Identificador de la caché de queries

*/

String getQueryCacheRegion();

}

Cada aplicación manejará su propio DBManager, que implementará la interfaz anterior. Además, hay varia

lógica común a todas las aplicaciones que se centraliza en la siguiente clase abstracta.

public abstract class AbstractDBManager implements DBManager {

private EntityManagerFactory entityManagerFactory;

private CacheManager cacheManager;

private String queryCacheRegion;

public AbstractDBManager(String persistenceUnit, String queryCacheRegion) {

Page 100: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

100

100

entityManagerFactory =

Persistence.createEntityManagerFactory(persistenceUnit);

cacheManager = CacheManager.getInstance();

setQueryCacheRegion(queryCacheRegion);

}

public EntityManager getEntityManager() {

return entityManagerFactory.createEntityManager();

}

public void cleanCache(String cacheName) {

cacheManager.getCache(cacheName).removeAll();

}

public void shutdown() {

entityManagerFactory.close();

cacheManager.shutdown();

}

public String getQueryCacheRegion() {

return queryCacheRegion;

}

private void setQueryCacheRegion(String queryCacheRegion) {

this.queryCacheRegion = queryCacheRegion;

}

}

Se observa como se define un constructor al que indicar el identificador de la persistenceUnit y el de la región

de la región en la que se cachearán las consultas en base de datos. Con lo anterior se instancian los objetos

básicos: una factoría de EntityManager y un CacheManager, indicándole a este último cual es la región para

cachear las consultas. Junto al constructor observamos varios métodos básicos: obtención de un EntityManager,

limpieza de una caché indicada por el nombre de su región, cierre de la conexión con base de datos (y borrado

de las cachés), getters y setters de la región de caché para queries. La idea es centralizar todo el uso de los objetos

EntityManagerFactory y CacheManager en esta clase abstracta y en los DBManagers que extiendan de ella. Un

buen patrón de diseño implica separar funcionalidades: es altamente peligroso que se pueda alterar la conexión

a base de datos o jugar con las cachés en un punto cualquiera de una aplicación. Cada aplicación definirá su

DBManager heredando el abstract arriba definido, de forma que proporcione solo una serie de métodos al

exterior. En definitiva, solo en el DBManager se trabajará sobre los objetos básicos que gestionan la base de

datos, comportándose como una caja negra para el resto de la aplicación. La configuración de la base de datos

se lleva a cabo a través del fichero persistence.xml, mientras que parametrización de la caché la realiza

ehcache.xml. Como en este punto solo se han definido interfaces y abstract, no es necesaria la presencia de

ninguno de estos ficheros, los cuales comentaremos adecuadamente en cada una de las aplicaciones.

5.5.3.1.3.3 DAOs y Services

Aunque se ha comentado ya en capítulos previos, conviene recordar en qué consiste exactamente el objeto

EntityManager. Cada vez que queramos trabajar con la base de datos se creará un nuevo EntityManager, que se

encargará de llevar a cabo las acciones que sobre él se indiquen. Una vez finalizada la tarea para la que se creó,

el EntityManager se cierra. Si en el futuro se desean realizar más operaciones con la base de datos basta con

crear un nuevo EntityManager a través del método que proporciona el AbstractDBManager. Un objeto de tipo

EntityManager ofrece métodos básicos como persist, merge o remove que se corresponden con los clásicos

insert, update y delete. Sin embargo, una buena gestión de la comunicación con la base de datos implica mucho

más que llamar a esos métodos en el momento adecuado. Como mínimo se debe tener en cuenta la

transaccionalidad. En muchos casos será necesario realizar acciones múltiples sobre la base de datos, de forma

que deban ejecutarse atómicamente. Es decir, si se produjera algún error debería devolverse la base de datos al

estado previo. Surge el concepto de transaccionalidad: una transacción es una “sesión” en base de datos. Todas

las acciones ejecutadas para esa transacción forman una misma unidad de trabajo, de forma que o bien se

persisten en la base de datos conjuntamente o se rechazan todas. Un objeto EntityManager nos permite crear

transacciones, tal y como se observa en el siguiente fragmento de código.

Page 101: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

101

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

101

EntityTransaction tx = entityManager.getTransaction();

tx.begin();

try {

t.setDeleted(true);

t.setUpdateDate(new Date());

t = entityManager.merge(t);

tx.commit();

res = true;

} catch (Exception e) {

tx.rollback();

}

Toda acción realizada sobre un EntityManager tras el inicio de la transacción es gestionada temporalmente, y

solo es persistida en base de datos cuando se confirma (commit). Gracias a esta lógica, si se produce algún error

inesperado se pueden deshacer todos los cambios realizados en esta transacción (rollback), recuperando el estado

anterior de la base de datos.

Está claro que se debe seguir siempre una determinada estructura en el acceso a base de datos, por lo que

deberíamos controlar el acceso a la base de datos en la medida de lo posible, haciendo que pase siempre por una

determinada lógica común. Para ello se ha optado por emplear el patrón DAO [68] de acceso a la base de datos.

El patrón DAO es una opción de diseño para aplicaciones Java EE que ofrece un conjunto de normas para

permitir un acceso estructurado a la base de datos. Consiste en crear objetos de acceso a bases de datos – Data

Access Object (DAO) – quienes serán los encargados de trabajar con el framework de acceso a datos del sistema,

en nuestro caso JPA, para realizar las acciones indicadas. De esta manera, una vez más recurrimos a un patrón

de diseño que pretende modularizar la funcionalidad: un DAO se comporta también como una caja negra para

el resto de la aplicación, de tal forma que si se desea modificar alguna lógica relativa a la comunicación con base

de datos se hará solo en el DAO en vez de buscar por toda la aplicación en qué puntos se trabaja con la base de

datos y modificarlos uno a uno.

Figura 5-23. Patrón DAO en MEDIPi

En las aplicaciones de MEDIPi se ha optado por emplear el patrón DAO, con unas características propias:

- Un DAO está siempre asociado a una entidad de base de datos, de forma que un DAO solo contenga la

lógica relacionada con una tabla. Esto permite definir métodos comunes para todos los DAOs (insert,

update, delete, etc.) pero es menos útil cuando se pretenden operaciones algo más complejas. Por

ejemplo, si realizamos una consulta que implique varias tablas esta metodología de trabajo es menos

adecuada, pues habrá que ubicar la consulta en algún DAO. En nuestro caso ubicaremos la consulta en

el DAO que se considere más apropiado (en función del objeto a devolver o la tabla principal entre

todas las que intervienen).

- Los DAOs deben realizar operaciones casi exclusivamente de comunicación con la base de datos. La

lógica de gran complejidad debe ubicarse en capas superiores.

- El patrón de diseño DAO se complementa habitualmente con los servicios. Un servicio es una capa

Page 102: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

102

102

superior que realiza la lógica compleja, llamando a los DAOs que necesita para realizar las acciones

necesarias. En nuestro caso, estamos definiendo una arquitectura que permita a muchas aplicaciones

diferentes construirse sobre los elementos aquí definidos. Para facilitar esto no debemos llegar al

extremo de definir una única metodología de trabajo, algo que puede variar en función de las

necesidades de cada proyecto, solamente debemos cubrir la creación de una estructura común que

establezca una homogeneidad entre todos los módulos de la suite MEDIPi.

- Partiendo del punto anterior, se define como una buena política no emplear directamente los DAOs en

el código lógico, si no utilizar una capa más de abstracción. En el caso de las aplicaciones diseñadas se

ha optado por generar una clase, representada en el esquema superior como

“ApplicationConfigurationObject” y que se corresponde con “DDAConfiguration”,

“SaverConfiguration” o “ChartConfiguration” según la aplicación, que mantiene una instancia de cada

DAO empleado, ofreciendo al exterior métodos lógicos que llaman a los DAOs adecuados, Se tratan

de métodos normalmente estáticos que evitan tener que instanciar una clase en memoria cada vez que

se pretende usar la base de datos. Pueden verse como un servicio, comprendiendo que se trata de un

solo servicio por aplicación y que no realizan una lógica muy compleja, más allá de la llamada al DAO

correspondiente. Es importante destacar que se ha optado por este patrón porque permite centralizar el

acceso a los DAOs, controlar el acceso multi-hilo a los métodos y evitar instancias frecuentes de objetos

en memoria que se emplearán continuamente. En resumen, se ha considerado que esta metodología “de

servicio único” es la más adecuada para las aplicaciones diseñadas, pero no debe ser vista como una

parte “básica” de la estructura diseñada, ya que otros proyectos deben preparar su propia estructura

según sus necesidades. Parece evidente que crear servicios es una buena práctica, pero el diseño de los

mismos puede variar: uno centralizado como en el caso actual, uno para cada funcionalidad / petición,

etc.

Por tanto, en el proyecto core-dom se realiza la definición de la estructura común de los DAOs, creando para

ello una interfaz y una clase abstracta con la lógica común, como es habitual.

public interface DAO<T> {

EntityManager getEntityManager();

T insert(T t);

T update(T t);

boolean delete(T t);

}

public abstract class AbstractDAO<T extends MedipiAbstractEntity> implements DAO<T> {

private static final Logger LOG = Logger.getLogger(AbstractDAO.class);

private DBManager myDBManager;

public AbstractDAO(DBManager myDBManager) {

this.myDBManager = myDBManager;

}

public EntityManager getEntityManager() {

return myDBManager.getEntityManager();

}

public void cacheQuery(JPAQuery<?> query) {

query.setHint(DBConstants.ACTIVE_QUERY_CACHE, true);

query.setHint(DBConstants.ACTIVATE_QUERY_CACHE_REGION,

myDBManager.getQueryCacheRegion());

}

public T insert(T t) {

EntityManager entityManager = this.getEntityManager();

EntityTransaction tx = entityManager.getTransaction();

tx.begin();

try {

t.setInsertDate(new Date());

Page 103: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

103

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

103

entityManager.persist(t);

entityManager.flush();

entityManager.refresh(t);

tx.commit();

} catch (Exception e) {

try {

tx.rollback();

} finally {

LOG.error("Error inserting an object: " + e);

}

} finally {

entityManager.close();

}

return t;

}

...

}

Del fragmento de código anterior conviene resaltar tres puntos. En primer lugar, podemos ver cómo se manejan

las transacciones dentro de un DAO, de forma que cada método de un DAO supone una transacción con la base

de datos. Este es el diseño correcto. En segundo lugar, se ha creado un método que cachea una JPAQuery en la

caché correspondiente, de forma que todo DAO pueda usarla cuando lo considere conveniente. En último lugar,

comentar que se ha empleado el tipado genérico de Java para trabajar en este DAO base abstracto. Se define un

tipo genérico T con la única condición de extender de MedipiAbstractEntity, de tal forma que se puede trabajar

con los atributos comunes en el DAO abstracto. Si pretendemos crear un DAO para una clase concreta

realzaremos la siguiente declaración.

public class ConstantInfoDAO extends AbstractDAO<ConstantInfo>

De forma que los métodos del DAO accesibles a través de una instancia de ConstantInfoDAO deberán usar

entidades ConstantInfo.

5.5.3.1.3.4 Paquete Util

En este paquete se ubica simplemente una clase con todas las constantes empleadas en el presente proyecto. En

todos los proyectos desarrollados se ha seguido el mismo diseño: cada proyecto tiene una única clase en las que

se ubican todas las constantes empleadas. Se ha optado por esta solución porque suelen ser constantes bastante

genéricas, usables desde varios lugares de la aplicación, y además no hay una gran cantidad de ellas. Existen

varios patrones de diseño posibles, siendo el más habitual ubicar las constantes comunes en una clase general y

colocar las específicas como atributos de las clases que las utilicen. Al igual que ocurría con los servicios, se ha

optado por una metodología adecuada para la situación actual, no siendo necesario mantenerla a toda cosa.

public class DBConstants {

public static final String ACTIVE_QUERY_CACHE = "org.hibernate.cacheable";

public static final String ACTIVATE_QUERY_CACHE_REGION =

"org.hibernate.cacheRegion";

}

5.5.3.2 HEALTH-DOM

5.5.3.2.1 Funcionalidad de la libreria

En health-dom definimos las entidades JPA asociadas al esquema HEALTH de base de datos. Se ha optado por

separar esta librería del proyecto core-dom para que siempre exista una librería por cada esquema, que contenga

exclusivamente el mapeo de dicho esquema, las QClasses y las constantes relacionadas con ellas. Además, se

Page 104: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

104

104

abre la posibilidad de que se amplíe el modelo de datos y se considere que HEALTH no debe ser el esquema

básico, sino que es posible que depende de otro esquema más general. En ese caso, gracias a esta separación,

basta con cambiar las dependencias en el pom y no hay necesidad de tocar código.

Figura 5-24. Proyecto health-dom

5.5.3.2.2 Configuracio n de proyecto Maven

El fichero pom.xml de health-dom es extremadamente simple, similar al del core-dom. Además de indicar el

pom padre y definir el id del proyecto se establece la dependencia con core-dom.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-dom</artifactId>

<version>1.0</version>

</parent>

<artifactId>health-dom</artifactId>

<packaging>jar</packaging>

<name>health-dom</name>

<dependencies>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-dom</artifactId>

<version>${project.version}</version>

</dependency>

</dependencies>

5.5.3.2.3 Co digo Java

La práctica totalidad del proyecto consiste en el mapeo de las tablas del esquema HEALTH. Comencemos con

la primera tabla mapeada, a modo de ejemplo.

@Entity

@Table(name = "PATIENT", schema = "HEALTH")

public class Patient extends MedipiAbstractEntity {

public Patient() {

}

public Patient(Long patientId, String pid, String dni, String name, String

surname1, String surname2, PersonSex sex) {

Page 105: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

105

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

105

this.patientId = patientId;

this.pid = pid;

this.dni = dni;

this.name = name;

this.surname1 = surname1;

this.surname2 = surname2;

this.sex = sex;

}

@Id

@Column(name = "PATIENT_ID", unique = true, nullable = false, precision = 5,

scale = 0)

@SequenceGenerator(name = "HEALTH.PATIENT_ID_SEQ", sequenceName =

"HEALTH.PATIENT_ID_SEQ", allocationSize = 1)

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator =

"HEALTH.PATIENT_ID_SEQ")

private Long patientId;

@Column(name = "PID", unique = true, nullable = false, length = 32)

private String pid;

@Column(name = "DNI", unique = true, nullable = false, length = 32)

private String dni;

@Column(name = "NAME", length = 32)

private String name;

@Column(name = "SURNAME1", length = 32)

private String surname1;

@Column(name = "SURNAME2", length = 32)

private String surname2;

@Enumerated(EnumType.ORDINAL)

@Column(name = "SEX", nullable = false, precision = 1, scale = 0)

private PersonSex sex;

// getters y setters

}

Se emplea la etiqueta @Entity para indicar que se trata de una entidad / tabla JPA. Para especificar qué tabla y

esquema se emplea @Table. Esto ocurre porque puede haber entidades que no se correspondan con una tabla

en base de datos. Por ejemplo, una vista es también una entidad. Incluso es posible que esa vista no tenga ninguna

correspondencia con base de datos, si no que sea una entidad interna utilizada por algún motivo concreto, aunque

no sea el caso más habitual.

La clave primaria de una entidad se marca con @Id. Todas las claves simples de nuestro modelo de datos

emplean una secuencia, que puede mapearse directamente en JPA con las etiquetas @SequenceGenerator y

@GeneratedValue. De esta manera, JPA/Hibernate se encarga de avanzar consecuentemente la secuencia

cuando se inserta un registro. Con @SequenceGenerator estamos creando el manejador de la secuencia para

JPA: le damos un id, le indicamos la secuencia de base de datos con la que se corresponde y el aumento que

debe realizar cada vez. Por su parte, con @GeneratedValue es donde estamos indicando el valor para ese

atributo. Podemos indicar valores autogenerados de tipo identidad, tabla y secuencia, informando además del id

del generador de secuencia creado anteriormente.

El resto de columnas nos mapeos de JPA, similares a los vistos en MedipiAbstractEntity, salvo el caso del

atributo sex. En ese caso se está indicando un mapeo con un enumerado de Java. Cuando eso ocurre basta con

indicar en la etiqueta @Enumareted si va a ser de tipo numérico o texto. En el primer caso el valor numérico en

base de datos (0, 1, 2...) se mapea con el valor que corresponde a su posición en el enumerado. En caso de tipo

ordinal (numérico) se busca una correspondencia entre el texto almacenado en base de datos y el indicado en el

enumerado. La utilización de enumerados puede ser bastante útil, permite transformar números en base de datos

en objetos con entidad y significado propio.

Page 106: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

106

106

@ManyToOne(fetch = FetchType.EAGER)

@JoinColumn(referencedColumnName = "PATIENT_ID", name = "PATIENT_ID", nullable =

false)

private Patient patient;

En las líneas superiores observamos cómo se mapea la foreing key que hay en EPISODE hace PATIENT.

Gracias a JPA, no solo tenemos el PATIENT_ID que figura en el registro, si no que podemos acceder al objeto

Patient completo, algo tremendamente útil. Con @ManyToOne se especifica el tipo de relación entre las tablas,

en este caso un registro en EPISODE se corresponde con uno en PATIENT, pero un PATIENT puede tener

múltiples EPISODES. Además de esta etiqueta se pueden emplear otras según la cardinalidad de la relación:

@OneToOne, @OneToMany, @ManyToMany… En todas ellas se debe indicar si el FetchType es EAGER o

LAZY. Este atributo indica el tratamiento que debe hacer JPA/Hibernate de la relación. Si se indica EAGER el

objeto referenciado (en este caso Patient) se trae automáticamente con Episode, realizando JPA las consultas

que considere oportunas para poblar el objeto Patient. Sin embargo, si se indica LAZY el objeto no está

instanciado inicialmente, si no que hará falta llamar a su getter (getPatient() en el ejemplo) para que se lance la

consulta a base de datos y se forme el objeto. Ambos modos de trabajo tienen ventajas e inconvenientes. La

regla general empleada para este desarrollo es considerar EAGER aquellas relaciones que aportan sentido

funcional al objeto (como conocer el paciente de un episodio) y marcar como LAZY las que ofrecen información

opcional, aunque no es fácil establecer un criterio único.

@Entity

@Table(name = "CONSTANT", schema = "HEALTH")

@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region =

HealthConstants.CACHE_CONSTANT)

public class Constant extends MedipiAbstractEntity

Terminamos el detalle del desarrollo de health-dom comentando cómo se indica el cacheo de una tabla completa.

Para ello basta con emplear la etiqueta @Cache, en este caso de Hibernate. La configuración es bastante sencilla:

se indica la región correspondiente y la estrategia de concurrencia [69]. Las regiones se definen en el fichero

ehcache.xml en cada aplicación, tal y como veremos más adelante. Junto a un nombre o identificador de la

región se indicarán otros parámetros como tamaño, tiempo que se espera antes de borrar información antigua,

etc. En nuestro caso definimos aquí el nombre de la región, de forma que cada aplicación pueda diseñar la caché

según sus necesidades. Por otra parte, la estrategia puede ser:

- READ_ONLY: se usa cuando los datos no van a cambiar, por lo que solo se va a emplear en la consulta

de datos.

- READ_WRITE: se emplea cuando los datos necesitan ser actualizados, pero no se provee un

mecanismo de separación entre transacciones simultaneas. Por tanto, puede que las transacciones no

funcionen correctamente si hay muchas inserciones/actualizaciones a la vez, provocando “lecturas

fantasmas”, es decir, inconsistencias en la caché.

- NONSTRICT_READ_WRITE: similar a la anterior, solo que realiza un mayor control de la

transaccionalidad.

- TRANSACTIONAL: caché totalmente transaccional. EhCache no la implementa.

Evidentemente, solo nos interesará una caché READ_ONLY, pues la información que se va a escribir no se

deseará cachear, ya que no se consultará con frecuencia.

Page 107: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

107

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

107

Conviene recordar que Hibernate mantiene una caché de primer nivel. Toda operación que se realiza sobre un

objeto EntityManager es cacheada y permanece en esta situación hasta que se elimina el objeto.

Junto al mapeo de las entidades el proyecto incluye las QClass autogeneradas y una clase HealthConstants en la

que solamente se indican las cachés diseñadas, para que otros proyectos puedan conocer el nombre de la región

y operar con ellas.

5.5.3.3 DATACQ-DOM

5.5.3.3.1 Funcionalidad de la librerí a

Este proyecto es el último de los dedicados a la base de datos. En él se lleva a cabo el mapeo de las tablas del

esquema DATA_ACQ.

Figura 5-25. Proyecto datacq-dom

5.5.3.3.2 Configuracio n de proyecto Maven

En el pom.xml definimos el proyecto Maven e indicamos la dependencia con health-dom, que a su vez incluirá

la librería core-dom.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-dom</artifactId>

<version>1.0</version>

</parent>

<artifactId>datacq-dom</artifactId>

<packaging>jar</packaging>

<name>datacq-dom</name>

<dependencies>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>health-dom</artifactId>

<version>${project.version}</version>

</dependency>

</dependencies>

Page 108: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

108

108

5.5.3.3.3 Co digo Java

El mapeo del esquema DATA_ACQ no es muy diferente al visto en el proyecto anterior. La única novedad con

respecto a lo ya comentado es remarcar que JPA nos permite crear atributos que no tienen una correspondencia

directa con ninguna columna de la tabla mapeada en base de datos. Veamos un ejemplo

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)

@JoinColumn(referencedColumnName = "MEDIPI_INSTANCE_ID", name = "MEDIPI_INSTANCE_ID",

nullable = false)

private MedipiInstance medipiInstance;

@OneToMany(orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "medipiInstance",

cascade = CascadeType.ALL)

private Set<Allocation> allocations;

El primer atributo pertenece al objeto Allocation, mientras que el segundo lo hace a MedipiInstance. Con las dos

instrucciones estamos mapeando una misma relación, vista desde cada extremo. Desde Allocation definimos

una relación ManyToOne a la instancia a la que está asignada, mapeando la columna de base de datos

MEDIPI_INSTANCE_ID con el objeto que representa dicha tabla. Sin embargo, en el otro extremo no estamos

realizando ninguna vinculación entre el atributo y la base de datos. En su lugar se hace referencia al atributo que

constituye el otro extremo de la relación. Esto nos ofrece muchas ventajas. Podemos realizar una búsqueda sobre

la tabla MedipiInstance y luego acceder a todas sus asignaciones en una lista simplemente llamando al getter del

atributo. Hibernate hará el resto. Conviene comentar el significado de algunas opciones empleadas. Con

OrphanRemoval indicamos que, si existen Allocations en base de datos que no se encuentra en el objeto Java,

estos deben eliminarse al persistir el objeto MedipiInstance. De esta manera podemos recuperar las asociaciones

de una instancia, borrar una por el motivo que sea, y persistir el registro. Automáticamente Hibernate borrará el

registro huérfano de la tabla Allocation. Otra novedad con respecto a lo comentado en el proyecto anterior es la

opción cascade. Esta opción indica qué acciones efectuadas sobre un objeto deben aplicarse también sobre el

objeto relacionado. Si marcamos REMOVE en la clase MedipiInstance sobre la lista de asignaciones estamos

pidiendo a la implementación de JPA que borre todos los registros asociados a una instancia cuando esta sea

eliminada. Parece evidente que estas acciones son tremendamente útiles para extrapolar acciones sobre objetos

padres a sus objetos hijos. JPA nos permite aplicarlas también a la inversa, algo que debe ejecutarse con cuidado.

En nuestro caso, se indica ALL en la relación padre-hijo (one to many) y REFRESH en la hijo – padre (many

to one). Esto implica que toda acción sobre un padre se propagará sobre los hijos, mientras que a la inversa solo

se propagará la acción REFRESH. REFRESH hace referencia a una llamada de JPA para recargar el objeto,

generalmente antes de operar sobre él, por lo que es importante que esta acción se propague para evitar

incoherencias.

Se puede realizar una última observación de las líneas de código superiores: nos encontramos ante otro ejemplo

de utilización del fetch, en este caso a la inversa del expuesto en health-dom. En este caso se considera que no

será poco habitual consultar una instancia a partir de una asignación, ya que no suele ser el flujo de trabajo

habitual. Además de eso, hay una cosa que conviene tener clara en el desarrollo de mapeos con JPA: no se

pueden generar ciclos: si en ambas relaciones se marca EAGER se produce un ciclo: Allocation se trae siempre

el objeto MedipiInstance, que a su vez se trae siempre en la consulta inicial los Allocations, que a su vez… JPA

conoce estos ciclos y es capaz de cortarlos, pero no su presencia son una práctica totalmente desaconsejada.

5.5.4 MEDIPI-CLUSTER

Medipi-Cluster es un proyecto Maven diseñado para agrupar los elementos comunes en la compilación y

construcción de los proyectos java del área Cluster. Actualmente solo existe uno, core-cluster, pero dado que a

Page 109: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

109

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

109

lo largo del diseño se ha hecho especial hincapié en diseñar una arquitectura software robusta que permita

fácilmente su ampliación se ha optado por crear un proyecto agrupador, de manera análoga a lo establecido en

medipi-dom y medipi-app.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-suite</artifactId>

<version>1.0</version>

</parent>

<artifactId>medipi-Cluster</artifactId>

<packaging>pom</packaging>

<modules>

<module>core-Cluster</module>

</modules>

<dependencies>

<!-- Kafka -->

<dependency>

<groupId>org.apache.kafka</groupId>

<artifactId>kafka-clients</artifactId>

<version>0.9.0.1</version>

</dependency>

<!-- JSON -->

<dependency>

<groupId>com.google.code.gson</groupId>

<artifactId>gson</artifactId>

<version>2.6.2</version>

</dependency>

</dependencies>

En esta ocasión no tenemos necesidad de aplicar ninguna lógica especial durante la fase de compilación del

productor, por lo que este pom no contiene más de los aspectos básicos habituales: definición del proyecto,

referencia a su pom padre, referencia a sus proyectos hijos y definición de las dependencias que todos ellos

deberán incluir.

5.5.4.1 CORE-CLUSTER

5.5.4.1.1 Funcionalidad de la librerí a

En el proyecto core-Cluster se ubica la parte del desarrollo que abarca la comunicación con el clúster de Kafka,

lo que incluye: definición de los objetos de transferencia de datos (Data Transfer Object, DTO) empleados,

configuración e implementación de los consumidores y productores de datos para dicho sistema de intercambio

de información. Al igual que ocurre en otros aspectos de la suite, la gran utilidad que proporciona core-Cluster

es el manejo de consumers y producers de Kafka, de tal forma que ofrece a las aplicaciones que así lo deseen un

conjunto reducido de métodos a emplear para que se produzca esta comunicación, sin tener que entrar en detalle

de la lógica existente bajo ellos.

Page 110: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

110

110

Figura 5-26. Proyecto core-Cluster

5.5.4.1.2 Configuracio n de proyecto Maven

Al tratarse del único hijo del proyecto maven medipi-Cluster toda la configuración especial y las dependencias

se vuelcan en el pom padre, dejando para el proye8cto core-Cluster poco más que los campos obligatorios.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-Cluster</artifactId>

<version>1.0</version>

</parent>

<artifactId>core-Cluster</artifactId>

<packaging>jar</packaging>

<name>core-Cluster</name>

5.5.4.1.3 Co digo Java

5.5.4.1.3.1 DTO – Data Transfer Objects

En el apartado 5.4.3. DTOs se definió los objetos que servirán como base para la información intercambiada a

través del clúster Kafka. Cada uno de ellos se corresponde con un objeto Java, ubicado en este proyecto.

public class LFConstantInfo {

public LFConstantInfo() {

}

public LFConstantInfo(Long constantId, Long episodeId, Date constantDate,

String value, Boolean manual) {

this.constantId = constantId;

this.episodeId = episodeId;

this.constantDate = constantDate;

this.value = value;

this.manual = manual;

}

private Long constantId;

private Long episodeId;

private Date constantDate;

private String value;

private Boolean manual;

// getters y setters

}

Page 111: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

111

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

111

5.5.4.1.3.2 Producer Kafka

Instanciar un producer Kafka desde Java no es especialmente complicado, como ya se viró en el apartado 4.4.5.

Producers. Aun así, se ha querido centralizar lo máximo posible el código para evitar redundancias, de forma

que sea lo más modular posible. Al crear un MedipiProducer con una interfaz propia evitamos que los

desarrolladores de las aplicaciones tengan q tener conocimiento alguno de Kafka. Además, Kafka es una

tecnología en plena fase de desarrollo, no en vano todavía ni siquiera cuenta con una versión 1.0. Hemos

observado cómo se han producido algunos cambios importantes al avanzar de versiones, algunos estructurales,

otros de parametrización, que refuerzan la opción escogida. Con esta modularización solo hará falta aplicar los

cambios que impliquen nuevas versiones de Kafka en un único proyecto, de forma que estas transformaciones

sean totalmente transparentes a otros proyectos.

Se ha optado por generar dos clases producers MedipiLFProducer y MedipiHFProducer. Ambos extienden del

AbstractMedipiProducer, en el que se encuentra la mayoría de la lógica. En ambos casos su utilización es tan

sencilla como la expuesta en las líneas inferiores.

Properties props = new Properties();

props.put(KafkaConstants.PROP_SERVER_LIST,PropertiesReader.getProperty(KafkaConstants.

VALUE_SERVER_LIST));

. . .

MedipiLFProducer producerLF = new MedipiLFProducer();

producerLF.initialize(props);

producerLF.sendLFConstantInfo(info);

Con cuatro instrucciones básicas se puede mandar información al clúster. Es interesante remarcar que se ha

optado por crear dos producers, uno para cada topic, cuando esto no es necesario: un producer puede enviar

información a tantos topics como quiera. Los motivos de este cambio son dos: facilitar las labores al

desarrollador y ofrecer una interfaz coherente para el uso de Kafka. Como vamos a emplear dos consumers, uno

subscrito a cada topic, es más coherente ofrecer dos producers a los desarrolladores.

A continuación, se indica el código de las clases desarrolladas, en la línea del especificado en capítulos

anteriores.

public class AbstractMedipiProducer {

private Producer<Long, String> producer;

public void initialize(Properties props) {

producer = new KafkaProducer<Long, String>(props);

}

protected void sendKafkaMessage(String message, String topic) {

new ProducerThread(producer, new ProducerRecord<Long, String>(topic,

message)).start();

}

private class ProducerThread extends Thread {

private Producer<Long, String> producer;

private ProducerRecord<Long, String> producerRecord;

public ProducerThread(Producer<Long, String> producer,

ProducerRecord<Long, String> producerRecord) {

this.producer = producer;

this.producerRecord = producerRecord;

}

public void run() {

this.producer.send(producerRecord);

}

}

Page 112: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

112

112

public void shutdown() {

producer.close();

}

}

public class MedipiLFProducer extends AbstractMedipiProducer {

public void sendLFConstantInfo(LFConstantInfo info) {

Gson gson = new Gson();

String msg = gson.toJson(info);

String topic = KafkaConstants.TOPIC_LF;

sendKafkaMessage(msg, topic);

}

}

5.5.4.1.3.3 Consumer Kafka

Instanciar un consumer de Kafka es algo más complicado que hacer lo propio con un producer. Como en el

apartado 4.4.6 Consumers ya se definieron las instrucciones básicas que se han de emplear para consumir

información del clúster Kafka, nos centraremos aquí en justificar las decisiones tomadas en pos de empaquetar

y personalizar la lógica necesaria para utilizar adecuadamente un consumer Kafka desde los proyectos de

MEDIPi.

Por coherencia, la estructura empleada es similar a la de los MedipiProducers: tendremos dos consumers, uno

para cada topic o canal del que queramos recibir información, de tal forma que ambos extienden de una clase

abstracta AbstractMedipiConsumer en la que se ubica la lógica común.

Properties props = new Properties();

props.put(KafkaConstants.PROP_SERVER_LIST,

. . .

MedipiLFConsumer consumerLF = new MedipiLFConsumer() {

@Override

public void receiveLFConstantInfo(LFConstantInfo info) {

receiveDataToAll(info);

}

};

consumerLF.initialize(props);

Se ha puesto especial hincapié en que la utilización de estos MedipiConsumers sea lo más sencilla posible. En

este caso observamos que basta con instanciar el objeto, indicarle la configuración mediante un fichero

Properties y sobrescribir el método en el que se maneja el DTO recibido. Es destacable que un desarrollador no

tiene q conocer el funcionamiento de un consumer, de Kafka y ni siquiera la utilización de JSON para la

transformación del DTO en el mensaje que va por el clúster. Todo eso es totalmente transparente para él.

public abstract class AbstractMedipiConsumer {

protected KafkaConsumer<Long, String> consumer;

protected ExecutorService executor;

protected boolean end = false;

public void initialize(Properties props) {

consumer = new KafkaConsumer<>(props);

executor = Executors.newCachedThreadPool();

}

public void shutdown() {

end = true;

executor.shutdown();

}

}

Page 113: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

113

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

113

public abstract class MedipiLFConsumer extends AbstractMedipiConsumer {

public void initialize(Properties props) {

super.initialize(props);

consumer.subscribe(Arrays.asList(KafkaConstants.TOPIC_LF));

startLFThread();

}

private void startLFThread() {

executor.execute(new Thread() {

public void run() {

while (!end) {

ConsumerRecords<Long, String> records =

consumer.poll(KafkaConstants.POLL_TS);

for (ConsumerRecord<Long, String> record : records) {

Gson gson = new Gson();

receiveLFConstantInfo(gson.fromJson(record.value(),

LFConstantInfo.class));

}

}

consumer.close();

}

});

}

public abstract void receiveLFConstantInfo(LFConstantInfo info);

}

Observamos que se arranca un hilo encargado solamente de leer del topic. Cuando se reciben datos se reconstruyen y se

llama al método que debe implementar el receptor.

5.5.4.1.3.4 Paquete Util

La presencia de un paquete .util es habitual en todos los proyectos de la suite y siempre incluye el mismo tipo

de código: una clase para almacenar todas las constantes empleadas a lo largo del proyecto.

5.5.5 MEDIPI-APP

Tal y como se ha realizado para las otras categorías, se ha decidido crear un proyecto maven que permita agrupar

las aplicaciones de MEDIPi y sus librerías comunes, centralizando dependencias y configuraciones comunes.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-suite</artifactId>

<version>1.0</version>

</parent>

<artifactId>medipi-app</artifactId>

<packaging>pom</packaging>

<modules>

<module>core-app</module>

<module>dda</module>

<module>saver</module>

<module>chart</module>

</modules>

<build>

<pluginManagement>

<plugins>

Page 114: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

114

114

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-jar-plugin</artifactId>

<version>2.6</version>

</plugin>

</plugins>

</pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-jar-plugin</artifactId>

<executions>

<execution>

<goals>

<goal>test-jar</goal>

</goals>

</execution>

</executions>

</plugin>

</plugins>

<filters>

<filter>src/main/filters/conf-${environment}.properties</filter>

</filters>

<resources>

<resource>

<directory>src/main/resources</directory>

<filtering>true</filtering>

</resource>

</resources>

</build>

<profiles>

<profile>

<id>development</id>

<activation>

<activeByDefault>true</activeByDefault>

</activation>

<properties>

<environment>development</environment>

</properties>

</profile>

<profile>

<id>final</id>

<properties>

<environment>final</environment>

</properties>

</profile>

</profiles>

En las líneas superiores tenemos el contenido principal del fichero pom.xml en el que se define este proyecto

maven como un módulo de medipi-suite y padre, a su vez, de cuatro proyectos: dda, saver, chart y core-app.

La sección build de un pom.xml se emplear para informar de un conjunto de configuraciones o

parametrizaciones comunes a emplear durante la compilación del proyecto. En este caso, se está indicando el so

un nuevo plugin de maven a todos los proyectos hijos de medipi-app: maven-plugin-jar. Este plugin no hace

más que empaquetar en un fichero .jar las clases java compiladas. Cuando un proyecto se define como de tipo

jar Maven automáticamente llama a este plugin tras las fases iniciales, generando un jar. Sin embargo, puede

resultar de interés llamar al plugin en otros momentos. Tal y como vimos en el capítulo teórico de Maven, el

ciclo de trabajo de la herramienta pasa por la compilación y ejecución de las clases de pruebas (que por

convención se ubican, salvo modificación explícita, en src/test/…) pero no las empaqueta en un jar. Es aquí

donde entra la configuración realizada: en el pom estamos indicando a Maven que llame al plugin jar en la fase

de test-jar, provocando que se genere un fichero jar con todos los tests. Se pretende con esto que todas las

aplicaciones de MEDIPi tengan un catálogo de pruebas asociadas que puedan ser ejecutadas mediante la

invocación adecuada de este jar.

Page 115: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

115

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

115

El siguiente punto son los filtros y los perfiles, que comentaremos conjuntamente. Para entender el trabajo

realizado vamos a comenzar comentando cada funcionalidad empleada de manera independiente.

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>health-dom</artifactId>

<version>${project.version}</version>

</dependency>

En las líneas superiores, correspondientes al pom.xml de datacq-dom, se está indicando que el proyecto health-

dom debe incorporarse como librería externa el proyecto actual para su correcto funcionamiento. Sin embargo,

no se está definiendo explícitamente el proyecto, si no que se están empleando “variables” que Maven es capaz

de entender y traducir. Cuando se indica ${project.groupId} Maven reconoce la sintaxis ${} y busca el valor

con el que se corresponde project.groupId. En este caso se trata de una variable propia de Maven, que hace

referencia al groupId del pom.xml del proyecto, pero es perfectamente posible definir nuevas “variables”, de

forma que puedan usarse no solo en el pom.xml, sino también en otros puntos del desarrollo. Para ello se emplea

la sección properties. A continuación, tenemos un ejemplo en el que definimos dos variables: Cluster (de valor

Kafka) y hardware (de valor Raspberry).

<properties>

<Cluster>Kafka</Cluster>

<hardware>Raspberry</hardware>

</properties>

Podemos definir un filtro indicando, con las etiquetas adecuadas en el pom.xml, el fichero de texto en el que se

ubican las variables que se quieren declarar y sus valores. Gracias a esto Maven las reconocerá y permitirá

realizar la traducción en el pom.xml siempre y cuando se utilicen las variables con la sintaxis adecuada. El

siguiente paso es no “traducir” solo en el pom.xml, si no tener la capacidad de utilizar estas variables en el resto

de recursos del proyecto. Para ello se activa la propiedad filtering a true en la sección resources.

Otra funcionalidad de maven empleada en este proyecto son los perfiles. Mediante la etiqueta profiles podemos

generar un catálogo de perfiles, identificados unívocamente por un id, que contienen cada uno una configuración

determinada. Por tanto, los perfiles nos permiten personalizar aún más la construcción del proyecto. Por ejemplo,

podemos crear un perfil denominado Pruebas y ubicar en él la configuración del plugin maven-jar-plugin que se

ha comentado. Cuando llevamos a cabo alguna fase de Maven es necesario indicar el perfil, excepto cuando solo

hay un perfil o alguno de ellos está marcado como activo por defecto.

Por último, los ficheros .properties son un tipo de recursos ampliamente usados en Java como método de

definición de variables o de parámetros de configuración, y tienen la siguiente estructura.

log_path = /opt/medipi/logs/

log_filename = dda.log

db_connection_ip = localhost

...

Todo lo anterior se va a combinar para formar un mecanismo de parametrización de las aplicaciones. No toda la

parametrización de una aplicación debe estar en base de datos, al contrario, solo tiene sentido que esté en base

de datos aquella que se pretenda modificar durante la ejecución del software. Para definir una serie de variables

u opciones de configuración que no se esperan que cambien es más adecuado utilizar los ficheros .properties.

El flujo de trabajo es el siguiente: al ejecutar el software desde el IDE de desarrollo o al generar el jar compilado

se debe especificar uno de los dos perfiles posibles: development o final. Si no se indica ninguno se toma

development como perfil seleccionado, al ser el valor por defecto. El perfil seleccionado da el valor

Page 116: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

116

116

correspondiente a la variable environmet. Observamos dónde se está usando esa variable: en la definición del

fichero que usaremos de filtro. Es decir, en el proyecto deben existir dos archivos filtros ubicados en

src/main/filters: conf-development.properties y conf-final.properties. Elegir un perfil u otro está repercutiendo

en elegir entre un filtro u otro. En dicho filtro definimos una serie de valores, como se ve en el siguiente ejemplo.

log_path_value = D:/MEDIPI/logs/

log_filename_value=chart.log

Los dos filtros deben tener las mismas variables, aunque puedan tener diferente valor. Maven ahora reconoce

las variables log_path_value, log_filename_value, etc. de forma que será capaz de sustituir

${log_filename_value} por chart.log tanto en el pom.xml como en los recursos, gracias a que activamos dicha

opción. ¿Qué utilidad tiene esto? Queremos poder cambiar la ruta del log, pero no es una buena práctica realizar

un desarrollo en el que leamos de un fichero u otro según el perfil seleccionado, si no que debemos acceder

solamente a uno y que este properties vaya cambiando de valores en función del perfil actual. Para ello se ha

definido un archivo denominado configuration.properties. Su contenido tiene el siguiente aspecto.

log_path = ${log_path_value}

log_filename = ${log_filename_value}

Al ser un recurso, Maven lo interpreta y traduce las variables que en él encuentre, por lo que desde el punto de

vista del código Java se vería de la siguiente manera,

log_path = D:/MEDIPI/logs/

log_filename = chart.log

Independientemente de cual sea el perfil, la aplicación solo tiene que leer el valor almacenado en el fichero

configuration.properties. En resumen, el fichero configuration.properties hace uso de las variables creadas en el

filtro (con un valor diferente según el perfil indicado), ofreciendo una capa de abstracción al código.

Hay que tener claro que el fichero configuration.properties no define nuevas variables Maven, no es un filtro,

solo es un recurso que leerá la aplicación Java como considere oportuno. Además, no estamos filtrando solo este

fichero, estamos filtrando todos los resources, por lo que podremos hacer uso de las variables declaradas en los

filtros en otros ficheros, algo que se verá más adelante.

5.5.5.1 CORE-APP

5.5.5.1.1 Funcionalidad de la librerí a

Al trabajar con varias aplicaciones que comparten una arquitectura común y pretenden pertenecer a una misma

suite de proyectos, es lógico plantear la necesidad de unificar aquellos desarrollos que se consideran estructurales

o que sabemos a ciencia cierta que se deben abordar por más de una aplicación. Es esta la utilidad del Proyecto

core-app.

Page 117: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

117

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

117

Figura 5-27. Proyecto core-app

5.5.5.1.2 Configuracio n de proyecto Maven

Core-app queda definido como proyecto Maven mediante el sencillo pom.xml mostrado en las líneas posteriores.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-app</artifactId>

<version>1.0</version>

</parent>

<artifactId>core-app</artifactId>

<packaging>jar</packaging>

<name>core-app</name>

5.5.5.1.3 Co digo Java

5.5.5.1.3.1 Configuración del Log

Uno de los elementos comunes a todas las aplicaciones será la configuración del log. Mediante unas sencillas

instrucciones se carga el fichero de configuración de log y se inicia.

public class LogConfigurator {

public static void loadConfiguration(Class<?> initialClass) {

// Configure log4j

String log4jFile = AppConstants.LOG_CONF_FILE;

try {

Properties logProperties = new Properties();

logProperties.load(initialClass.getClassLoader().getResourceAsStre

am(log4jFile));

PropertyConfigurator.configure(logProperties);

} catch (Exception e) {

System.err.println("Error reading Log4j configuration file " +

log4jFile);

e.printStackTrace();

System.exit(1);

}

}

}

El único punto de interés en el desarrollo anterior es la ubicación del fichero de configuración del log, ya que

este método debe ser empleable por muchas aplicaciones a la vez. En la constante LOG_CONF_FILE se está

indicando, como su propio nombre indica, el fichero de configuración: log4j.properties. Sin embargo, ¿cómo

conocemos su ubicación? Para resolver esta pregunta deben tenerse en cuenta varios conceptos importantes.

Page 118: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

118

118

Figura 5-28. Estructura de un proyecto durante el desarrollo vs compilado

El método recibe la clase origen y recupera su ClassLoader. El Java Classloader (en español, cargador de clases

Java) es una parte del Java Runtime Environment que carga dinámicamente clases o recursos en la máquina

virtual, definiendo un recurso (resource) como un fichero de datos (imágenes, audio, texto, etc.) al que se puede

acceder desde el código java de una clase. El ClassLoader recuperado nos ofrece métodos para cargar recursos

como getResource() o getResourceAsStream(). Para ello debemos indicarle la ruta relativa desde el ClassLoader

(y no desde el class) hasta el fichero que se quiere leer. Un ClassLoader se ubica siempre en el classpath, en el

directorio base de nuestro proyecto. En la imagen superior, a la derecha, tenemos la estructura resultante de

compilar el proyecto Saver, donde observamos que el fichero log4j.properties está ubicado en el directorio base,

lugar desde donde arranca la ruta relativa del ClassLoader. Es por eso por lo que basta con indicar el nombre del

fichero. Si esta situación cambia, habrá que indicar las carpetas intermedias entre el directorio base y el fichero

a cargar. Solo queda por comprender una cosa: existe una evidente diferencia entre la estructura de carpetas de

la izquierda (durante el desarrollo) y la de la derecha (contenido del jar generado). Esto se debe a que la estructura

de carpetas src/main/java, src/test/java, src/main/resources, etc. son un conjunto de convenciones que establece

Maven para facilitar el desarrollo. Cuando se compila el proyecto la información contenida en

src/main/resources se mueve al directorio base, a no ser que se indique una configuración distinta en el pom.xml.

5.5.5.1.3.2 Properties

Toda aplicación de MEDIPi contará con un fichero denominado configuration.properties en el que los

desarrolladores ubicarán los parámetros de configuración que no vayan a ser modificados frecuentemente, El

proyecto core-app proporcionará una interfaz de acceso común a ese fichero; es decir, mantendrá una clase,

denominada PropertiesReader, con una serie de métodos que permitan acceder a los parámetros indicados en

ese fichero, de forma que se puedan usar sin necesidad de conocer la ubicación del mismo.

Se ha seguido este diseño por razones ya comentadas previamente: la clase PropertiesReader deberá ser

modificada si se realizan cambios estructurales como emplear más de un fichero de configuración, etc. Pero será

esta la única clase que deberá modificarse, no será necesario recorrer todo el desarrollo buscando dónde se leía

el fichero de configuración e ir haciendo las correcciones necesarias. Por tanto, se construye un modelo más

escalable que además es menos propenso a errores ante cualquier cambio o modificación.

En resumen, manejaremos una clase PropertiesReader encargada de leer el fichero configuration.properties.

Además, también se proporciona la capacidad de emplear un segundo fichero de configuración

(extra_configuration.properties). Este fichero se ubicará, en caso de existir, fuera del jar, permitiendo al

desarrollador sobrescribir los parámetros que considere necesarios.

Para llevar a cabo esta funcionalidad la clase mantendrá un atributo estático de tipo java.util.Properties. Este tipo

de objetos Java permiten interactuar con los ficheros .properties redactados en diversos formatos, entre ellos el

empleado para nuestros proyectos (nombre_parametro = valor_parametro).

Además, la clase contará con un bloque estático. Los bloques de código estáticos se ejecutan una sola vez, en la

primera llamada a cualquier método de la clase (incluyendo un constructor). Ahí se leerá del fichero de

Page 119: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

119

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

119

configuración, cargando su contenido en el objeto Properties. Para ilustrarlo se incluye a continuación una

versión reducida del código.

private static Properties props;

static {

if (props == null) {

try {

loadProperties();

loadExtraProperties();

} catch (IOException e) {

LOG.error("Error loading configuration properties", e);

System.exit(1);

}

}

}

private static void loadProperties() throws IOException {

props = new Properties();

try {

InputStream inputStream = PropertiesReader.class.getClassLoader()

.getResourceAsStream(AppConstants.PROP_FILE_NAME);

props.load(inputStream);

} catch (Exception e) {

throw new FileNotFoundException("Property file '" +

AppConstants.PROP_FILE_NAME + "' incorrect or not found in the

classpath");

}

}

private static void loadExtraProperties() throws IOException {

File file = new File(AppConstants.EXTRA_PROP_FILE_NAME);

if (file.exists()) {

InputStreamReader inputStream = new InputStreamReader(new

FileInputStream(file), Charset.forName("UTF-8"));

props.load(inputStream);

}

}

Simplemente, en la primera llamada a cualquier método de la clase se invoca a los métodos encargados de poblar

el objeto properties tanto con el fichero de configuración regular como con el fichero de configuración extra.

Existen pequeñas pero importantes diferencias entre ellos. En loadProperties() se reinicia siempre el objeto

Properties antes de cargar la parametrización. Posteriormente se genera un InputStream del fichero, siguiendo

el mismo método de acceso visto previamente para el log (algo lógico pues ambos ficheros se encontrarán en el

mismo directorio). Como se está empleando un formato “estándar” de java, basta con llamar al método load del

objeto Properties. Por su parte, en loadExtraProperties() no se reinicia el objeto properties, por lo que los

parámetros que se lean del fichero de configuración extra se añadirán o sobrescribirán. En esta ocasión si el

fichero no existe no se provoca ningún error. Además, la instrucción para recuperar el InputStream asociado es

totalmente diferente. La instrucción new FileInputStream utilizará como ruta el “working directory”; es decir,

el directorio del sistema de ficheros desde el cual se invocó a la instrucción java. Por tanto, para que se carguen

adecuadamente sus parámetros, el fichero extra_configuration.properties deberá colocarse en el mismo

directorio en el que se ejecute la llamada a Java.

Para terminar, PropertiesReader contará con un método que recupere el valor de un parámetro a través de su

nombre.

public static String getProperty(String name) {

String value = props.getProperty(name);

if (value == null) {

LOG.error("Error reading " + name + " property . Stopping JVM");

}

return value;

Page 120: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

120

120

}

5.5.5.1.3.3 Paquete Util

En la clase AppConstants se declaran todas las constantes utilizadas por este proyecto.

5.5.5.2 DDA

5.5.5.2.1 Funcionalidad de la aplicacio n DDA

DDA son las siglas de Device Data Acquisition, el módulo de MEDIPi encargado de establecer comunicación

con los biodispositivos, a partir de un conjunto de protocolos específicos mayoritariamente propietarios,

recuperar la información biomédica del paciente, adaptarla a un formato propio y enviarla al Cluster de MEDIPi

para que pueda ser consumida por otras aplicaciones de la suite.

Figura 5-29. Proyecto DDA

5.5.5.2.2 Configuracio n de proyecto Maven

DDA es un proyecto módulo de medipi-app, que además empleará core-app como dependencia para poder usar

toda la funcionalidad común implementada por la misma. Además, tal y como vimos al principio del presente

apartado dedicado al Software, debe incluir core-Cluster para gestionar la comunicación con el Cluster Kafka

de MEDIPi.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-app</artifactId>

<version>1.0</version>

</parent>

<artifactId>dda</artifactId>

<packaging>jar</packaging>

<name>dda</name>

<build>

<pluginManagement>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-assembly-plugin</artifactId>

<version>2.6</version>

</plugin>

</plugins>

</pluginManagement>

Page 121: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

121

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

121

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-assembly-plugin</artifactId>

<configuration>

<finalName>${project.groupId}-

${project.artifactId}</finalName>

<descriptors>

<descriptor>assembly.xml</descriptor>

</descriptors>

</configuration>

<executions>

<execution>

<id>make-assembly</id>

<phase>package</phase>

<goals>

<goal>single</goal>

</goals>

</execution>

</executions>

</plugin>

</plugins>

</build>

<dependencies>

<!-- Dependencias de MEDIPi -->

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>datacq-dom</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-Cluster</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-app</artifactId>

<version>${project.version}</version>

</dependency>

<!-- PROTOCOLOS -->

</dependencies>

En el pom.xml del proyecto se emplea un plugin de maven no usado hasta el momento: maven-assembly-plugin

asociado a la fase package de Maven. Este plugin construye una versión empaquetada de la solución de acuerdo

a una serie de reglas definidas en el archivo assembly.xml indicado. En este caso se pretende generar un fichero

.zip con los .jar necesarios para ejecutar DDA y los scripts de arranque (ubicados en src/main/resources), de

forma que sea más sencillo el despliegue y uso de la solución en el hardware de integración elegido.

<assembly

xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-

plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

<id>package</id>

<formats>

<format>zip</format>

</formats>

<fileSets>

<fileSet>

<directory>src/main/resources</directory>

<outputDirectory>/bin</outputDirectory>

<includes>

<include>*.sh</include>

Page 122: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

122

122

<include>*.bat</include>

</includes>

<lineEnding>unix</lineEnding>

</fileSet>

</fileSets>

<dependencySets>

<dependencySet>

<outputDirectory>/lib</outputDirectory>

</dependencySet>

</dependencySets>

</assembly>

El fichero comienza indicando un identificador único de la construcción configurada. Este id se añadirá al

nombre del proyecto (artifact-id) para dar lugar al nombre del archivo/s generado/s, en este caso dda-

package.zip. Su utilidad radica en que podemos tener varios ficheros de assembly (uno por construcción) de

forma que el id nos sirva para identificar la solución generada. Con la etiqueta formats se indica el formato o

formatos en los que se empaquetará la solución construida. Es decir, si quisiéramos generar un dda-

package.tar.gz bastaría con añadir este formato a la lista, sin necesidad de duplicar el assembly.

La sección fileSets sirve para parametrizar el tratamiento que se le va a realizar a uno o varios ficheros no Java

del proyecto. Para cada conjunto de ficheros con configuración común se debe declarar un fileSet. Para el

proyecto DDA es necesario que todos los ejecutables (aquellos ficheros .sh y .bat de la carpeta de resources de

Maven) se copien a una carpeta bin en el directorio raíz del zip. Es interesante destacar que se pueden realizar

varias configuraciones específicas sobre los ficheros tratados, como se observa en el assembly.xml cuando se ha

parametrizado que todos los ficheros tratados utilicen la codificación de fin de línea de unix.

Para terminar, se puede realizar un tratamiento parecido al visto con los ficheros no Java para las dependencias,

con dependencySets y dependecySet. En este caso basta con especificar que se quiere que todas las librerías

Java (incluyendo el jar correspondiente al presente proyecto) se ubiquen en un directorio determinado.

5.5.5.2.3 Co digo Java

DDA es, sin lugar a duda, la aplicación más compleja de las que componen la suite MEDIPi. Detallar sus

funcionalidades y las decisiones técnicas tomadas durante el desarrollo implicará tener primero una visión

general de todas las tareas implicadas.

A grandes rasgos, DDA cuenta con cuatro secciones o agrupaciones de funcionalidad diferenciadas:

- Configuración de las utilidades o elementos empleados: la base de datos, el log o el acceso a los

properties son elementos que se deben configurar, cada uno a su manera.

- ProtocolReader: cada instancia de DDA se identifica de forma unívoca. Mediante este identificador la

aplicación deberá ir a base de datos y conocer sus asignaciones actuales. Será necesario mantener un

conjunto de ProtocolReaders (implementaciones de protocolos), de acuerdo a las asignaciones actuales.

Todos los ProtocolReader emplearán una serie de convenciones que permitan estandarizar la

información recuperada.

- CommandListener: DDA arranca un servidor para atender a peticiones de actualización de

asignaciones, refresco de caché, etc. Por ejemplo, una aplicación externa informará al servidor de que

ha habido un cambio de dispositivo asignado. Gracias a esto DDA podrá llamar nuevamente al

ProtocolReaderManager para que compare los lectores actuales con los requeridos según las

asignaciones de la base de datos.

- DataSender: La información biomédica recuperada se envía a un DataSenderManager. Un DataSender

no es más que un conjunto de clases preparadas para recibir los datos y almacenarlas / enviarlas a un

lugar determinado. El clúster Kafka es el DataSender principal.

- Util: clase para métodos comunes

Page 123: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

123

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

123

Figura 5-30. Esquema de DDA

Para facilitar las secciones comentadas se ha diseñado el esquema previo, en el que se muestra un diagrama de

flujo de los paquetes / clases / métodos fundamentales del proyecto. De un primer vistazo es posible ubicar cada

agrupación de funcionalidad en el gráfico, además de obtener una idea aproximada de las conexiones a base de

datos y al Cluster.

5.5.5.2.3.1 Configuraciones

5.5.5.2.3.1.1 Log

Para configurar el log simplemente basta con ubicar el fichero log4j.properties en la carpeta de recursos del

proyecto y llamar a la utilidad de core-app comentada en su apartado correspondiente.

LogConfigurator.loadConfiguration(Main.class);

5.5.5.2.3.1.2 Properties

Esta función también está regulada por core-app, solo que no necesita que se llame a ningún método explícito

para arrancarla. Como se vio anteriormente, basta con llevar a cabo la lectura de un parámetro para que se hagan

las operaciones iniciales necesarias. DDA tiene, al igual que el resto de aplicaciones que usan core-app, los

properties configuration.properties, configuration-development.properties y configuration-final.properties

necesarios para que la lógica de core-app funcione.

5.5.5.2.3.1.3 Base de datos

El funcionamiento de la base de datos es ligeramente parecido al de los properties. Previamente se detalló el

patrón de diseño empleado en el acceso a base de datos (4.5.3.1.3 DBManager y 4.5.3.1.3 DAOs y Services).

Page 124: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

124

124

En resumen, los DAOs realizan las acciones sobre la base de datos (y tenemos un DAO por entidad), siendo

todas ellas accesibles a través de un objeto Service denominado DDAConfiguration.

public class AllocationDAO extends AbstractDAO<Allocation> {

public AllocationDAO(DBManager myDBManager) {

super(myDBManager);

}

private static final Logger LOG = Logger.getLogger(AllocationDAO.class);

private static AllocationDAO instance = new

AllocationDAO(DDADBManager.getInstance());

public static AllocationDAO getInstance() {

return instance;

}

@SuppressWarnings("unchecked")

public List<Allocation> getActualAllocationsByInstance(Long medipiInstanceId) {

List<Allocation> res = new ArrayList<Allocation>();

QAllocation qallo = QAllocation.allocation;

EntityManager em = getEntityManager();

try {

Date now = new Date();

JPAQuery<?> query = new JPAQuery<Allocation>(em);

query.from(qallo);

query.where(qallo.medipiInstance.medipiInstanceId.

eq(medipiInstanceId));

query.where(qallo.startDate.before(now));

query.where(qallo.endDate.after(now).or(qallo.endDate.isNull()));

query.where(qallo.deleted.isFalse());

res = (List<Allocation>) query.fetch();

} catch (Exception e) {

LOG.error("Error executing a query: " + e);

}

em.close();

return res;

}

}

Todos los DAOs tienen una estructura similar: cuentan con un atributo estático denominado instance que

devuelve un objeto de esta clase. Este patrón de diseño se denomina singleton (instancia única en inglés) y está

diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.

Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso

global a ella. Esta instancia se crea con el constructor definido, que llama al constructor del AbstractDAO. Dicho

constructor requiere que se le informe de una implementación de la instancia. En el caso actual se empleará

DDADBManager. Junto a los métodos ya comentados se encontrarán los creados específicamente para realizar

una acción concreta, generalmente una consulta.

En getActualAllocationsByInstance(Long medipiInstanceId) podemos observar un caso concreto de QueryDSL

para generar una consulta. Basta con instanciar un objeto JPAQuery, indicarle la entidad principal de la consulta

y especificar el EntityManager. Los objetos JPAQuery nos proporcionan un conjunto de métodos para simular

la sintaxis SQL (from, where, etc.). Para hacer referencia a las entidades debe usarse las QClass autogeneradas,

las cuales también cuentan con un conjunto de métodos que nos permiten la comparación con valores u otros

atributos. Gracias a todo esto podemos lanzar una consulta con una sintaxis muy parecido a SQL, que nos

proporcionará los resultados en los objetos JPA mapeados.

. . .

private static AllocationDAO allocationDAO = AllocationDAO.getInstance();

. . .

Page 125: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

125

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

125

public static synchronized List<Allocation> getActualAllocations() {

List<Allocation> res = new ArrayList<Allocation>();

try {

MedipiInstance myInstance = getMyInstance();

res = allocationDAO.getActualAllocationsByInstance

(myInstance.getMedipiInstanceId());

} catch (Exception e) {

LOG.error("Allocation for this instance can not be found", e);

}

return res;

}

El objeto DDAConfiguration simplemente se encarga de gestionar el singleton de cada DAO empleado,

ofreciendo a las clases un acceso común a través de sus métodos estáticos y sincronizados.

public class DDADBManager extends AbstractDBManager {

public DDADBManager(String persistenceUnit, String queryCacheRegion) {

super(persistenceUnit, queryCacheRegion);

}

private static DDADBManager instance = new

DDADBManager(DDAConstants.PERSISTENCE_UNIT,

DDAConstants.QUERY_CACHE_REGION);

public static DDADBManager getInstance() {

return instance;

}

public static void cleanProtocolConstantMapCache() {

instance.cleanCache(DataAcqConstants.CACHE_PROTOCOL_CONSTANT_MAP);

}

public static void cleanConstantCache() {

instance.cleanCache(HealthConstants.CACHE_CONSTANT);

}

public static void cleanQueryCache() {

instance.cleanCache(instance.getQueryCacheRegion());

}

}

En la clase de gestión de base de datos también se emplea el patrón singleton. Hasta ahora no se ha comentado

en qué punto de la aplicación se llama al constructor de DDADBManager, provocando que se inicialice la

comunicación con la base de datos. Al generarse estáticamente una instancia de esta clase se está llamando al

constructor del AbstractDBManager, especificando el persistenceUnit y la queryCacheRegion de este proyecto,

quien creará los objetos de gestión de base de datos y caché adecuados, tal y como se comentó adecuadamente

en su apartado correspondiente. Por tanto, cuando se realice la primera llamada a un método (estático) de

DDADBManager (como, por ejemplo, getInstance()) automáticamente se crea la instancia, llamando al

constructor del abstract e inicializando la conexión correctamente. La creación de todos los DAOs necesita

recibir una instancia de un objeto de interfaz DBManager, como se vio anteriormente, por lo que esa será con

frecuencia la instrucción que accederá a DDADBManager por primera vez, creando la instancia.

Por otra parte, no hay muchas más novedades con respecto al abstract: simplemente se proponen algunos

métodos para limpiar las cachés propias de esta aplicación.

Queda una parte importante de la gestión de la base de datos por comentar. Hasta ahora se ha ido desgranando

la configuración de la base de datos, comentando la capa correspondiente a cada librería o proyecto de MEDIPi.

Es por ese motivo por el que se ha dejado para el final la capa básica, aquella encargada de parametrizar o

configurar la conexión (indicar la ip de la base de datos, el esquema, las regiones de caché, etc.). Cada aplicación

podrá personalizar la suya, indicando simplemente el persistenceUnit y la queryCacheRegion al

Page 126: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

126

126

AbstractDBManager que actúa a modo de configurador común.

Para parametrizar una conexión a base de datos con JPA se ha de emplear un fichero denominado

persistence.xml y ubicado en directorio-base-proyecto/META-INF. En este fichero, mediante una sintaxis

determinada que veremos a continuación, se especifica toda la configuración necesaria.

<persistence xmlns="http://java.sun.com/xml/ns/persistence"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistence

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"

version="2.0">

<persistence-unit name="medipi.dda" transaction-type="RESOURCE_LOCAL">

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<!-- HEALTH -->

<class>medipi.health.dom.Patient</class>

<class>medipi.health.dom.Episode</class>

<class>medipi.health.dom.Constant</class>

<class>medipi.health.dom.ConstantInfo</class>

<!-- DATA_ACQ -->

<class>medipi.datacq.dom.Allocation</class>

<class>medipi.datacq.dom.Device</class>

<class>medipi.datacq.dom.DeviceModel</class>

<class>medipi.datacq.dom.DeviceType</class>

<class>medipi.datacq.dom.MedipiInstance</class>

<class>medipi.datacq.dom.Parameter</class>

<class>medipi.datacq.dom.Protocol</class>

<class>medipi.datacq.dom.ProtocolConstantMap</class>

<properties>

<!-- JPA 2.0 Standard -->

<property name="javax.persistence.jdbc.driver"

value="oracle.jdbc.driver.OracleDriver" />

<property name="javax.persistence.jdbc.url"

value="jdbc:oracle:thin:@${db_ip}:${db_port}:${db_sid}" />

. . .

</properties>

</persistence-unit>

</persistence>

En un persistence.xml podemos definir tantos persistence-unit como queramos. Cada persistence-unit es una

parametrización diferente, pudiendo variar cada uno de sus argumentos: base de datos, parámetros de hibernate,

caché, entidades reconocidas, etc. El nombre del persistence-unit es el identificador que el

EntityManagerFactory necesita conocer para poder generar las EntityManager. Junto al identificador se ha de

especificar el tipo de transacción empleada. Este es un asunto complejo e implica el conocimiento de varios

elementos de JPA a bajo nivel, como la caché interna de JPA [70]. Simplificando, con el tipo JTA se puede

instanciar EntityManagers (aunque nunca una EntityManagerFactory) y cada EntityManager estará asociada a

una transacción. Será necesaria la existencia de una capa de negocio o servicio (siendo el estándar EJB y lo más

empleado Spring Framework, etc.) que se comunicarán con JPA para gestionar dichas transacciones, pudiendo

el desarrollador indicar determinadas políticas de las mismas mediante anotaciones. Por otra parte,

RESOURCE_LOCAL delega en el desarrollador la tarea de crear los EntityManagers que considere necesarios

a partir de un EntityManagerFactory y de gestionar sus transacciones. Deberá crearse la transacción, realizarse

los commits y rollback adecuados según el programador considere. Esta opción es más artesanal, pero evita la

necesidad de implementar una capa de servicio innecesaria para los proyectos actuales. Además, ofrece mucha

más versatilidad al dar más control al desarrollador, motivos por los que se ha empleado. Conviene darse cuenta

de que está decisión es coherente con lo desarrollado en el AbstractDAO de core-dom, donde se gestiona la

Page 127: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

127

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

127

transacción manualmente.

Para cada persistence-unit indicamos qué implementación de JPA se va a usar, pues JPA no es más que el

estándar, la API que Hibernate implementa. A continuación, se indican las entidades JPA que este persistence-

unit manejará.

La sección de properties es la principal: en ella se encuentra la mayor parte de la configuración. Para rellenar

muchos de los parámetros se emplean variables de Maven. Recordemos que el persistence.xml se encuentra en

una carpeta dentro de la ruta de resources de Maven y que dicho directorio está siendo filtrado, sustituyendo las

variables con sintaxis ${variable} por el valor indicado en el filtro correspondiente al perfil actual. De esta

manera podemos cambiar muchos parámetros de configuración de acuerdo al perfil, de una manera ágil y sin

inconsistencias.

Nivel Parámetro Valor Descripción

javax.persistence. jdbc.driver oracle.jdbc.driver.OracleDriver Driver de JDBC

javax.persistence. jdbc.url jdbc:oracle:thin:@${db_ip}:${

db_port}:${db_sid} Conexión a BBDD

javax.persistence. jdbc.user ${db_user} Usuario para la

conexión

javax.persistence. jdbc.password ${db_password} Password para la

conexión

hibernate. cache.provider_class org.cache.EhCacheProvider Proveeder de la caché

de segundo nivel.

hibernate. dialect org.dialect.Oracle10gDialect

Dialecto

(Especificación) de la

base de datos empleada

hibernate. default_schema ${db_user} Esquema

hibernate. generate_statistics true Generar estadísticas

hibernate. cache.use_structured_en

tries true

Almacena datos en un

formato más

visualizable / explotable

hibernate. cache.use_minimal_puts true Optimizador

hibernate. format_sql true

Formatear las consultas

SQL para una mejor

explotación

hibernate. show_sql ${hibernate_sql_value} Visualización de las

consultas en el LOG.

hibernate. cache.region.factory_cla

ss

org.cache.ehcache.EhCacheReg

ionFactory

Clase de la factoría de

regiones de caché

hibernate. cache.use_second_level

_cache true

Emplear caché de

segundo nivel

Page 128: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

128

128

hibernate. cache.use_query_cache true Usar caché de consultas

net.sf.ehcache. configurationResourceN

ame ehcache.xml Descriptor de la caché

De los parámetros solo es interesante destacar la configuración de la caché de segundo nivel de Hibernate,

indicándole que proveedor usaremos y en qué fichero se configura.

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

<defaultCache eternal="false" maxElementsInMemory="100"

timeToLiveSeconds="86400" overflowToDisk="false" diskPersistent="false"

/>

<cache name="constant" maxElementsInMemory="100" eternal="false"

timeToLiveSeconds="86400" overflowToDisk="false" diskPersistent="false"

/>

<cache name="protocolConstantMap" maxElementsInMemory="50"

eternal="false" timeToLiveSeconds="86400" overflowToDisk="false"

diskPersistent="false" />

<cache name="queries" maxElementsInMemory="50" eternal="false"

timeToLiveSeconds="86400" overflowToDisk="false" diskPersistent="false"

/>

</ehcache>

La configuración de la caché es muy sencilla. EhCaché maneja un concepto denominado regiones de caché, de

forma que crea varias pequeñas cachés independientes. Cada una de ellas, incluyendo la caché por defecto, se

parametrizan aquí.

Nombre Descripción

name Identificador de la región de caché

eternal Caché permanente

maxElementsInMemory

Número de elementos máximos en memoria. Si una caché alcanza este número

de elementos, los nuevos registros se incluirán en la caché eliminando los más

antiguos.

timeToLiveSeconds Cuando un elemento supera este timeout se borra automáticamente de la caché.

overflowToDisk Si se supera el umbral definido por maxElementsInMemory se usará el disco

duro (y no la memoria RAM) como soporte para almacenar más datos.

diskPersistent Controla que la parte de la caché almacenada en el disco duro no se elimina al

parar la aplicación.

Para hacer referencia a estas regiones se han visto ya las dos opciones: indicar la región de la cache en el mapeo

de JPA (anotación @Cache) o indicar a una JPAQuery que debe incluir dicha consulta en una región

determinada (query. setHint (DBConstants. ACTIVE_QUERY_CACHE, true); y query. setHint (DBConstants.

ACTIVATE_QUERY_CACHE_REGION, myDBManager. getQueryCacheRegion());).

Page 129: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

129

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

129

5.5.5.2.3.1.4 ReportNetwok

Cada instancia de DDA, cada ejecución de dicho programa se identifica unívocamente a través del hostname

del equipo sobre el que corre. Por tanto, la arquitectura de DDA no está pensada para arrancar dos aplicaciones

DDA en un mismo dispositivo. El motivo es claro: este módulo de MEDIPi se encarga de establecer una

comunicación con los biodispositivos a los que está conectado. En capítulos anteriores hemos definido que se

empleará una Raspberry Pi para correr nuestro programa, con la mayoría de los dispositivos conectados

directamente mediante una interfaz USB o RS232. Por tanto, no tiene sentido que haya dos programas a la vez

intentando comunicarse con un dispositivo, pues al leer o pretender escribir a la vez en un mismo puerto

provocaría que la información se corrompiera. Es por este razonamiento por el que se ha diseñado una

arquitectura basada en una ejecución de DDA, una máquina. Volviendo atrás, partimos de que se va a emplear

el hostname para identificar una instancia, pudiendo emplear dicho nombre de equipo para recuperar el registro

de base de datos de MEDIPI_INSTACE. A través de él podremos, por ejemplo, encontrar los registros en la

tabla ALLOCATION de dicha MEDIPI_INSTANCE asociados actualmente.

public static void reportNetwork() {

// Discover Ip

String ip = DDAUtils.discoverMyIpAddress();

String port = String.valueOf(PropertiesReader.

getProperty(DDAConstants.COMMAND_LISTENER_PORT));

String info = ip + DDAConstants.IP_PORT_SEPARATOR + port;

// If daemon has network connectivity report server port. If not report

// connection out

if (ip != null && !ip.isEmpty() && port != null && !port.isEmpty()) {

MedipiInstance myInstance = DDAConfiguration.getMyInstance();

myInstance.setIp(info);

DDAConfiguration.saveMedipiInstance(myInstance);

}

}

ReportNetwork no es más que un método ejecutado directamente desde el main de DDA para realizar la última

labor de configuración del sistema: identificar el hostname de su equipo y escribir en MEDIPI_INSTANCE la

dirección ip y el puerto con el que otros sistemas podrán comunicarse con él. Para ello se emplean dos sencillos

métodos: discoverMyIpAddress y getMyInstance. El primero es un método de DDAUtils que se encarga de

recuperar las interfaces de red (mediante NetworkInterface.getNetworkInterfaces()) y recorrerlas una a una hasta

encontrar aquella con una configuración IP válida. Por otro lado, getMyInstance recupera el hostname y acude

con él a base de datos para recuperar un objeto MedipiInstance que mapee dicho registro. Para recuperar el

hostname se lanza una instrucción en línea de comandos para posteriormente leer el resultado, mediante las

utilidades proporcionadas por Java para dicha tarea.

Process process = Runtime.getRuntime().exec("hostname");

BufferedReader reader = new BufferedReader(new

InputStreamReader(process.getInputStream()));

String hostname = reader.readLine().trim();

Basta con recuperar el puerto del CommandListener (ubicado en un properties y recuperable por tanto a través

de PropertiesReader) para tener toda la información necesaria antes de realizar la actualización en base de datos.

Page 130: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

130

130

5.5.5.2.3.2 ProtocolReader

Figura 5-31. ProtocolReader

El conjunto de clases que agrupamos bajo la categoría ProtocolReader constituye el núcleo de DDA, pues serán

las encargadas de realizar una implementación estructurada y estandarizada de los protocolos necesarios para

establecer la comunicación con los biodispositivos. En la imagen anterior observamos un esquema básico de

esta sección de DDA que iremos detallando a lo largo de este epígrafe. Atendiendo a dicha representación nos

encontramos con dos elementos claramente diferenciados.

5.5.5.2.3.2.1 ProtocolReader

Cada vez que se quiera establecer una comunicación con un dispositivo concreto será necesario llevar a cabo el

desarrollo Java de dicha integración. Para estandarizar esta tarea lo máximo posible se ha creado una interfaz

conocida como ProtocolReader, de forma que cada desarrollo de un protocolo concreto la implemente, teniendo

así una base común. De esta forma, el ProtocolReaderManager podrá trabajar con referencias a ProtocolReader,

independientemente de la clase concreta. Sin embargo, no nos bastará con una mera interfaz, será imprescindible

la creación de un Abstract que maneje la lógica común a todos los protocolos. Por ejemplo, todos los protocolos

deben construir un objeto representativo de la variable biomédica recuperada y enviarlo al apartado software de

DDA encargado de comunicarlo al clúster. Esta tarea será común a todos, por lo que es absurdo duplicar lógica

en las diferentes clases.

public interface ProtocolReader {

public ProtocolReader createAndConfigurate();

public void start();

public boolean stop();

public void sendObservation(String constantName, Object value, String unitName,

Date constantDate);

public void sendObservation(String constantName, Object[] value, String

unitName, Date startDate, Float periodobs);

public Allocation getAllocation();

public void setAllocation(Allocation allocation);

}

La interfaz fuerza la implementación de varios métodos. Los tres primeros (createAndConfigurate, start y stop)

se emplean simplemente para manejar el flujo de trabajo del protocolo. Justo tras instanciar una clase que

implemente ProtocolReader se llamará al método createAndConfigure donde cada protocolo realizará las tareas

necesarias para preparar la integración con el dispositivo. Por su parte, start y stop serán llamados por el

ProtocolReaderManager para arrancar o parar el ProtocolReader cuando sea necesario. Además de los métodos

Page 131: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

131

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

131

ya comentados, ProtocolReader obliga a implementar getters y setters de la asignación, lo que implica que todo

lector de protocolos debe conocer la asignación concreta con la que se corresponde, U poco más adelante

veremos la utilidad de esta decisión. Para finalizar, define dos métodos sendObservation que los protocolos

emplearán cuando hayan recuperado una constante biomédica, realizando además su envío a otros puntos de

DDA.

Es el turno de analizar la clase AbstractProtocolReader. Esta clase va a contener solo dos atributos: un índice o

identificador único del ProtocolReader en el ProtocolReaderManager y la asignación de dispositivo a la que da

soporte. Este último venía prácticamente impuesto por la interfaz, que nos obligaba a implementar su getter y

setter. El índice solo será realmente útil cuando se vayan a instanciar dos o más ProtocolReaders iguales, de

forma que ambos tengan un identificador único que puedan emplear para instanciar otros objetos. Por su parte,

conocer la asignación es mucho más útil: es posible que dos modelos de dispositivos empleen el mismo

protocolo con algunas diferencias. En ese caso, el patrón de diseño recomendado es manejar el mismo

ProtocolReader, pero emplear el campo info del modelo para identificar sus particularidades. Para solucionar

esto el ProtocolReader conoce el dispositivo al que da soporte, sabiendo su modelo, tipo, etc.

protected int index;

protected Allocation allocation;

public AbstractProtocolReader(int index, Allocation allocation) {

this.index = index;

this.allocation = allocation;

}

public int getIndex() {

return index;

}

public void setIndex(int index) {

this.index = index;

}

@Override

public void setAllocation(Allocation allocation) {

this.allocation = allocation;

}

@Override

public Allocation getAllocation() {

return allocation;

}

Por otra parte, se definen los métodos sendObservation, encargados de recibir la información de una constante

biomédica del paciente, construir un objeto de tipo LFInfoConstant o HFInfoConstant y enviarlo a la clase

encargada de comunicarse con el clúster Kafka. La lógica realizada en estos métodos es muy sencilla: a partir

de los datos conocidos recuperamos la constante y el episodio al que hace referencia, construyendo el objeto

apropiado. En el caso de las LFInfoConstants se realiza una comprobación básica: si es una constante de tipo

numérica se ignorará la información si el valor se encuentra fuera de los rangos permitidos indicados en base de

datos. Tras esto, se envía el ConstantInfo al DataSenderManager, que se comentará más adelante.

@Override

public synchronized void sendObservation(String constantName, Object value,

String unitName, Date constantDate) {

String protocolCode = allocation.getDevice().getDeviceModel().

getProtocol().getCode();

Constant cnt = DDAConfiguration.

getConstantByProtocolMap(protocolCode, constantName);

Episode epi = allocation.getEpisode();

if (cnt != null && epi != null && valueFiltering(value, cnt)) {

LFConstantInfo observation = new

LFConstantInfo(cnt.getConstantId(), epi.getEpisodeId(),

constantDate, String.valueOf(value), false);

DataSenderManager.sendInfoToAll(observation);

Page 132: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

132

132

}

}

Con esto se define la arquitectura de clases de una implementación de un protocolo para la comunicación con

biodispositivos. Se han definido un conjunto de políticas y mecanismos que se deberán seguir mediante la

herencia de la clase AbstractProtocolReader. Al margen de eso, será tarea de cada implementación lidiar con las

particularidades de su protocolo.

5.5.5.2.3.2.2 ProtocolReaderManager

Clase encargada de ir a base de datos, recuperar los dispositivos asignados a la instancia actual, encontrar los

ProtocolReaders asociados a dichos dispositivos y realizar las operaciones necesarias para cuadrar los

ProtocolReaders actuales del sistema con los esperados de acuerdo a la configuración de base de datos. Es, por

tanto, una clase gestora, de forma que sus métodos servirán de punto de acceso para otras clases de DDA. Para

evitar tener que instanciar un objeto de esta clase cada vez que se quiere refrescar, parar o arrancar un lector de

protocolos se emplearán métodos y atributos estáticos.

La base de ProtocolReaderManager es sencilla: se va a mantener un mapa con todos los ProtocolReader que

corren actualmente en el sistema, de forma que podrá comparar dicho mapa con la información proporcionada

por la base de datos.

Map<Integer, ProtocolReader> protocolReaderMap = new LinkedHashMap<Integer,

ProtocolReader>();

ProtocolReader cuenta con un conjunto de métodos estáticos para cubrir la funcionalidad descrita:

- getProtocolReaderByAllocation: a través de un objeto Allocation (mapeo JPA de un registro de la

tabla ALLOCATION) es posible acceder al modelo, tipo y protocolo del dispositivo concreto asociado.

Con esta información, el método getProtocolReaderByAllocation se encarga de encontrar la

implementación de ProtocolReader más adecuada. Como es evidente, existirá una implementación de

ProtocolReader para cada protocolo, por lo que el núcleo del método no será más que un conjunto de

if/else en función del código del protocolo del dispositivo.

- startReaders: es probablemente el método más básico de ProtocolReaderManager. Como se puede

deducir, se encarga simplemente de recuperar las asignaciones actuales en base de datos y comprobar

si ya se están manejando mediante algún ProtocolReader. Para aquellas asignaciones nuevas se busca e

instancia el ProtocolReader adecuado (mediante una llamada a getProtocolReaderByAllocation). Este

ProtocolReader se añade al mapa para futuras comprobaciones.

- conditionalStopReaders: realiza la tarea inversa al método anterior: recorre el mapa de

ProtocolReaders actual para ver si hay alguna asignación que ya no esté en base de datos, procediendo

a pararla.

- forceStopReaders: para todos los ProtocolReader actualmente arrancados, independientemente de lo

que indique la base de datos.

- updateReaders: comprueba que los ProtocolReaders son los adecuados mediante una parada

condicional, una limpieza de la caché de consultas y el arranque de los readers.

- restart: fuerza la parada de todos los ProtocolReaders actuales, limpia todas las cachés del sistema y

vuelve a arrancar los lectores de protocolos.

- getProtocolReaderByIndex: simplemente accede al mapa, devolviendo el ProtocolReader

correspondiente al índice especificado.

- getters y setters del mapa protocolReaderMap.

Page 133: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

133

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

133

Los distintos métodos de ProtocolReaderManager son llamados desde varios puntos de DDA, destacando la

llamada a startReaders desde el main y las posibles llamadas a updateReaders y restart por el servidor de

comandos.

5.5.5.2.3.3 CommandListener

DDA cuenta con un servidor de comandos preparado para escuchar en un puerto determinado un conjunto de

comandos soportados que provocarán las acciones oportunas en la aplicación. Para construirlo se va a emplear

una clase CommandListenerServer que herede de Thread, de forma que arrancamos un hilo para este servidor.

Además, los comandos no serán más que valores numéricos decimales que se enviarán entre un cliente y este

servidor. Es decir, se buscará leer un byte de información, transformando este byte en su representación decimal.

Este valor será el comando intercambiado.

Figura 5-32. CommandListener

Se trata de un servidor muy simple, construido directamente con Java:

ServerSocket servidor = new ServerSocket(puertoConexion);

Socket conexion = servidor.accept();

BufferedInputStream is = new BufferedInputStream(conexion.getInputStream());

InputStreamReader isr = new InputStreamReader(is);

int comando;

while (true) {

comando = isr.read();

selectCommand(comando, conexion);}

Se crea un socket y se acepta la conexión. La llamada al read() bloquea el hilo hasta que se recibe un byte. Cada

byte se castea a un int y se manda a un método encargado de realizar las acciones que se correspondan con dicho

comando. Las acciones soportadas se pueden ver en el esquema con el que comienza este apartado.

- refreshThreads: llama al método updateThreads() de ProtocolReaderManager. Devuelve ACK.

- refreshCache: limpia todas las cachés empleadas por DDA. Devuelve ACK.

- restart: llama al método restart de ProtocolReaderManager. Devuelve ACK.

- test: devuelve ACK sin realizar ninguna acción.

El valor con el que se corresponde cada uno de los comandos anteriores (incluyendo el ACK) se ha fijado en la

clase DDAUtils mediante el empleo de constantes.

Además, se ha añadido un cliente para este servidor entre los tests de DDA, bajo la denominación de

TestCommandListenerClient.

5.5.5.2.3.4 DataSender

Para dotar de escalabilidad a la solución se ha optado por entender el envío de datos al Kafka como uno de los

posibles destinos de la información biomédica. De esta manera, la comunicación con el clúster se comporta

Page 134: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

134

134

como uno de los posibles DataSenders de DDA, permitiendo al desarrollado añadir o eliminar nuevos. Por

ejemplo, podemos pensar en un nuevo DataSender muy sencillo: un fichero de texto en el que se vuelquen los

datos tal y como se van obteniendo. Por tanto, si ahora el envío de datos al clúster es solo uno de los posibles

destinos es necesario una capa intermedia que reciba los datos y se los pase a los DataSenders adecuados.

El patrón de diseño es exactamente el mismo al diseñado para ProtocolReader: contaremos con una interfaz que

define los métodos básicos (DataSender), implementaciones concretas (KafkaDataSender) y un organizador o

gestor (DataSenderManager). En este caso no es necesaria la existencia de una clase abstracta ya que no existe

lógica común a mantener.

Figura 5-33. DataSenderManager

5.5.5.2.3.4.1 DataSender

La interfaz DataSender define solamente dos métodos: sendInfo(LFConstantInfo) y sendInfo(HFConstantInfo).

Cada implementación concreta deberá implementar este método para recibir los objetos, procesarlos si es

necesario y almacenarlos / enviarlos a donde corresponda.

Por ejemplo, KafkaDataSender simplemente instancia y configura dos MedipiProducers (uno para cada topic)

y envía los objetos recibidos al clúster, gracias al diseño realizado en core-Cluster.

public class KafkaDataSender implements DataSender {

private MedipiLFProducer producerLF;

private MedipiHFProducer producerHF;

public KafkaDataSender() {

Properties props = new Properties();

props.put(KafkaConstants.PROP_SERVER_LIST,

PropertiesReader.getProperty(KafkaConstants.VALUE_SERVER_LIST));

props.put(KafkaConstants.PROP_KEY_SER,

PropertiesReader.getProperty(KafkaConstants.VALUE_KEY_SER));

props.put(KafkaConstants.PROP_VALUE_SER,

PropertiesReader.getProperty(KafkaConstants.VALUE_VALUE_SER));

props.put(KafkaConstants.PROP_RETRIES,

PropertiesReader.getProperty(KafkaConstants.VALUE_VALUE_RETRIES));

props.put(KafkaConstants.PROP_LINGER,

PropertiesReader.getProperty(KafkaConstants.VALUE_LINGER));

props.put(KafkaConstants.PROP_BATCH,

PropertiesReader.getProperty(KafkaConstants.VALUE_BATCH));

props.put(KafkaConstants.PROP_FIRST_TS,

PropertiesReader.getProperty(KafkaConstants.VALUE_FIRST_TS));

props.put(KafkaConstants.PROP_ACK_TS,

PropertiesReader.getProperty(KafkaConstants.VALUE_ACK_TS));

producerLF = new MedipiLFProducer();

producerLF.initialize(props);

producerHF = new MedipiHFProducer();

producerHF.initialize(props);

}

@Override

public void sendInfo(LFConstantInfo info) {

Page 135: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

135

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

135

producerLF.sendLFConstantInfo(info);

}

@Override

public void sendInfo(HFConstantInfo info) {

producerHF.sendHFConstantInfo(info);

}

}

5.5.5.2.3.4.2 DataSenderManager

Es una clase con dos funciones claramente diferenciadas:

- Organizar los DataSenders, instanciando y manteniendo aquellos disponibles.

static {

instantiateDataSenders();

}

private static void instantiateDataSenders() {

try {

dataSenderList = new ArrayList<DataSender>();

dataSenderList.add(new KafkaDataSender());

} catch (Exception e) {

LOG.error("Error creating data senders.", e);

System.exit(1);

}

}

- Servir de intermediario al resto de la aplicación: cuando un ProtocolReader haya recuperado una

constante biomédica se la enviará al DataSenderManager, quien a su vez se la reenviará a todos los

DataSenders disponibles, evitando que los ProtocolReaders tengan que conocer el estado actual de cada

DataSender disponible en el programa.

public static void sendInfoToAll(LFConstantInfo constantInfo) {

for (DataSender ds : dataSenderList) {

ds.sendInfo(constantInfo);

}

}

public static void sendInfoToAll(HFConstantInfo constantInfo) {

for (DataSender ds : dataSenderList) {

ds.sendInfo(constantInfo);

}

}

5.5.5.2.3.5 Util

Como último comentario acerca de DDA se destaca que cuenta con dos clases de utilidades: una para métodos

comunes o considerados de propósito general (DDAUtil) y otro para almacenar las constantes del módulo de

acuerdo a la política general de la suite (DDAConstants).

5.5.5.3 SAVER

5.5.5.3.1 Funcionalidad de la aplicacio n

SAVER es el módulo de la suite MEDIPI encargado de consumir la información existente en el clúster para

procesarla y almacenarla en la base de datos. Solo se van a procesar las constantes discretas o a baja frecuencia,

pues son las únicas que tiene sentido almacenar en base de datos. El resto serán tratadas por otras aplicaciones

de la suite.

Page 136: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

136

136

Figura 5-34. Proyecto SAVER

5.5.5.3.2 Configuracio n de proyecto Maven

Como todo proyecto Maven cuenta con un descriptor pom.xml, en el que hace referencia al proyecto padre y se

especifica nombre del proyecto, versión y dependencias. En este caso las dependencias son solo internas: core-

app para poder seguir la arquitectura de las aplicaciones de la suite, core-Cluster para la comunicación con Kafka

y datacq-dom para poder trabajar con referencias al esquema DATA_ACQ de base de datos.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-app</artifactId>

<version>1.0</version>

</parent>

<artifactId>saver</artifactId>

<packaging>jar</packaging>

<name>saver</name>

<dependencies>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>datacq-dom</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-Cluster</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-app</artifactId>

<version>${project.version}</version>

</dependency>

</dependencies>

5.5.5.3.3 Co digo Java

SAVER es la aplicación más sencilla de la suite. Esto no solo se debe a que realiza una funcionalidad que no es

excesivamente compleja (leer las constantes del clúster, procesarlas y almacenarlas en base de datos), sino

también a que la estructura de clases diseñada para cubrir dicha funcionalidad es tremendamente similar a la

empleada en DDA:

- Configuración: será necesario configurar el log, el acceso a los properties, a la base de datos, etc.

- DataReader: recuperación de constantes de Kafka (y otros posibles puntos de entrada de datos).

Page 137: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

137

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

137

- DataWriter: existirán un conjunto de clases encargados de guardar la información recuperada por los

DataReaders en el sistema de almacenamiento concreto de cada uno, realizando algún procesamiento

intermedio se así se desea.

- Util: constantes.

Figura 5-35. Esquema de SAVER

5.5.5.3.3.1 Configuraciones básicas de la aplicación

La configuración de Log, PropertiesReader y acceso a la base de datos es similar a la comentada en el caso de

DDA.

5.5.5.3.3.2 DataReader

El principal punto de acceso de SAVER es las constantes biomédicas recibidas del clúster, pero se ha empleado

el mismo patrón de diseño que en DDA para permitir múltiples puntos de acceso. Por tanto, se define una interfaz

(DataReader), una clase abstracta con lógica común (AbstractDataSender) y un organizador

(DataSenderManager).

5.5.5.3.3.2.1 DataReader

La interfaz define simplemente tres métodos: startReading(), readedInfo(LFConstantInfo info) y

readedInfo(HFConstantInfo info). Mientras que el primero arranca la lectura de datos, el resto serán llamados

cuando se hayan recuperado datos del origen.

Por su parte, AbstractDataReader simplemente implemente los métodos readedInfo, enviando la información

común al DataReaderWriter.

Bajo este patrón se ha creado el siguiente KafkaDataReader.

public class KafkaDataReader extends AbstractDataReader {

private Properties props;

private MedipiLFConsumer consumerLF;

Page 138: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

138

138

private MedipiHFConsumer consumerHF;

public KafkaDataReader() {

props = new Properties();

props.put(KafkaConstants.PROP_SERVER_LIST,

PropertiesReader.getProperty(KafkaConstants.VALUE_SERVER_LIST));

props.put(KafkaConstants.PROP_GROUP,

PropertiesReader.getProperty(KafkaConstants.VALUE_GROUP));

props.put(KafkaConstants.PROP_KEY_DESER,

PropertiesReader.getProperty(KafkaConstants.VALUE_KEY_DESER));

props.put(KafkaConstants.PROP_VALUE_DESER,

PropertiesReader.getProperty(KafkaConstants.VALUE_DESER));

props.put(KafkaConstants.PROP_OFFSET,

PropertiesReader.getProperty(KafkaConstants.VALUE_OFFSET));

consumerLF = new MedipiLFConsumer() {

@Override

public void receiveLFConstantInfo(LFConstantInfo info) {

readedInfo(info);

}

};

consumerHF = new MedipiHFConsumer() {

@Override

public void receiveHFConstantInfo(HFConstantInfo info) {

readedInfo(info);

}

};

}

@Override

public void startReading() {

consumerLF.initialize(props);

consumerHF.initialize(props);

}

}

Simplemente, cuando cualquier DataReader procesa una constante llama al readedInfo que la envía al

DataWriterManager. Podemos observar cómo se están recuperando información de los dos topics, a pesar de

que se ha indicado que no se va a guardar en base de datos las constantes a alta frecuencia. Se ha optado por

implementar el consumer del HFConstantInfoTopic para explicitar una idea: una cosa es la información

recuperada por el DataSender y otra la procesada por el DataWriter. En este caso, el DataReader puede recuperar

la información, pero el DataWriter puede descartarla si así lo necesita para cumplir su propósito.

5.5.5.3.3.2.2 DataReaderManager

El DataReaderManager es prácticamente una copia del DataSenderManager, realizando las adaptaciones

oportunas. El main de SAVER llamará al método startReceiving() del Manager, que se encargará de recorrer su

mapa e invocar a dicho método en cada DataReader. Como siempre, el manager tiene todos sus métodos y

atributos estáticos, para que no haya que instanciar un objeto de esta clase cada vez que se vaya a actuar sobre

los DataReaders.

5.5.5.3.3.3 DataWriter

5.5.5.3.3.3.1 DataWriter

Empleamos, nuevamente, una estructura análoga. En este caso no hay lógica común por lo que no hay necesidad

de crear un abstract.

DBDataWriter implementa los dos métodos de la interfaz: writeInfo((LFConstantInfo) y

writeInfo(HFconstantInfo). A través de ellos llegarán las constantes biomédicas procedentes de los DataReaders.

Page 139: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

139

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

139

En este caso concreto, el método writeInfo de HFConstantInfo estará vacío, pues se descarta toda la información

de este tipo.

@Override

public void writeInfo(LFConstantInfo info) {

if (timeFiltering(info)) {

ConstantInfo ci = SaverConfiguration.

getConstantInfoByEpisodeAndConstant(info);

if (ci != null && ci.getValue() == null) {

ci.setConstantDate(info.getConstantDate());

ci.setManual(info.getManual());

ci.setValue(info.getValue());

SaverConfiguration.saveConstantInfo(ci);

}

}

}

Sí se implementa el writeInfo de las variables discretas, realizando un sencillo filtrado temporal. En timeFiltering

se tratan las variables recibidas para provocar que no se guarde toda la información recibida, solo un valor de

una misma constante médica para un episodio cada un determinado número de minutos. Dicha información

estará parametrizada en la base de datos. Por ejemplo, podemos colocar el valor del filtro en 5 minutos, de forma

que solo habrá un valor de una misma constante para un episodio cada 5 minutos. Por tanto, además de rechazar

datos se deberá tratar la fecha de la constante, poniendo una que sea representativa del periodo de filtrado (en

nuestro ejemplo serán 0’, 5’, 10’, etc.). Tras esto, se comprueba si existe un registro en base de datos que coincida

con el que se busca insertar, machacándolo con la información recibida en caso afirmativo.

5.5.5.3.3.3.2 DataWriterManager

DataWriterManager sirve para distribuir las constantes biomédicas recibidas por los DataSenders. Para ello

manejará una lista de DataWriters disponible y, al recibir un objeto de tipo LFConstantInfo o HFConstantInfo

llamará al writeInfo correspondiente de cada uno de ellos.

5.5.5.3.4 Paquete Util

En esta categoría SAVER solo cuenta con una clase de constantes denominada SaverConstants.

5.5.5.4 CHART

5.5.5.4.1 Funcionalidad de la aplicacio n

Chart es la aplicación de visualización de datos de la suite diseñada en el presente proyecto. Subscribiéndose al

clúster, mostrará las constantes vitales del paciente seleccionado en directo. Para ello, se empleará la librería

JavaFX, provocando que este sea el proyecto más diferenciado del resto de la suite. A pesar de ello, no deja de

ser una aplicación Java por lo que emplearemos la misma estructura que para el resto de aplicaciones.

Page 140: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

140

140

Figura 5-36. Proyecto CHART

5.5.5.4.2 Configuracio n de proyecto Maven

El pom.xml de CHART no se sale del patrón comentado hasta el momento: definición del proyecto actual,

referencia al padre y dependencias. Destaca que nos encontramos ante la única aplicación que no tiene

dependencias hacia datacq-dom, sino hasta health-dom. Simplemente no se emplea ninguna tabla de este

esquema, por lo que podemos ignorarlo y construir un proyecto más liviano gracias a la modularización.

<parent>

<groupId>medipi</groupId>

<artifactId>medipi-app</artifactId>

<version>1.0</version>

</parent>

<artifactId>chart</artifactId>

<packaging>jar</packaging>

<name>chart</name>

<dependencies>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>health-dom</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-Cluster</artifactId>

<version>${project.version}</version>

</dependency>

<dependency>

<groupId>${project.groupId}</groupId>

<artifactId>core-app</artifactId>

<version>${project.version}</version>

</dependency>

</dependencies>

5.5.5.4.3 Co digo Java

En esta aplicación debemos cambiar un poco el enfoque seguido hasta el momento, pues tener un objetivo

bastante diferenciado al resto provoca una estructura de software ligeramente distinta. Aun así, vamos a intentar

estructurar la explicación del desarrollo realizado de una manera lo más simular posible a la empleada en el resto

de aplicaciones.

Page 141: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

141

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

141

Figura 5-37. Esquema de CHART

- Configuración: al igual que en el resto de aplicaciones se ha de inicializar el log, los properties y el

acceso a la base de datos.

- KafkaDataReader: en este caso no se ha empleado el mismo patrón de diseño que en DDA o SAVER.

Se ha optado por tener una sola clase que gestiona la entrada de datos.

- Pantalla principal: la propia clase main arrancará una ventana en la que se debe seleccionar el paciente

del que se quieren consultar sus constantes vitales.

- Ventana de constantes vitales de un paciente.

- Util: métodos comúnes y constantes.

5.5.5.4.3.1 Configuraciones básicas de la aplicación

La configuración de Log, PropertiesReader y acceso a la base de datos es similar a la comentada en el caso de

DDA y SAVER.

5.5.5.4.3.2 KafkaDataReader

En este caso se ha optado por un enfoque diferente al comentado hasta ahora, mostrando de esta manera cómo

sería y qué ventajas proporciona. Será el main quien directamente llame a la clase KafkaDataReader encargada

de arrancar los consumers y subscribirlos a los dos topics del clúster Kafka. Con este patrón de diseño se manejan

menos clases, se carga menos información en memoria y se facilita el código, aunque se pierde en escalabilidad.

La decisión se sustenta en que Chart debe representar la información recuperada en tiempo real, por lo que no

tiene sentido otro punto de entrada distinto al clúster.

public static synchronized void receiveDataToAll(LFConstantInfo constantInfo) {

getDataQByEpisodeId(constantInfo.getEpisodeId()).add(constantInfo);

}

public static synchronized ConcurrentLinkedQueue<LFConstantInfo>

getDataQByEpisodeId(Long episodeId) {

Page 142: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

142

142

if (dataQMap.get(episodeId) == null) {

dataQMap.put(episodeId, new ConcurrentLinkedQueue<>());

}

return dataQMap.get(episodeId);

}

En las líneas superiores observamos el tratamiento que se hace de las constantes a baja frecuencia recibidas del

clúster. El KafkaDataReader de CHART maneja un mapa de colas Java. Cada episodio tiene una cola de

LFConstantInfo que será consumida por otros puntos de la aplicación. Para las constantes a alta frecuencia se

realiza un pretratamiento que genera un conjunto de LFConstantInfo por cada valor recibido, enviándolas al

método comentado.

5.5.5.4.3.3 MainWindow

La clase Main de CHART es la responsable, no solo de la configuración y arranque del KafkaDataReader, sino

también de generar la ventana principal de la aplicación.

Para comentarla conviene partir de algunos conceptos básicos de Java FX.

- Application: las clases Java que son controladoras de una ventana deben extender la clase abstracta

javafx.application.Application. Dicha clase proporciona un flujo de trabajo y obliga a implementar un

conjunto de métodos para la construcción de la ventana.

- Stage: es el objeto que se corresponde con la ventana en sí. Por ejemplo, contiene propiedades como el

icono de la ventana o el tamaño. Toda clase que extiende de Application debe implementar un método

start(Stage) en el que ya recibe la Stage que se mostrará en el pc donde se está ejecutando la aplicación.

- Scene: a una Stage se le puede asignar una y solo una Scene. El objeto Scene es quien contiene la

estructura de elementos de la ventana: textos, combos, botones, imágenes, etc.

Se ha definido un abstract denominado MedipiChartWindow. Las dos ventanas de la aplicación (la ventana

principal defina en Main y la de constantes de un paciente) extienden de este abstract, en el que simplemente se

setea el icono de la aplicación.

public abstract class MedipiChartWindow extends Application {

@Override

public void start(Stage stage) {

stage.getIcons().add(new Image(Main.class.getClassLoader()

.getResourceAsStream(ChartConstants.ICON_FILE_NAME)));

initialize(stage);

stage.show();

}

public abstract void initialize(Stage stage);

}

El primer paso es generar los elementos que se van a mostrar en pantalla. JavaFX proporciona un objeto de cada

elemento habitual en la construcción de interfaces de usuario. Es decir, tenemos objetos ComboBox, Button,

etc. Se pueden emplear los métodos proporcionados por los objetos UI de JavaFX para indicarles un aspecto,

texto, etc. Algunos de ellos buscan asociar un método externo a una actuación o estado concreto del elemento

en pantalla. Por ejemplo, el método setOnAction de Button espera recibir un objeto de tipo EventHandler. Este

manejador de eventos simplemente define un método principal en el que se desarrolla una lógica determinada.

Cuando se pulse el botón, Java llamará al método principal de la clase asociada a la acción de pulsación (en este

caso onAction). Por tanto, puede entenderse como una suscripción a eventos proporcionados por los objetos. En

las líneas de código posteriores se muestra la definición de algunos de los elementos de la ventana principal.

Page 143: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

143

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

143

final ComboBox<ComboEpisode> episodeComboBox = new ComboBox<ComboEpisode>();

episodeComboBox.getItems().addAll(refreshEpisodes());

episodeComboBox.valueProperty().addListener(new ChangeListener<ComboEpisode>(){

@Override

public void changed(ObservableValue<? extends ComboEpisode> observable,

ComboEpisode oldValue, ComboEpisode newValue) {

selected.setEpisodeId(newValue.getEpisodeId());

selected.setText(newValue.getText());

}

});

final Button refreshBtn = new Button(ChartConstants.REFRESH_BUTTON);

refreshBtn.setOnAction(new EventHandler<ActionEvent>() {

@Override

public void handle(ActionEvent e) {

episodeComboBox.getItems().clear();

episodeComboBox.getItems().addAll(refreshEpisodes());

}

});

final Button selectBtn = new Button(ChartConstants.SELECT_BUTTON);

selectBtn.setOnAction(new EventHandler<ActionEvent>() {

@Override

public void handle(ActionEvent e) {

if (selected.getEpisodeId() != null) {

Platform.runLater(new Runnable() {

public void run() {

try {

Long id = selected.getEpisodeId();

if (chartWindowMap.get(id) == null) {

ChartWindow win = new ChartWindow();

win.open(selected.getEpisodeId(),

selected.getText());

chartWindowMap.put(id, win);

}

} catch (Exception e) {

LOG.error("Error launching Chart Window: ", e);

}

}

});

}

}

});

Hacía al final del fragmento de código indicado arriba se observa la lógica que se realiza cuando se pulsa el

botón de seleccionar. Para entenderlo hay que comentar que la clase Main maneja un atributo básico: un mapa

de las ventanas de información de paciente abiertas actualmente (chartWindowMap) indexadas por el

identificador único de episodio. Al pulsar el botón de seleccionar, si no hay ya una ventana abierta para dicho

paciente se instancia y arranca la ventana adecuada.

GridPane grid = new GridPane();

grid.setVgap(7);

grid.setHgap(4);

grid.setPadding(new Insets(20, 20, 20, 20));

grid.add(img, 0, 0, 4, 1);

GridPane.setHalignment(img, HPos.CENTER);

grid.add(new Label(ChartConstants.EPISODE_LABEL), 0, 4);

grid.add(episodeComboBox, 1, 4);

grid.add(refreshBtn, 3, 4);

grid.add(selectBtn, 0, 6, 4, 1);

GridPane.setHalignment(refreshBtn, HPos.RIGHT);

Page 144: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

144

144

GridPane.setHalignment(selectBtn, HPos.CENTER);

Group root = (Group) scene.getRoot();

root.getChildren().add(grid);

stage.setScene(scene);

Una vez definidos los elementos se han de asociar a la Scene del Stage actual de acuerdo a un diseño

determinado. Para ello se ha empleado un Grid (cuadrícula) de 4x7. Al Grid se le van añadiendo los diferentes

objetos de la UI, mediante el método add. En él se especifican, de izquierda a derecha: la columna, la fila, el

número de columnas a ocupar (1 si no se indicada nada) y el número de filas a ocupar (1 por defecto). De esta

manera indicamos la ubicación de los diferentes elementos en la Scene, dotándola del aspecto que consideremos

adecuado. Una vez realizada esta tarea se ubica el grid en la raíz de la escena.

5.5.5.4.3.4 ChartWindow

Ya se ha visto como se instancia objetos ChartWindow desde la clase principal cuando se selecciona un paciente

determinado y se pulsa el botón de selección. La clase ChartWindow, que también hereda del abstract común

MedipiChartWindow, se sustenta en un objeto de tipo LineChart. Esta clase facilita la representación de gráficos

de tipo lineal, pues ofrece un conjunto de métodos que nos permiten indicar los datos a representar y personalizar

el aspecto que tendrá la gráfica. Basta con llamar al constructor de Scene indicándole un objeto de tipo LineChart

para que la ventana generada incluya una gráfica lineal.

Para añadir valores a representar a un LineChart se emplea el método getData().add(Series). Una serie no es más

que un conjunto de datos con sentido común, en nuestro caso formará una serie todos los datos de una misma

constante. Para controlarlas se empleará un mapa en el que las series serán identificadas por la id de la constante

a la que representan. Como se puede ver, las series creadas para Chart esperan recibir dos valores: uno de tipo

Date para el eje X y otro de tipo Number para el eje Y.

private Map<Long, Series<Date, Number>> graphMap = new HashMap<>();

Para controlar el desplazamiento del eje temporal se va a emplear un objeto de tipo

javafx.animation.AnimationTimer. Esta clase define un timer que será cargado en cada frame, en cada instante

temporal en el que se refresca la información en pantalla. Se trata de una clase abstracta que obliga a implementar

un método handle(long now). En dicho método se ubica la lógica que se ha de realizar para ese frame (que ocurre

en now milisegundos).

private void prepareTimeline() {

animation = new AnimationTimer() {

@Override

public void handle(long now) {

addDataToSeries();

cleanOldSeriesData();

}

};

animation.start();

}

private void addDataToSeries() {

while (!KafkaDataReader.getDataQByEpisodeId(selectedEpisodeId).isEmpty()) {

LFConstantInfo ci = KafkaDataReader.getDataQByEpisodeId

(selectedEpisodeId).remove();

Series<Date, Number> ser = getSeries(ci.getConstantId());

ser.getData().add(new Data<Date, Number>(ci.getConstantDate(),

Float.valueOf(ci.getValue())));

}

}

Page 145: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

145

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

145

private void cleanOldSeriesData() {

Calendar cal = Calendar.getInstance();

cal.setTime(new Date());

cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) –

ChartConstants.INTERVAL_IN_SECONDS);

for (Long id : graphMap.keySet()) {

ObservableList<Data<Date, Number>> obList = graphMap.get(id).getData();

if (obList != null && !obList.isEmpty()) {

obList.removeIf(p -> p.getXValue().before(cal.getTime()));

}

}

}

private Series<Date, Number> getSeries(Long cntId) {

if (graphMap.get(cntId) == null) {

Series<Date, Number> series = new LineChart.Series<Date, Number>();

series.setName(ChartConfiguration.getConstantById(cntId).

getDescription());

chart.getData().add(series);

graphMap.put(cntId, series);

}

return graphMap.get(cntId);

}

En cada frame se realizan dos fases: añadir datos a la serie y eliminar datos antiguos. En el primero se lee cada

dato disponible hasta el momento para la cola de este episodio manejada por KafkaDataSender. Con cada dato

se va al método getSeries para recuperar la serie de su constante. Es importante ver que en este método se crea

la serie por primera vez, metiéndola en el mapa y, más importante aún, añadiéndola a Chart. Es decir, la serie se

añade a la gráfica solo la primera vez, lo que estamos haciendo para cada frame será añadir y quitar datos. Tras

recuperar la serie se añade un punto XY con los datos recibidos, pasando después a la segunda fase, Para la fase

de eliminación se emplea la fecha en la que se ha parado el timer (recibida en milisegundos). Con esta fecha se

puede calcular una fecha umbral (la fecha actual menos determinado intervalo de tiempo configurable) y recorrer

toda la serie para eliminar los datos antiguos. La gráfica se expande / contrae automáticamente según el tamaño

del eje X que debe representar. Gracias a este control nos aseguramos de que represente siempre el mismo

intervalo temporal (definido por la constante INTERVAL_IN_SECONDS), evitando que el

redimensionamiento distorsione la representación de las constantes biomédicas del paciente.

Resumen de la descripción de la propuesta

A lo largo del presente capítulo se ha detallado con profundidad el proyecto realizado, comentando ampliamente

todas y cada una de las partes que componen esta aplicación (o mejor dicho aplicaciones) IoMT: desde la

Raspberry Pi 2 Modelo B sobre la que correremos nuestro software de integración con biodispositivos, pasando

por la base de datos Oracle y los servidores de colas de mensajes distribudas hasta llegar al último punto del

proyecto: una aplicación Java FX que permita a los facultativos observar las constantes médicas de los pacientes

en tiempo real. En algunos casos nos hemos centrado solamente en explicar el enfoque tomado y en detallar la

parametrización y configuración necesaria para adecuar los productos ya existentes a neustras necesidades. Sin

embargo, en los últimos epígrafes se ha analizado los pormenores del software creado exclusivamente para este

proyecto, comentando cuando, cómo y con qué finalidad se han utilizado todas y cada una de las tecnologías

implicadas.

Page 146: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Descripción de la propuesta

146

146

Page 147: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

147

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

147

6 VALIDACIÓN

urante todos los capítulos que componen esta memoria se ha ido detallando, desde distintas perspectivas,

la realización del proyecto. Se puede comprobar que en todo momento se han comentado las decisiones

funcionales, tecnológicas o de diseño en relación a los objetivos que se marcaron al inicio del proyecto,

y que están presentes en el primer capítulo de este texto. Con ellos en mente se va a llevar a cabo una validación

del proyecto, probando su correcto funcionamiento.

Funcionamiento de la solución

El primer punto de este proyecto es la Raspberry Pi 2 que, conectada a los biodispositivos y ejecutando nuestro

software de recolección de datos (DDA – Device Data Acquisition), se encarga de interpretar los protocolos

propietarios, recuperar la información biomédica y mandarla al clúster de Kafka.

Figura 6-1. Raspberry Pi 2 Modelo B conectada a un biodispositivo mediante un adaptador USB – RS232

La Raspberry, que corre el sistema operativo Raspbian, debe contar con la última versión del software DDA,

encargado de establecer la comunicación con los biodispositivos implicados.

Figura 6-2. Módulo DDA desplegado en la Raspberry

Una vez se tiene preparada la Raspberry, debemos asegurarnos de que Base de Datos y clúster Kafka están

arrancados y funcionando adecuadamente.

D

Page 148: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Validación

148

148

Figura 6-3. Entorno de desarrollo SQL conectado correctamente a la base de datos

Figura 6-4. Nodos Zookeeper, Broker 1 y Broker 2 arrancados sobre una misma máquina Windows

Con todo preparado, basta con arrancar DDA ejecutando el fichero start.sh ubicado en la carpeta bin de la

solución. Inmediatamente, podemos comprobar cómo arranca la aplicación, mostrando por el log las incidencias

que ocurran de acuerdo a su configuración.

Figura 6-5. Log de ejecución, en modo Debug, de DDA en la Raspberry

De igual forma, los distintos nodos de Kafka indican por consola que la Raspberry está activa y enviando datos:

Page 149: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

149

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

149

Figura 6-6. Log de un Broker Kafka

Con lo anterior ya se están recopilando datos, que se envían al clúster, para que puedan ser recibidos por otros

módulos de este proyecto o de terceros. Para comprobar que la comunicación mediante Kafka es correcta, vamos

a arrancar los otros dos componentes que conforman la aplicación.

Primero se inicia la aplicación SAVER, ejecutando el fichero jar correspondiente en cualquier máquina

Windows o Linux.

Figura 6-7. Log de SAVER

Comprobamos que la aplicación arranca correctamente e introduce datos procedentes de la Raspberry en la tabla

CONSTANT_INFO de la base de datos, aplicando el filtro temporal que está actualmente indicado la tabla de

parámetros (5 minutos).

Figura 6-8. Tabla CONSTANT_INFO con datos insertados por SAVER

Page 150: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Validación

150

150

Para terminar, arrancamos la aplicación Chart y comprobamos que podemos visualizar la información

biomédica recuperada por DDA y la Raspberry a tiempo real.

Figura 6-9. Ejecución de Chart, en la que podemos ver datos (simulados) a tiempo real

Las operaciones realizadas hasta ahora abarcan un ciclo completo de funcionamiento del conjunto de

aplicaciones software y componentes hardware que componen este proyecto.

Resumen de la validación

A partir de lo expuesto en el presente capítulo se puede concluir que se ha creado una solución completamente

funcional que satisface no solo la necesidad de recuperación de las constantes clínicas de los pacientes medidas

con biodispositivos, sino que también abarca la centralización y puesta a disposición de dicha información a

aplicaciones propias del proyecto o de terceros. Por tanto, la primera conclusión no puede ser más positiva, a la

espera de abordar con más detalle este punto, junto a las líneas futuras de mejora, en el último capítulo.

Page 151: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

151

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

151

7 PLANIFICACIÓN

levar a cabo un proyecto como el presentado en esta memoria implica trabajar con numerosos frentes y

una amplia variedad de tecnologías distintas. Aunque es sencillo dividir todos los módulos y componentes

(tanto hardware como software) que conforman el proyecto en tres sectores o categorías (integración con

biodispositivos, almacenamiento / intercambio y visualización de la información clínica) no conviene olvidarse

que el núcleo central es la comunicación con los biodispositivos para recuperar las constantes médicas del

paciente. Esta tarea es, sin duda, la más compleja de cuantas abarca el proyecto, pues implica una importante

labor de documentación, investigación, desarrollo y pruebas. Parece evidente entender que una planificación

adecuada del proyecto debe dimensionar las distintas partes del mismo de acuerdo a su complejidad, no

escatimando en recursos para el análisis y estudio inicial. En todo proyecto de innovación partir de una base

adecuada es fundamental: cometer cualquier error de enfoque o análisis puede provocar que el trabajo realizado

no llegue nunca a buen puerto. Es por estos motivos por los que se ha apostado decisivamente por dotar de

mayor importancia a la fase de pre desarrollo y a todo aquello relacionado con la integración con biodispositivos

en la planificación del proyecto realizada, la cual pasaremos a comentar a continuación.

Fases de la planificación

Para abordar la planificación del proyecto vamos a dividir todas las tareas que se deben realizar / se han realizado

en seis grupos o fases:

Planteamiento del proyecto: primera fase en la que se define el proyecto a realizar, estableciendo una propuesta

concreta y elaborando los objetivos a cumplir. La mayor parte del tiempo dedicado a esta fase se emplea en

documentarse adecuadamente acerca del mundo de la IoT (Internet of Things) aplicado a la medicina,

recuperando la información necesaria como para entender las necesidades actuales del mercado. Solo cuando

esa etapa ha concluido y disponemos de la cantidad de información adecuada tiene sentido plantear una

propuesta completa de aplicación IoMT (Internet of Medical Things) para la monitorización de bioseñales.

Figura 7-1. Planificación Planteamiento

Fase de análisis: es la parte más importante de todo proyecto de innovación. Abarca todos los análisis y estudios

necesarios para determinar qué caminos y estrategias se han de seguir para poder realizar el proyecto planeado,

sí es posible hacerlo.

Figura 7-2. Planificación Fase de análisis

L

Page 152: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Planificación

152

152

Esta fase se inicia con un estudio completo de las alternativas existentes en el mercado y en la comunidad de

código libre al proyecto que se pretende realizar. Como resultado de lo anterior, se deben tratar inmediatamente

después todas las cuestiones relacionadas con los protocolos propietarios, pues ellos determinan el enfoque que

se ha de tomar en el desarrollo posterior. Tras esta fase, dedica a analizar en exclusiva todos los elementos

implicados en la integración, se pasa a estudiar los elementos que solo se tratarán sector del almacenamiento e

intercambio de datos. En ese punto, con toda la información recopilada hasta ahora a disposición de futuros

análisis, es el momento de plantear cómo serán las aplicaciones software que se van a desarrollar en este proyecto

y que deberán relacionarse con los elementos vistos hasta ahora.

Prueba de concepto: en este proyecto se ha denominado como pre desarrollo o prueba de concepto a una fase

intermedia entre el análisis y el desarrollo en sí. En ella se deben poner en práctica las ideas planteadas durante

los estudios y análisis ya realizados para comprobar que el desarrollo del proyecto es posible. Esta tarea incluye

la realización de un primer prototipo de DDA (Device Data Acquisition) que simplemente pruebe que es posible

establecer la comunicación con los biodispositivos y acceder a la información medida por los mismos. Para ello

se han dedicado varios días a configurar adecuadamente el hardware de integración, algo que abarca instalar el

sistema operativo, drivers, máquina virtual de Java, etc. La fase concluye satisfactoriamente con la realización

de la prueba.

Figura 7-3. Planificación Prueba de concepto

Desarrollo: es la fase central del proyecto, en la que se implementa la solución planeada para cumplir los

objetivos marcados. Dada la complejidad y diversidad de elementos implicados en este proyecto se ha dividido

en dos: arquitectura, que trata la instalación, configuración y parametrización de componentes como la base de

datos o el clúster de servidores de colas de mensajes, y el desarrollo de las aplicaciones en sí.

Figura 7-4. Planificación Desarrollo I

La primera parte del desarrollo se centra en diseñar la arquitectura del proyecto, las bases sobre las que construir

las aplicaciones software que necesitamos para satisfacer los objetivos que nos hemos marcado. Esto implica en

primer lugar tener claro cómo se van a relacionar todos y cada uno de los elementos que intervendrán en el

proyecto. Con esto sobre la mesa hay que dedicarse a la tarea de instalar y configurar la base de datos, lanzar los

scripts necesarios para parametrizarla convenientemente; así como instalar y preparar los nodos Zookeeper y

Brokers de Kafka. Como última etapa del diseño de la arquitectura se trata la estructura básica que deberá tener

el software, separando adecuadamente los proyectos para apostar por una modularización adecuada.

Page 153: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

153

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

153

Figura 7-5. Planificación Desarrollo II

A esta fase se llega habiendo planteado ya los proyectos que compondrán nuestro software. En este punto se

tienen ya claros qué proyectos serán librerías, cuales aplicaciones y cuales meros proyectos Maven que nos

sirvan para agrupar otros módulos, dependencias y lógicas de construcción comunes. Como se observa, esta es

la fase que más tiempo requiere con diferencia, pues implica plasmar sobre el código todas las ideas planteadas

hasta el momento. El orden en el que se abordan los componentes del software se basa en la idea de construir

primero las bases (los proyectos denominados core), para ir, poco a poco, trabajando sobre ellas para desarrollar

las librerías más complejas. Como ya ocurría en otras etapas, existen momentos de solapamiento, pues la enorme

relación entre todos ellos ha provocado que se descubrieran errores de código o incluso de planteamiento en

algunos módulos al empezar el desarrollo de otros relacionados. Antes de comentar la fase final es importante

destacar que toda etapa incluye la realización de pruebas unitarias.

Postdesarrollo: fase de validación, pruebas, correcciones y realización de una memoria que permita plasmar

todo lo realizado para este proyecto.

Figura 7-6. Planificación Postdesarrollo

La fase final del proyecto se inicia con una etapa de pruebas integradas, en las que se mezclan todos y cada uno

de los componentes hardware y software que componen el proyecto para comprobar que no existen errores en

el código diseñado. De igual forma, se buscan y abordan los posibles puntos de mejora y optimización en la

solución realziada, de cara a generar la primera versión estable del proyecto. La primera versión estable del

proyecto pasa por una etapa de validación, en la que se comprueba qué objetivos inicales se han cumplido, cuales

no y bajo qué argumentos. Tras esto, solo queda la redacción de la presente memoria que de cuerpo y documente

adecuadamente todo el trabajo realizado.

Resumen de la planificación

Durante algo más de siete meses se ha planteado, analizado, desarrollado, probado y documentado

adecuadamente el proyecto “Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos

biomédicos”. Se ha partido siempre de la necesidad de satisfacer los requisitos u objetivos iniciales marcados en

el planteamiento del proyecto, siendo tarea del próximo capitulo estudiar el estado de los objetivos una vez

cumplida la planificación aquí comentada.

Page 154: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Planificación

154

154

Page 155: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

155

Desarrollo de aplicación IoMT sobre Raspberry Pi para monitorización de datos biomédicos

155

8 CONCLUSIONES Y LÍNEAS FUTURAS

lo largo de esta memoria se ha detallado el proyecto realizado: un conjunto de aplicaciones informáticas

programadas en Java y centradas en la información biomédica del paciente. En torno a estos datos,

recuperados mediante una aplicación que corre sobre una Raspberry Pi, se ha diseñado una arquitectura

robusta, permitiendo construir sobre estas bases otras aplicaciones o módulos para la suite. Para ello, se ha optado

por una gran modularización, dividiendo las distintas funcionalidades en pequeños proyectos que puedan ser

empleados por aplicaciones actuales o futuras con facilidad y evitando duplicar desarrollos. Desde el principio

se ha trabajado teniendo en mente una idea clara: no se está diseñado una aplicación, sino una arquitectura, una

suite sobre la que sea posible construir el mayor número posible de proyectos diferentes. En este camino, ha sido

imprescindible apoyarse en tecnologías consolidadas (Maven, Oracle Database, JPA + Hibernate) pero también

se ha apostado por herramientas en fase de desarrollo temprano, algo ineludible al tratarse de un proyecto tan

enfocado a la innovación. La necesidad de dar una solución seria y realista a la cuestión del almacenamiento e

intercambio de las variables clínicas de los pacientes ha requerido el diseño de un clúster propio de servidores

de intercambio de mensajes, apoyado sobre la nueva (y cada vez más popular) herramienta de Apache, Kafka.

Esta decisión no solo ha dotado de más enjundia al proyecto, permitiéndole abarcar algunos aspectos más

alejados de la programación pura, sino que también ha sido vital para cumplir con la condición base del proyecto,

garantizando una arquitectura realmente preparada para crecer y abarcar nuevos productos. Junto a todo esto, y

para ofrecer un conjunto de programas reales, con capacidad de competir en el mundo real, se ha diseñado una

pequeña base de datos, cerrando el círculo que nos permite hablar de una verdadera suite de aplicaciones. Esto

se ha llevado hasta el extremo de diseñar una pequeña (y simple) aplicación visual que permitiera mostrar a los

interesados las interesantes aplicaciones prácticas que este proyecto puede tener en la vida real y la facilidad con

la que podrían extenderse sus funcionalidades gracias a un planteamiento modular.

Por otra parte, no se ha abordado las implementaciones de los protocolos propietarios empleados en la

comunicación con los biodispositivos. Esto hubiera implicado que el proyecto se centrara solo en ese proyecto,

provocando que se quedaran fueran otros aspectos más interesantes como podrían haber sido la creación de una

arquitectura multiaplicación o la construcción de un sistema de intercambio de información mediante un clúster

de servidores. En el capítulo dedicado al estado del arte, a las posibilidades punteras que existen en la comunidad

y el mercado de ha hablado de aplicaciones de código abierto que implementan alguno de estos protocolos,

pudiendo servir al lector interesado de punto de acceso a información más profunda sobre este tipo de protocolos.

Conclusiones

Con todo lo comentado anteriormente tenemos información más que suficiente para comprobar el estado de los

objetivos que nos marcamos al inicio del proyecto:

- La solución aquí diseñada gira entorno a las bioseñales de los pacientes, recuperadas a través de una

placa hardware (Raspberry Pi 2) y un software específico.

- La utilización de Kafka permite que todas las aplicaciones que así lo deseen puedan acceder fácilmente

a los datos, sin más que subscribirse al clúster. Esto ha quedado probado con los módulos SAVER y

CHART, que se comportan como aplicaciones independientes completamente separadas de DDA.

- Como consecuencia de lo anterior, las constantes clínicas del paciente se convierten en fuente de

información para un conjunto ampliable de aplicaciones del proyecto, o incluso de terceros si se

establece un protocolo para su conexión con nuestro clúster de colas de mensajes.

- Para ejemplificar que la información recuperada se realiza correctamente y se centraliza, estando

disponible en tiempo real para cualquiera que quiera acceder a ella se ha diseñado el módulo CHART.

- El clúster de servidores gestionado por Kafka es lo suficientemente versátil como para no limitar las

aplicaciones que quieran acceder a la información. Esto sí ocurriría si solo hubiéramos apostado por

una base de datos, ya que las bases de datos SQL no se comportan adecuadamente como fuente de

información de sistemas big data. Con la arquitectura diseñada no se limita la posible implantación de

A

Page 156: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

Conclusiones y líneas futuras

156

156

un sistema big data sobre el proyecto diseñado, requisito que se había marcado antes del inicio del

proyecto.

- Además, se ha estudiado la posibilidad de permitir a alguna aplicación (propia o de terceros) modificar

el comportamiento de los biodispositivos. A pesar de haber optado por implementar los protocolos

propietarios que fueran necesarios, más proclives a esta funcionalidad que el estándar HL7 (Health

Level Seven), no se ha encontrado una cantidad mínima de protocolos que soporten esta característica

ni un conjunto de acciones comunes o habituales. Por tanto, este objetivo se ha descartado.

En resumen, el desarrollo del proyecto puede considerarse ampliamente satisfactorio, al haberse cumplido la

práctica totalidad de los objetivos marcados durante el planteamiento del mismo. La solución desarrollada cubre

la recuperación de la información biomédica de los pacientes medida mediante biodispositivos, siendo capaz de

centralizarla y ponerla a disposición de cualquier aplicación que pretenda visualizarla, explotarla, etc.

Líneas futuras

Enfocados a la creación de una aplicación robusta, han aparecido a lo largo de esta memoria distintas

funcionalidades interesantes que no han podido ser abordadas en este proyecto, algo lógico al tratar con un sector

tan extenso y complejo como el sanitario. Estas nuevas características, posibles nuevos proyectos a construir

sobre las bases aquí montadas, abarcan desde pequeños cambios o mejoras en el planteamiento hasta ideas que

implicarían nuevas aplicaciones, generalmente de gran complejidad.

En la primera categoría surgen varias posibilidades: realizar un tratamiento adecuado de las unidades en las que

se reciben las variables clínicas (algo que en lo que no se repara en el momento actual) o tener en cuenta las

posibles técnicas empleadas en la medición, algo que condiciona sin atisbo de duda el resultado obtenido.

La segunda categoría abre más posibilidades, las cuales además implican proyectos tan interesantes o más al

aquí comentado. Si se buscara continuar este trabajo hacia una solución implantarle en centros sanitarios reales

sería necesario desarrollar un programa de integración con el estándar HL7, para cubrir tres funciones

tremendamente útiles: recuperar la información de los dispositivos que lo empleen, poder enviar información en

este formato a terceros y emplear los mensajes recibidos como fuente de datos para poblar la base de datos.

Dentro de la misma lógica, aunque yendo un paso más allá, sería necesario construir un visualizador de datos

más potente, desarrollado probablemente en alguna tecnología front-end como Javascript, a ser posible

combinándolo con una aplicación de historia clínica propia u ofreciendo integración con alguna opción de

código libre existente en el mercado. Si pretendemos diseñar una suite de aplicaciones sanitarias en torno a los

datos clínicos del paciente es absurdo plantear que la información recuperada pueda mostrarse totalmente

disociada de otros valores imprescindibles como el diagnóstico del paciente, los resultados de sus últimos

estudios, los informes realizados por los distintos profesionales sanitarios que lo han atenido, etc. Hasta ahora

se han comentado mejores destinadas a obtener más información del paciente y a ofrecerla de la forma más

completa e integrada posible, pero no se ha seguido ahondando en las posibilidades que nos ofrece tener

informatizadas y centralizadas las constantes clínicas de muchos pacientes. No cuesta mucho imaginar un

escenario en el que toda esta información pueda ser explotada, tanto como fuente para estudios de profesionales

sanitarios como por un motor de big data que permita sacar estadísticas, reconocer patrones o incluso facilitar

la labor a los facultativos a partir de todo lo anterior. Esta última posibilidad se ve además reforzada por el amplio

uso de Kafka como fuente de datos para productos de tratamiento masivo de datos.

Page 157: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

REFERENCIAS

[1] Health Level Seven International, «HL7,» [En línea]. Available: http://www.hl7.org/. [Último acceso:

Enero 2016].

[2] IHE International, «Integrating the Healthcare Enterprise,» [En línea]. Available: http://www.ihe.net/.

[Último acceso: Enero 2016].

[3] Capsule Tech, Inc, «SmartLinx,» 06 2016. [En línea]. Available: http://www.capsuletech.com/integration.

[4] Capsule Tech Inc, «SmartLinx Axon,» [En línea]. Available: http://webinfo.capsuletech.com/smartlinx-

axon-product-brief. [Último acceso: 06 2016].

[5] Capsule Tech, Inc., «SmartLinx Vitals Stream,» [En línea]. Available:

http://webinfo.capsuletech.com/smartlinx-vitals-stream-product-brief. [Último acceso: 06 2016].

[6] Capsule Tech, Inc, «SmartLinx Client,» [En línea]. Available: http://webinfo.capsuletech.com/medical-

device-integration-smartlinx-client. [Último acceso: 06 2016].

[7] Capsule Tech, Inc, «SmartLinx IQ,» [En línea]. Available: http://www.capsuletech.com/medical-device-

data-analytics. [Último acceso: 06 2016].

[8] Piscis Clinical Solutions, «Hawkeye,» [En línea]. Available: http://www.picis.com/medical-device-

integration.html. [Último acceso: 06 2016].

[9] The OpenICE Team, «OpenICE,» [En línea]. Available: https://www.openice.info. [Último acceso: 05

2016].

[10] MD PnP Program, «MD PnP,» [En línea]. Available: http://www.mdpnp.org/. [Último acceso: 05 2016].

[11] ASTM International, «ASTM final F-2761 - ICE Standard,» [En línea]. Available:

http://www.mdpnp.org/uploads/F2761_completed_committee_draft.pdf. [Último acceso: 06 2016].

[12] Real-Time Innovations, «RTI DDS,» [En línea]. Available: https://www.rti.com/products/dds/. [Último

acceso: 06 2016].

[13] RASPBERRY PI FOUNDATION, «Raspberry Pi 2,» [En línea]. Available:

https://www.raspberrypi.org/products/raspberry-pi-2-model-b/. [Último acceso: 01 2016].

[14] JAGUAR ELECTRONIC H.K. CO. Ltd , «Jaguar One,» [En línea]. Available:

http://www.jaguarboard.org/index.php/products/buy/jaguarboard/207/jaguarboard-

detail.html#specification. [Último acceso: 05 2016].

[15] Shenzhen Xunlong Software CO.,Limited, «Orange Pi One,» [En línea]. Available:

http://www.orangepi.org/orangepione/. [Último acceso: 05 2016].

[16] Hardkernel co., Ltd., «ODROID-C1+,» [En línea]. Available:

http://www.hardkernel.com/main/products/prdt_info.php?g_code=G143703355573. [Último acceso: 05

Page 158: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

2016].

[17] SolidRun Ltd., «HummingBoard,» [En línea]. Available: https://www.solid-run.com/freescale-imx6-

family/hummingboard/. [Último acceso: 05 2016].

[18] BeagleBoard.org Foundation, «BeagleBoard Black,» [En línea]. Available: https://beagleboard.org/black.

[Último acceso: 05 2016].

[19] CubieBoard, «CubieBoard5,» [En línea]. Available: http://cubieboard.org/model/. [Último acceso: 05

2016].

[20] LinkSprite, «pcDuino4,» [En línea]. Available: http://www.linksprite.com/linksprite-pcduino/. [Último

acceso: 05 2016].

[21] The Raspberry Foundation, «Raspbian,» [En línea]. Available: https://www.raspbian.org/. [Último

acceso: 05 2016].

[22] Canonical Ltd, «Ubuntu MATE,» [En línea]. Available: https://ubuntu-mate.org/raspberry-pi/. [Último

acceso: 06 2016].

[23] Canonical Ltd, «Snappy Ubuntu Core for Raspberry Pi,» [En línea]. Available:

https://developer.ubuntu.com/en/snappy/start/#snappy-raspi2. [Último acceso: 05 2016].

[24] Microsoft Corporation, «Windows 10 IoT Core,» [En línea]. Available: http://ms-iot.github.io/content/en-

US/Downloads.htm. [Último acceso: 05 2016].

[25] RISC OS Open Limited, «RISC OS for the Raspberry Pi,» [En línea]. Available:

https://www.riscosopen.org/content/downloads/raspberry-pi. [Último acceso: 06 2016].

[26] The Apache Software Foundation, «Apache Kafka,» [En línea]. Available: http://kafka.apache.org/.

[Último acceso: 05 2016].

[27] The Apache Software Foundation!, «Kafka Log Compaction,» [En línea]. Available:

https://cwiki.apache.org/confluence/display/KAFKA/Log+Compaction. [Último acceso: 06 2016].

[28] Pivotal Software, Inc, «RabbitMQ,» [En línea]. Available: https://www.rabbitmq.com/. [Último acceso:

06 2016].

[29] solid IT gmbh, «DB-Engines Ranking,» [En línea]. Available: http://db-engines.com/en/ranking. [Último

acceso: 06 2016].

[30] Oracle Corporation, «Oracle Database,» [En línea]. Available:

https://www.oracle.com/es/database/index.html. [Último acceso: 06 2016].

[31] Oracle Corporation, «MySQL,» [En línea]. Available: http://www.mysql.com/. [Último acceso: 06 2016].

[32] Microsoft Corporation, «SQL Server,» [En línea]. Available: https://www.microsoft.com/es-es/server-

cloud/products/sql-server/. [Último acceso: 06 2016].

[33] Oracle Corporation, «SQL Developer,» [En línea]. Available:

http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html. [Último acceso:

06 2016].

Page 159: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

[34] Dell, Inc, «TOAD,» [En línea]. Available: http://www.toadworld.com/. [Último acceso: 05 2016].

[35] Oracle Corporation, «Java,» [En línea]. Available: https://www.java.com/. [Último acceso: 07 2015].

[36] Python Software Foundation, «Python,» [En línea]. Available: https://www.python.org/. [Último acceso:

06 2016].

[37] Red Hat, Inc., «Hibernate,» [En línea]. Available: http://www.hibernate.org/. [Último acceso: 06 2016].

[38] Eclipse Foundation, «EclipseLinik,» [En línea]. Available: http://www.eclipse.org/eclipselink/. [Último

acceso: 06 2016].

[39] Apache Software Foundation, «OpenJPA,» [En línea]. Available: http://openjpa.apache.org/. [Último

acceso: 06 2016].

[40] The Querydsl Team, Mysema Oy, «QueryDSL,» [En línea]. Available: http://www.querydsl.com/.

[Último acceso: 06 2016].

[41] Apache Software Foundation, «iBatis,» [En línea]. Available: http://ibatis.apache.org/. [Último acceso: 06

2016].

[42] Apache Software Foundation, «Ant,» [En línea]. Available: http://ant.apache.org/. [Último acceso: 06

2016].

[43] Apache Software Foundation, «Maven,» [En línea]. Available: https://maven.apache.org/. [Último acceso:

06 2016].

[44] Heavybit, Inc, «Gradle,» [En línea]. Available: http://www.gradle.org/. [Último acceso: 06 2016].

[45] ZeroTurnaround, «Java Tools & Technologies Landscape,» 2014.

[46] Eclipse Foundation, «Eclipse,» [En línea]. Available: https://eclipse.org. [Último acceso: 07 2015].

[47] Eclipse Foundation, «SWT,» [En línea]. Available: https://wiki.eclipse.org/SWT. [Último acceso: 07

2015].

[48] Eclipse Foundation, «JFace,» [En línea]. Available: https://wiki.eclipse.org/JFace. [Último acceso: 07

2015].

[49] Eclipse Foundation, «JDT,» [En línea]. Available: https://wiki.eclipse.org/JDT. [Último acceso: 07 2015].

[50] JetBrains, «IntelliJ IDEA,» [En línea]. Available: https://www.jetbrains.com/idea/. [Último acceso: 07

2015].

[51] InfoWorld, «Top Java programming tools,» [En línea]. Available:

http://www.infoworld.com/article/2683534/development-environments/infoworld-review--top-java-

programming-tools.html. [Último acceso: 07 2015].

[52] Oracle Corporation, [En línea]. Available: https://netbeans.org/. [Último acceso: 07 2015].

[53] Oracle Corporation, «JDeveloper,» [En línea]. Available: http://www.oracle.com/technetwork/developer-

tools/jdev/overview/index-094652.html. [Último acceso: 07 2015].

Page 160: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

[54] The Apache Software Foundation. , «Hadoop,» [En línea]. Available: http://hadoop.apache.org/. [Último

acceso: 05 2016].

[55] Health Level Seven Inc, «Especificación MLLP,» [En línea]. Available:

http://www.hl7.org/documentcenter/public_temp_73F3EA42-1C23-BA17-

0C011D0AAF40F217/wg/inm/mllp_transport_specification.PDF. [Último acceso: 06 2016].

[56] Oracle Corporation, «Oracle FAQ - Tablespaces,» [En línea]. Available:

http://www.orafaq.com/wiki/Tablespace#Default_tablespaces. [Último acceso: 02 2016].

[57] Oracle Corporation, «Oracle FAQ - Profiles,» [En línea]. Available:

http://www.orafaq.com/wiki/Profiles_and_password_management. [Último acceso: 03 2016].

[58] Oracle Corporation, «Oracle Help Center - Database Link,» 03 2016. [En línea]. Available:

https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5005.htm.

[59] Oracle Corporation, «Oracle Healp Center - Sequences,» [En línea]. Available:

https://docs.oracle.com/cd/B28359_01/server.111/b28310/views002.htm. [Último acceso: 03 2016].

[60] Oracle Corporation, «Oracle Help Center - Indexes,» [En línea]. Available:

https://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CNCPT721. [Último acceso: 03

2016].

[61] Oracle Corporation, «Ask Tom - Indexes on foreign keys,» [En línea]. Available:

https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:292016138754. [Último

acceso: 03 2016].

[62] Oracle Corporation, «Oracle Help Center - Grant,» [En línea]. Available:

https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9013.htm. [Último acceso: 03

2016].

[63] The Apache Software Foundation, «Kafka Download,» [En línea]. Available:

http://kafka.apache.org/downloads.html. [Último acceso: 05 2016].

[64] The Apache Foundation, «Zookeeper Configuration,» [En línea]. Available:

https://zookeeper.apache.org/doc/r3.3.2/zookeeperAdmin.html#sc_configuration. [Último acceso: 05

2016].

[65] The Apache Foundation, «Apache Kafka: Broker Configuration,» [En línea]. Available:

http://kafka.apache.org/documentation.html#brokerconfigs. [Último acceso: 05 2016].

[66] The Apache Foundation, «Topic Configuration,» [En línea]. Available:

http://kafka.apache.org/documentation.html#topic-config. [Último acceso: 05 2016].

[67] The Apache Software Foundation, «Maven Central Repository,» [En línea]. Available:

https://repo1.maven.org/maven2/. [Último acceso: 05 2016].

[68] Oracle Corporation, «DAO,» [En línea]. Available:

http://www.oracle.com/technetwork/java/dataaccessobject-138824.html. [Último acceso: 05 2016].

[69] Red Hat, Inc., «Hibernate CacheConcurrencyStrategy,» [En línea]. Available:

https://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/cache/ReadWriteCache.html. [Último acceso:

05 2016].

Page 161: Proyecto Fin de Carrerabibing.us.es/proyectos/abreproy/12341/fichero/PFC+Alfredo+E+Sáez... · logo de toad ... tablespace iniciales de una base de datos oracle xe 11g r2.....58 figura

[70] The Apache Foundation, «JPA Transaction Type,» [En línea]. Available: http://tomee.apache.org/jpa-

concepts.html. [Último acceso: 05 2016].